Compare commits

..

622 Commits

Author SHA1 Message Date
minjaesong
aef601e9b8 some classes in sprite assembler is now internal 2019-01-22 03:51:18 +09:00
minjaesong
88db71f780 ingame will only render visible actor 2019-01-22 03:50:35 +09:00
minjaesong
ded9cb1a10 instead of dealing with delta, we'll just update multiple times, THIS TIME IN CORRECT WAY
(because it really works :p)
2019-01-22 02:59:22 +09:00
minjaesong
afba402c6c the entire game will use new smooth delta 2019-01-21 05:22:49 +09:00
minjaesong
b027f662ce forgot to comment out the debug print 2019-01-21 01:44:19 +09:00
minjaesong
c60b0b42ad I'll settle with 'Kalman filter with adaptive reset' 2019-01-20 22:50:22 +09:00
minjaesong
40580a57cd smooth delta uses framerate-averaged instead of raw delta; stupid but works :\ 2019-01-20 21:46:11 +09:00
minjaesong
09b4a34d14 trying to get smooth delta (because fuck you GDX) 2019-01-20 20:13:56 +09:00
minjaesong
613b69a20f issue #16: jump height is "close enough", friction and walk/stop needs fix 2019-01-20 07:03:23 +09:00
minjaesong
5738418f39 the simplest case of noclip=true 2019-01-20 06:43:59 +09:00
minjaesong
10cf3fb007 reverting changes on ActorWBMovable: gotta make new branch 2019-01-20 06:39:01 +09:00
minjaesong
be20fd8328 removing default batch on blendxxx() funs 2019-01-20 03:09:23 +09:00
minjaesong
d1a2e6b8f2 issue #16: walking fixed, jump not 2019-01-19 16:44:59 +09:00
minjaesong
5bf8b6cad7 on-the-fly sprite assembly WIP 2019-01-19 04:34:50 +09:00
minjaesong
2c59d60a15 spriteassembler: oob bodyparts will clip, as they should be
...to hide unwanted bodyparts in the skeleton
2019-01-18 18:59:05 +09:00
minjaesong
68df2a223e parallel light always does this random noise 2019-01-18 04:24:14 +09:00
minjaesong
784a6a13e3 f 2019-01-18 03:14:37 +09:00
minjaesong
9040ff2c87 light: seems like the problem is the ram access time 2019-01-17 21:08:50 +09:00
minjaesong
c4510f9c3b still working on light, no improvements perf-wise 2019-01-17 18:28:43 +09:00
minjaesong
ebce90aa4b light: lantern lookup should be faster 2019-01-17 16:06:00 +09:00
minjaesong
25d0e195c3 all my confusions were derived from not wiping old map; fixed things accordingly 2019-01-17 15:12:52 +09:00
minjaesong
e209967730 light: slightly improved performance with careful skipping
(hopefully...)
2019-01-17 06:52:04 +09:00
minjaesong
f689e1de99 added some features and comments for coding convenience 2019-01-17 05:32:52 +09:00
minjaesong
6e33dbdfaf ui itemlist scrolls with wheel 2019-01-16 01:37:44 +09:00
minjaesong
b10e8aa777 lol 2019-01-16 01:23:23 +09:00
minjaesong
6a343ae382 taking screenshot 2019-01-15 16:10:40 +09:00
minjaesong
17b6738308 fixing a new GDX version colouring bug 2019-01-15 06:05:43 +09:00
minjaesong
078cdfefa4 See Github issue #15 2019-01-15 05:50:36 +09:00
minjaesong
81f9c92e48 adding test code to export fboRGB 2019-01-15 03:02:40 +09:00
minjaesong
8237188dc3 a setup to mitigate directional artefacts in light 2019-01-15 01:18:54 +09:00
minjaesong
7b120020e4 map data format adds world generator version and fluids 2019-01-14 23:15:01 +09:00
minjaesong
f4cd4f49b2 width fixes in UI 2019-01-14 02:46:23 +09:00
minjaesong
09b039c62f trying to work on issue #15 and I'm stumped 2019-01-13 23:51:04 +09:00
minjaesong
ff8791f48a Gzipping PSDs; every art must be alpha premultiplied; added converter batch 2019-01-13 21:23:01 +09:00
minjaesong
43bc99548c copyright update 2019-01-13 04:42:40 +09:00
minjaesong
380a14492f grey box issue fixed (github issue #13) 2019-01-13 04:06:53 +09:00
minjaesong
692e08fc1e UI: quickslot register; IngameController: quickslot selection using wheel
This closes github issue #14
2019-01-13 03:02:57 +09:00
minjaesong
33ad8520f8 quickslot selections are controlled by the ingame rather than the 'bar UI' 2019-01-13 02:17:49 +09:00
minjaesong
9aa8eb395d fixed various quirks and removed dirty hacks on quickslot bar/pie 2019-01-12 22:56:48 +09:00
minjaesong
34d50b8d70 fixed wrong coords 2019-01-12 00:59:15 +09:00
minjaesong
07e8e21eae lightmap edge-case fixed
when camera.x is in -15..-1, all thing shifts to left
2019-01-11 04:44:52 +09:00
minjaesong
525273e37f TerrarumSansBitmap update 2019-01-11 03:07:10 +09:00
minjaesong
34a8113d53 tooltip positioning should work again 2019-01-11 03:06:45 +09:00
minjaesong
4f8cf2cb02 csv sort by ID (hacky?) 2019-01-09 15:15:26 +09:00
minjaesong
8a0abf22da circular array is fixed and tested 2019-01-09 05:43:56 +09:00
minjaesong
9140d6d8b0 prolonged alpha blending issue seemingly fixed?
at least it's partially fixed...
2019-01-07 17:34:47 +09:00
minjaesong
9133f05b5e sprite tool exports "formatted" TGA
meaning if alpha is zero, RGB is also zero
2019-01-07 17:11:43 +09:00
minjaesong
790d16b85d gradle tasks for two new apps 2019-01-07 14:19:15 +09:00
minjaesong
adf60e357e sprite assembler can produce intended output 2019-01-07 05:01:28 +09:00
minjaesong
f81db26e60 ALL kwd in transform implemented 2019-01-07 04:24:13 +09:00
minjaesong
655eccbe19 first successful sprite assembly
ALL kwd still not implemented
2019-01-07 04:13:38 +09:00
minjaesong
5b31b4768f screw AWT, we'll use GDX for sprite preview 2019-01-07 00:35:20 +09:00
minjaesong
425cb82133 TODO added: when the transform joint is "ALL" 2019-01-06 22:45:51 +09:00
minjaesong
344e4ebdab adproperties now has transforms list; assembler can make transformed skeleton
new fun: LinearSearch(By)
2019-01-06 22:43:50 +09:00
minjaesong
32afb2e2e5 updated the psd with the actual assembly 2019-01-06 19:28:06 +09:00
minjaesong
3100a093fd animation metadata now contains discovered frame count
...in hacky way
2019-01-06 15:13:17 +09:00
minjaesong
fb06200d26 ADProperties now properly stores parsed mumbojumbo 2019-01-06 04:19:21 +09:00
minjaesong
1696cc8601 fixed a bug properties view won't show scroll bars 2019-01-06 03:25:40 +09:00
minjaesong
4072b9fb09 adproperties now hold filename-related info 2019-01-06 02:57:49 +09:00
minjaesong
36160a6579 sprite assembler app can read and disp ADL
garbage code not properly handled
2019-01-06 02:06:51 +09:00
minjaesong
4986d570a0 sprite assembler test assets 2019-01-06 00:30:43 +09:00
minjaesong
1965eabaa3 joints in skeleton are ordered according to drawing order, PSD also updated 2019-01-05 16:53:21 +09:00
minjaesong
90784afd48 TIL you can go multiline on Java .properties 2019-01-05 16:33:40 +09:00
minjaesong
258364f37e skeleton datasets from sprite_joints.psd 2019-01-05 16:23:19 +09:00
minjaesong
f99531c9d4 testing how joints of sprites should look like
humanoid only
2019-01-05 04:53:22 +09:00
minjaesong
74cfc05fba parsing ADL
a road to auto-gen'd spriteanimation spritesheet
2019-01-05 02:19:56 +09:00
minjaesong
15868a5a2d forgot to update tga file 2019-01-04 21:19:11 +09:00
minjaesong
3abca8989a somewhat successful walk/idle anim impl 2019-01-04 17:44:22 +09:00
minjaesong
ae9a1ebcb4 write to the actual file 2019-01-03 13:02:54 +09:00
Minjae Song
18a05ace64 new csv and it asks number of lines to init 2019-01-02 22:41:20 +09:00
Minjae Song
3b2c38cf0b csv reader can read file, stringify (not real save) and read the save itself wrote 2019-01-02 22:25:44 +09:00
Minjae Song
6ecbb672fb csv editor read file with imperfections 2019-01-02 22:03:52 +09:00
Minjae Song
30954d239a CSV editor: test export of spreadsheet
Seems working?
2019-01-02 10:55:32 +09:00
Minjae Song
edd15a4f79 watch is semitransparent when EL is off 2019-01-01 22:29:18 +09:00
Minjae Song
db110d1ca4 csv editor wip 2019-01-01 21:00:33 +09:00
Minjae Song
e3e97000a7 New year's first commit
is just a comment
2019-01-01 00:10:37 +09:00
Minjae Song
ce2d9a271a slow descend of the platform fixed 2018-12-31 21:34:50 +09:00
Minjae Song
222aef7e3d more screwing around and commenting 2018-12-31 00:50:44 +09:00
Minjae Song
08bbdaf70b platform sorta works as intended 2018-12-31 00:00:47 +09:00
Minjae Song
7300b05442 removing useless list "affectingTiles" 2018-12-30 23:41:57 +09:00
Minjae Song
cd13e04658 platform going down with Down button on keeb 2018-12-30 20:17:28 +09:00
Minjae Song
48de42d98b jumping up to the platform working 2018-12-30 20:02:24 +09:00
Minjae Song
35c0c45500 WIP platforms, at least "should I collide with this?" is one single function 2018-12-30 19:50:22 +09:00
Minjae Song
6c01aa9b0b removed FLUID prop from the blocks 2018-12-29 21:04:27 +09:00
Minjae Song
2335312081 WIP removing fluid marker block
see "work_files/todo_platforms.png"
2018-12-29 17:04:46 +09:00
Minjae Song
abfd9b68fc detailed impl of fixtures WIP 2018-12-29 04:11:26 +09:00
Minjae Song
500c72ebc9 Summary
Description
2018-12-26 19:26:08 +09:00
Minjae Song
00fc4f1b8c reduced boot time by not using proper wall tex; darker wall draw 2018-12-25 16:28:38 +09:00
Minjae Song
98755fab61 still cleaning up
Making wall item textures takes SO long
2018-12-25 15:39:01 +09:00
Minjae Song
09d8702089 have been forgetting to update fullscreenquad on resize :\ 2018-12-25 05:34:59 +09:00
Minjae Song
9080127d38 when it's not dev build, title bar shows less info
they take some processing time
2018-12-25 01:58:18 +09:00
Minjae Song
d7664c7f46 moved things a lot just so that splash screen shows up WHILE things load 2018-12-25 01:39:22 +09:00
Minjae Song
47da7d5b81 Added JoiseDoc 2018-12-24 22:49:08 +09:00
Minjae Song
ef3690765d simplified fluid render 2018-12-23 02:13:41 +09:00
Minjae Song
33c333e7fa new version number
eheheheh
2018-12-22 02:10:33 +09:00
Minjae Song
10128a20a0 rendering scheme of the world changed, fluids draw as intended
But my idea wasn't very stellar, *sigh*
2018-12-22 02:08:08 +09:00
Minjae Song
764945fc30 prep for fluid exclusive render 2018-12-19 22:23:50 +09:00
Minjae Song
3098c0afd2 fluidmap won't have errenous behaviour at the world edge; tga alpha fix 2018-12-19 01:53:09 +09:00
Minjae Song
101c67a107 water flow works
turns out, var.coerceIn() returns value and does not modify the var
2018-12-18 01:48:38 +09:00
Minjae Song
a1661fbb4e fluid multiplies themselves ?! 2018-12-17 22:39:19 +09:00
Minjae Song
04c5e32ddf test: tiles tex blend according to seasons 2018-12-17 04:30:08 +09:00
Minjae Song
b78d488044 duh 2018-12-16 16:17:05 +09:00
Minjae Song
832e296bc5 rename TARGET_FPS to PHYS_TIME_FRAME; shader to use multiple atlas tex; and things 2018-12-16 15:30:25 +09:00
Minjae Song
46e5860143 at least this fluid sim passes collection assertion codes 2018-12-16 02:55:12 +09:00
Minjae Song
4fa44abd3e bugs on fluid sim, Type is NULL but fill isn't 0/new temporary fluid draw 2018-12-16 02:10:04 +09:00
Minjae Song
191a91cb81 blockingthreadpool test done
not very effective
2018-12-15 14:43:55 +09:00
Minjae Song
388d3d6f2f noise generator: automated test and reporting 2018-12-14 23:19:40 +09:00
Minjae Song
b1b29387e3 new thread pooling strategy and test program WIP 2018-12-14 22:53:25 +09:00
Minjae Song
764edea832 Update ThreadParallel.kt 2018-12-14 15:06:55 +09:00
Minjae Song
16e4067d89 working very crude fluid sim 2018-12-14 00:52:10 +09:00
Minjae Song
05a8f47006 implementing water sim but not actually working 2018-12-13 04:45:09 +09:00
Minjae Song
1f1d6f1eda preparing fluid updater: debug water bucket 2018-12-12 23:29:30 +09:00
Minjae Song
27f79238a1 perhaps missed this from before? 2018-12-12 20:47:06 +09:00
Minjae Song
6d553ea583 replacing water/lava tiles with one fluid marker
actual fluid not implemented
2018-12-12 20:32:13 +09:00
Minjae Song
ad8d3ba210 see page 9 2018-12-12 18:49:18 +09:00
Minjae Song
e441cdf5f0 fluid layer data and fluid sim specifications
See added note FLUID_SIMULATION
2018-12-12 18:39:14 +09:00
Minjae Song
9c3c35067d adjusted items ID range for more static items 2018-12-12 03:00:49 +09:00
Minjae Song
7a60ae0629 support for screen-overlay actors; buildingmaker has light now 2018-12-12 02:52:33 +09:00
Minjae Song
258273fd25 nonprivate lateinits are bitch 2018-12-11 16:39:27 +09:00
Minjae Song
dc502b2f12 Summary 2018-12-11 16:14:11 +09:00
Minjae Song
803e59a0ee Merge remote-tracking branch 'origin/master' 2018-12-11 16:08:41 +09:00
Minjae Song
e31eaf0241 matching blendglow's version with others 2018-12-11 11:06:03 +09:00
Minjae Song
8181bec481 things "look" good enough, should stop here and work on the main game 2018-12-11 04:02:23 +09:00
Minjae Song
7c1d6e6b88 fix: textbuttonlist selector appearance bug, nsmenu not closing its child 2018-12-11 02:22:31 +09:00
Minjae Song
7e7e54eed7 other commit didn't work, duh; this SHOULD fix shit
the other commit: "prev commit didn't work" at 2018-12-09 (16a7d2abe7)
2018-12-10 20:35:54 +09:00
Minjae Song
57c9b7b277 yaml: adding generic parse-as-invokable 2018-12-10 04:15:57 +09:00
Minjae Song
984eb4de00 nsmenu working submenu navigation; new graphics bug discovered 2018-12-10 03:33:08 +09:00
Minjae Song
c4b4bfd2fc UINSMenu is made to show how to code 'UI dragging' 2018-12-09 20:00:52 +09:00
Minjae Song
cf9bce5bac NSMenu WIP 2018-12-09 17:51:17 +09:00
Minjae Song
16a7d2abe7 prev commit didn't work 2018-12-09 17:31:17 +09:00
Minjae Song
a690b46456 textbuttonlist fixed incorrect vertical placement 2018-12-09 17:24:26 +09:00
Minjae Song
b55cd415f2 'the entire screen is shifted!' bug fixed 2018-12-09 13:38:25 +09:00
minjaesong
4c2b73197d NSMenu WIP, but also caught a source of the old bug 2018-12-09 04:40:46 +09:00
minjaesong
1c1ae37f41 moved white box tex to AppLoader; textButton now has alignment option 2018-12-09 04:36:53 +09:00
minjaesong
57fa6de62a making Yaml and BFS of QNDTree work 2018-12-09 01:52:57 +09:00
minjaesong
6f0a923df7 WIP new UI elem 2018-12-08 23:26:01 +09:00
minjaesong
4b04bf3781 replaced a hack that starts random game on title screen 2018-12-08 18:30:10 +09:00
minjaesong
eca0469f32 bringing back onscreen debug info 2018-12-08 05:05:42 +09:00
minjaesong
d588f73ed6 Memory leak alleviated FUCK YEAH? 2018-12-08 04:26:01 +09:00
minjaesong
b40a78b706 Update LightmapRendererNew.kt 2018-12-07 06:15:41 +09:00
minjaesong
93a43899e7 why they are keep resurrecting 2018-12-03 22:37:51 +09:00
minjaesong
155ba9eb56 Update .gitignore 2018-12-03 11:05:35 +09:00
minjaesong
4224d56b25 exit now gracefully calls gdx.app.exit 2018-12-03 00:34:31 +09:00
minjaesong
cc14218dd5 removing kotlin-stdlib.jar again duuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuh 2018-12-03 00:25:01 +09:00
minjaesong
b856829ca9 Merge branch 'gradle-migration-1' 2018-12-02 23:01:25 +09:00
minjaesong
a9bc4f47f8 Update .gitignore 2018-12-02 19:28:38 +09:00
minjaesong
bf9c172206 minor edits 2018-12-02 17:34:01 +09:00
minjaesong
fa86ca2e05 rem external_resource_packs.zip 2018-11-22 19:14:49 +09:00
minjaesong
9cc0a62188 rem workspace.xml 2018-11-22 19:09:48 +09:00
minjaesong
f3b0044d5f fixing one of the new bugs: block duplication artefact on render 2018-11-20 22:16:20 +09:00
minjaesong
f5d36e2c92 physics anomaly at x 0..33? are fixed, other issues (re)introduced
See ActorWBMovable@Line1238
2018-11-20 06:08:21 +09:00
minjaesong
8da80e88a3 Reverting GDX to nightly-20170610
Due to the some fuck rendering issue on certain graphics processors (maybe?)
2018-11-20 04:27:14 +09:00
minjaesong
f21ed3bf0d commiting minor changes cause I need to track down some bugs
- Text on small font goes dark gradually (?)
2018-11-20 04:10:13 +09:00
minjaesong
4d0c772dd8 1dim-ised lightmap 2018-11-16 22:44:54 +09:00
minjaesong
f4f0e59811 lightbufferastex is now properly disposed of
should help with my mem leak probs
2018-11-16 20:42:30 +09:00
minjaesong
d9f576e4dc change in ingame config: useamericanunit -> temperatureunit 2018-11-16 20:37:44 +09:00
minjaesong
091f79c7f8 reconfiguring docs and libs
- Targeting Java 10
- Gdx nightly 20181111 (1.9.9)
2018-11-11 20:13:31 +09:00
minjaesong
8942f352a1 drawing of the tile breakage 2018-11-10 21:09:02 +09:00
minjaesong
1aa90077a4 Can setTitle() cause memleak (right before test commit) 2018-11-08 22:42:27 +09:00
minjaesong
3360ab0dfe starting day of the game is now Spring 1st 2018-11-06 23:49:22 +09:00
minjaesong
4eee5ee2b1 a new watchface to support seasons instead of months 2018-11-06 23:40:36 +09:00
minjaesong
c7c68187eb fixed a NaN bug caused by a zero-width/height hitbox
Also inventory is widened to 10x7 of prev 9x7
2018-11-06 04:02:33 +09:00
minjaesong
5c8cdd3162 new ingame calendar impl
for some reason it runs slower that it should do
2018-10-30 22:47:41 +09:00
minjaesong
73d1a1bdc5 new RNG for everything; Joise update 2018-10-27 00:03:06 +09:00
minjaesong
ee3d98662c read world info 2018-10-09 23:49:14 +09:00
minjaesong
d77b552518 writeworldinfo tested to be working 2018-10-08 18:15:05 +09:00
Minjae Song
5f75288dc7 worldinfo writer 2018-10-08 01:16:29 +09:00
Minjae Song
74d76440ee new outputstream for bytearray64 2018-10-06 01:16:26 +09:00
minjaesong
e072aff897 testing the GDX's LZMA de/compressor 2018-10-06 00:49:06 +09:00
minjaesong
397b2a8795 abolished a need to pass world as parametre
+ simply changing the single variable (ingame.world) will update all the renderer's behaviour
+ somehow my git changelogs are exploding
2018-10-05 23:40:03 +09:00
minjaesong
ae1e99aa3e layer seems load, need to write better test-able code 2018-10-05 22:13:55 +09:00
minjaesong
17e550a6a0 layer write should write proper zlib 2018-10-05 01:23:18 +09:00
minjaesong
292de8d56a it's not zipping correctly; some fixes on readlayer 2018-10-05 01:11:12 +09:00
minjaesong
626aa710c1 layer export: tested output seems legit but can't confirm 2018-10-04 23:46:24 +09:00
minjaesong
78fc6fc657 GameWorld: adding "worldIndex"; more save/load stuffs 2018-10-03 23:15:24 +09:00
minjaesong
d2b7c76734 new map data format and its read/writer
!! UNTESTED !! UNTESTED !! UNTESTED !!
2018-10-03 19:20:11 +09:00
minjaesong
4cfd3b8c45 decided not to GZip the CSVs; hack it away! 2018-10-02 21:13:02 +09:00
minjaesong
e645eaade9 newer map data format 2018-10-02 21:10:02 +09:00
minjaesong
af34d94e6a the event works; ingame works; but starts as "bugged noclip" 2018-10-02 00:12:04 +09:00
minjaesong
98539e698f World Click events
let's hope it works w/o tests as I can't get to the Ingame now
2018-10-01 23:51:04 +09:00
minjaesong
03b642ddd3 player is now nullable; wtf is calling Ingame 5 times? 2018-09-17 01:46:50 +09:00
minjaesong
967eafe8a3 serialised RNG; font update 2018-09-16 03:32:12 +09:00
minjaesong
69eb2d7a3b title remocon: menu UI with no child should be displayed now 2018-09-15 01:08:10 +09:00
minjaesong
6d4ac92133 font update; ui remocon fix; save doc elaboration
UI RemoCon fix: RemoCon will no longer widen to the screen width when being used
2018-09-14 01:14:13 +09:00
minjaesong
b40af8e1b3 more remoCon thingies 2018-08-30 21:30:39 +09:00
minjaesong
c381250665 UI Remote Controller reworked (now 90% less stupidity) 2018-08-30 17:24:53 +09:00
minjaesong
497a88c8de font updates; PBS 2018-08-23 21:06:08 +09:00
minjaesong
0bad86bb9d partially working sky model 2018-08-05 21:57:39 +09:00
minjaesong
eee8a18875 dump (another useless message) 2018-08-05 21:57:18 +09:00
minjaesong
24b2e2a2af ENVIRON guide update straight from my observation 2018-07-21 19:58:56 +09:00
minjaesong
e48731b2e3 reducing down HistoricalFigure to nothing
It doesn't seem like a good idea
2018-07-03 22:45:00 +09:00
minjaesong
8f9022827c removing branching on tiling shader, improving performance
Now tga export needs extra care, but boy that 5 FPS improvement
2018-07-03 22:17:34 +09:00
minjaesong
de19f49d26 making debugwindow to appear again 2018-07-03 14:33:20 +09:00
minjaesong
9ade08013f intro screen flipped correctly, build passes 2018-07-03 14:28:30 +09:00
minjaesong
6b929ac107 PostProcessor working: nested FBO won't work, use FrameBufferManager 2018-07-03 13:48:34 +09:00
minjaesong
108a3e6188 title screen using IngameRenderer 2018-07-01 01:38:07 +09:00
minjaesong
07681110c7 IngameRenderer: damned thing finally works somewhat 2018-06-30 16:47:22 +09:00
minjaesong
abd1827182 still broken, still renders
because im going to break it once again
See my comment in PostProcessor.kt
2018-06-28 21:31:39 +09:00
minjaesong
9736d39e04 trying to optimise the rendering, this is BEFORE job 2018-06-26 09:10:05 +09:00
minjaesong
8daf0a2c38 still wip modularisation, game somehow boots 2018-06-21 17:33:22 +09:00
minjaesong
6bbfd5d167 scrollable inventory with up/down UI button 2018-05-09 19:41:04 +09:00
minjaesong
4664c9ba0d ModMgr: I can load class by name; dropped Groovy script support, coding must go to JAR 2018-05-09 05:34:39 +09:00
minjaesong
fded7f1dfb computery stuff and new set of wires 2018-03-04 19:15:43 +09:00
minjaesong
d11fd281f4 colourutil update 2018-02-16 10:49:13 +09:00
minjaesong
40423ede52 adopting Java 9/Kotlin 1.2 2018-02-10 21:40:17 +09:00
minjaesong
941d9fa107 rain megaparticle experiment 2017-12-18 20:45:32 +09:00
minjaesong
c5fa83b2f4 196 dithering instead of 625 2017-12-10 14:33:12 +09:00
minjaesong
51a2e47430 cheat detected notification 2017-12-10 14:32:32 +09:00
minjaesong
6715308f88 language vars are fully moved to apploader 2017-11-25 22:29:59 +09:00
minjaesong
35f2cf6b4d tooltip UI; tooltip in the inventory 2017-11-25 17:56:57 +09:00
minjaesong
f45a3d252a inventory grid mode buttons working highlight 2017-11-07 23:29:07 +09:00
minjaesong
ade77473c4 map & save button for inventory 2017-11-03 22:48:13 +09:00
minjaesong
7cd7b4047f postprocessor for 3dlut colcorr; dithering should be managed in "dirty" way
dirty way: loads dithered/passthru shader according to the game's config (boolean fxdither)
2017-11-02 17:47:52 +09:00
minjaesong
f5636fe0d3 hacked the titlescreen to fix resize-related UI shit 2017-11-01 15:46:09 +09:00
minjaesong
948f922041 encumbrance meter for new inventory 2017-10-30 04:28:27 +09:00
minjaesong
6c72bef0de black background for inventory 2017-10-29 13:26:34 +09:00
minjaesong
fe21340186 working "equipped" view with unequip 2017-10-28 15:07:58 +09:00
minjaesong
516314c47f "equipped" indicator on item grid 2017-10-25 05:53:39 +09:00
minjaesong
55cdac9269 fixed uiItem stupidity with uiCanvas; it activated even if its parent is invisible 2017-10-24 07:25:05 +09:00
minjaesong
a506269906 catbar and grid: updates and renders as intended 2017-10-24 00:21:13 +09:00
minjaesong
77b563396e at least some of the new UIs are working 2017-10-23 03:44:45 +09:00
minjaesong
98a67c80c6 new inventory design: is it good?
See work_files/inventory_nouveau_2.psd
2017-10-22 02:03:23 +09:00
minjaesong
a8398765c6 somehow fixed a consolewin bug
- It would read a key even if it's closed
2017-10-18 03:52:11 +09:00
minjaesong
6df79b96dd lightmap draw shift fixed; game will properly resize 2017-10-16 22:47:16 +09:00
minjaesong
83b9f74100 renderFront is fixed 2017-10-14 02:48:52 +09:00
minjaesong
d9a01a70c3 sprite shift re-fixed with a correct method 2017-10-14 02:13:06 +09:00
minjaesong
06949848f8 player sprites now aligned to hitbox && drawn at centre of the screen 2017-10-13 00:36:03 +09:00
minjaesong
0e1c46f18d Houston, we have a render (again) 2017-10-07 22:21:37 +09:00
minjaesong
fe8163c1e4 Feature idea I had around for months 2017-09-22 00:22:35 +09:00
minjaesong
e3ac877c3d Rectified heretic YY-MM-DD to standard YYYY-MM-DD 2017-09-20 14:36:40 +09:00
minjaesong
b560011d2f Scientifically correct moondial
Flipped crescents are my mistake 😄
2017-09-19 14:43:06 +09:00
minjaesong
e76458bff6 we've got something
- except actor's RGB won't draw; only the glow does
2017-09-18 02:32:47 +09:00
minjaesong
558430b4f3 fixed camera not putting actor at the centre of the screen
- Actually may not be fixed, but it does not cause render bugs at least!
2017-09-17 23:42:13 +09:00
minjaesong
1149311076 module UI now has margin; game update will drop consecutive updates if its try count is exhausted (reduced lag after window move/resize) 2017-09-15 01:40:12 +09:00
minjaesong
ef176909b4 Ingame: great, nothing renders :( 2017-09-15 00:40:11 +09:00
minjaesong
1d8e66a9cc simple hack for out-of-place render of terrain and lightmap
- Just made them not have negative value
2017-09-14 02:13:37 +09:00
minjaesong
cdf961df09 Guess it's fully working for titlescreen 2017-09-13 18:10:03 +09:00
minjaesong
01a32ad00c NOT using a trick in issue #5 was the key, also closes issue #8 2017-09-13 01:06:01 +09:00
minjaesong
7ffb417618 almost works but dae fucking jitter again 2017-09-12 23:52:16 +09:00
minjaesong
82ddfeb6ee Light fuck: At least I've figured out what the fuck was wrong with. 2017-09-12 21:29:45 +09:00
minjaesong
e67b97257c at least now I know which part is to be patched... 2017-09-09 02:45:58 +09:00
minjaesong
e6e962ecf7 terrain AND wall renders 2017-09-01 01:05:21 +09:00
minjaesong
749a82bcf7 now I can't even tell if it's working as intended or not 2017-08-30 22:16:10 +09:00
minjaesong
f9897bc439 new blocks drawer WIP 2017-08-29 21:06:30 +09:00
minjaesong
1c6560797d terrain atlas: added black patch 2017-08-28 20:37:39 +09:00
minjaesong
75192bef17 camera moving works 2017-08-28 02:27:53 +09:00
minjaesong
05560cf04c Tiling shader -- FIXME: cameraTranslation not working as it should 2017-08-27 23:55:54 +09:00
minjaesong
ee7d51c21b fucking finally... (needs cleanup) 2017-08-27 23:47:30 +09:00
minjaesong
2928aa2eb7 tiling using shader, sorta works 2017-08-26 23:48:07 +09:00
minjaesong
d0702c9159 trying to tile by shader 2017-08-25 19:37:12 +09:00
minjaesong
2bf9acb07a some sort of error screen impl 2017-08-20 22:10:47 +09:00
minjaesong
25ce7958ae better dithering 2017-08-07 01:09:04 +09:00
minjaesong
64f36d2d7c load app using apploader -- no more black screen on app load 2017-08-01 23:55:48 +09:00
minjaesong
65bc67710c RemoCons fully working; also fixed my stupidity 2017-07-26 17:03:22 +09:00
minjaesong
86d3a4a08d UIs wont FOR SURE update (more like, process events) anymore when they are not visible 2017-07-25 18:34:23 +09:00
minjaesong
33da9777ea UI: sub-UIs work? 2017-07-25 17:21:02 +09:00
minjaesong
07ee987411 fixed quickbar and piemenu texture 2017-07-23 19:55:06 +09:00
minjaesong
72b7adcf39 more compatible shader 2017-07-23 18:23:53 +09:00
minjaesong
c595270faa leak patched I guess 2017-07-23 17:38:57 +09:00
minjaesong
d753365e54 titlescreen: camera follows terraini undulation 2017-07-22 18:27:58 +09:00
minjaesong
116b4cc390 title screen renders well 2017-07-21 20:28:12 +09:00
minjaesong
a5dd5b9e98 generalised things so that they would work outside of ingame.world; title screen wip 2017-07-21 19:59:51 +09:00
minjaesong
f51417e709 action listener on textbutton list 2017-07-20 22:25:40 +09:00
minjaesong
fd7d724f39 parallax (sky looks bluer when you go up) 2017-07-20 18:39:05 +09:00
minjaesong
528fdc9fc5 limitedly successful attempt to create a title screen 2017-07-20 00:36:41 +09:00
minjaesong
33a774b5b7 Ingame's Player is now mandatory; player spawn on right position 2017-07-18 00:19:55 +09:00
minjaesong
58205e5eb5 Inventory UI: items page button 2017-07-17 14:37:10 +09:00
minjaesong
31b7203d01 some bayer matrix things and my discoveries 2017-07-17 12:22:15 +09:00
minjaesong
c9932fc81b simplified a structure of UIs a bit 2017-07-16 23:15:32 +09:00
minjaesong
145a4e5e71 dithered skybox 2017-07-16 05:03:04 +09:00
minjaesong
81529eb215 bayer-dithering shader revisited 2017-07-15 18:35:57 +09:00
minjaesong
057df6632a camera clamping, UI resize 2017-07-15 02:02:30 +09:00
minjaesong
5499ded796 wall render bug fixed
- wall wouldn't render if transparent-yet-sold tiles like glass is placed on top of it
2017-07-15 00:02:00 +09:00
minjaesong
61427b849a load screen adj, faster gravity response for standard 2017-07-14 18:48:48 +09:00
minjaesong
a53f818ba6 Rudimentary load screen works (only with Ingame screen) 2017-07-13 19:10:11 +09:00
minjaesong
d9a3318768 GenuineSonic 2017-07-13 18:07:12 +09:00
minjaesong
d241e5cbb0 disposable UI; loading screen mockup (i heard like loading screen -- sonic 06) 2017-07-13 17:53:40 +09:00
minjaesong
49a9278c59 load screen render, fixed some init code of the app 2017-07-13 03:59:26 +09:00
minjaesong
fc9516fd39 how changing the screen should be done 2017-07-13 01:34:09 +09:00
minjaesong
6bff02d91e lightmap downsample works, sampling bug fixed with Filter.NEAREST, now having shrinkage issue 2017-07-12 14:33:59 +09:00
minjaesong
bad6ff296a working UV simulation using alpha channel 2017-07-12 02:35:36 +09:00
minjaesong
1e9c04d7c0 working world-glow blend 2017-07-11 13:34:14 +09:00
minjaesong
3ffdd7233f prep for draw glow 2017-07-09 20:29:35 +09:00
minjaesong
5a5fb45c3b diching RGB10; colors are now fully vec3 2017-07-09 02:21:24 +09:00
minjaesong
1a33c3be5a float lightmap seems it does have little boost on fps 2017-07-09 00:51:25 +09:00
minjaesong
0ad7db3b51 failed attempt at multithreading 2017-07-08 22:34:45 +09:00
minjaesong
8504337da9 asynch update and render (aka frameskip) 2017-07-08 20:38:05 +09:00
minjaesong
f2f5cd7daf former bug fixed; now we have ceiling-stair-clip bug 2017-07-07 02:11:24 +09:00
minjaesong
464d30a384 improved collision displacer: no more clip-to-climb-up-rightside-only thingy 2017-07-07 00:01:20 +09:00
minjaesong
009b55481b new collision displacer: got one-block-ceiling-passthru bug, but otherwise tolerable 2017-07-06 16:35:58 +09:00
minjaesong
72e7931f4d 4096 shader finally works... perhaps it needs bayer matrix? 2017-07-05 18:30:53 +09:00
minjaesong
0e4dd79cc1 downsampling sorta works, ONLY WHEN (width or height % 4) is 0 or 1 2017-07-05 16:03:50 +09:00
minjaesong
f676938176 control scheme update 2017-07-05 12:49:26 +09:00
minjaesong
8a759cb178 Ladies and Gents, we have shader-powered smooth lighting! 2017-07-05 02:20:10 +09:00
minjaesong
66e4dcd1c4 shader seems working!; it's messed up by all the test codes but I commit anyway 2017-07-05 02:05:03 +09:00
minjaesong
d9381fc58e blur shader works 2017-07-04 23:30:48 +09:00
minjaesong
039ccea58f shader does work at least... 2017-07-04 22:04:07 +09:00
minjaesong
b592b8fa0f killed old zoom so that framebuffer would render without hack 2017-07-04 20:11:54 +09:00
minjaesong
b82d172d58 needs more shader (for smoothing out lightmap render) 2017-07-04 14:58:18 +09:00
minjaesong
41f9f4032d barely managed to fix inventory UI 2017-07-04 01:27:18 +09:00
minjaesong
7b2b6caf82 dunno why but setting camera position to negative works... 2017-07-03 23:42:59 +09:00
minjaesong
b7fb8ff4da putting ore vein prototype on main sheet; also a commit before fuck-up 2017-07-03 19:26:00 +09:00
minjaesong
2ea3ce0c67 fixed bug: things go dark as inventory is opened
Not cloning the color when MULing was the culprit
2017-07-03 02:55:33 +09:00
minjaesong
9b32cf63ff fixed bad color rendering on blocksdrawer and lightmaprenderer 2017-07-02 21:53:50 +09:00
minjaesong
2129cce7f3 debugger's got its colour codes back 2017-07-02 15:28:45 +09:00
minjaesong
c8c1bdf836 proper sprite flip draw 2017-07-02 00:45:57 +09:00
minjaesong
4a54c87826 keyboard control ported to GDX (at least as much as I can right now) 2017-07-01 18:31:00 +09:00
minjaesong
7248616e58 ore veins 2017-06-30 02:06:53 +09:00
minjaesong
33b5a21c26 blocks camera and framebuffer seems working 2017-06-30 01:50:06 +09:00
minjaesong
1095cb451f can see camera working but not the actor gravity 2017-06-28 22:15:42 +09:00
minjaesong
4472722c5d a commit before heading to the airport 2017-06-23 02:18:03 +09:00
minjaesong
ab846ad805 More game-related documentations 2017-06-22 19:00:15 +09:00
minjaesong
187277d6a8 Just got enought to render without error (no display tho) 2017-06-22 18:59:53 +09:00
minjaesong
ad481853bb LibGDX, here I am. 2017-06-22 02:31:07 +09:00
minjaesong
1ecbc57f83 gdx font: thai works good enough; RIP performance tho 2017-06-16 22:06:08 +09:00
minjaesong
41791af764 gdx font: can customise font spritesheet location 2017-06-16 19:29:40 +09:00
minjaesong
c664755ad8 gdx font working good 2017-06-16 19:27:14 +09:00
minjaesong
984881421c gdx font: working locale switch 2017-06-16 19:12:57 +09:00
minjaesong
e07e321ee3 gdx font almost working
- TODO: bulgarian/serbian, shadow
2017-06-16 18:52:03 +09:00
minjaesong
6e403f97f8 re-arranged all the docs in more convenient fashion 2017-06-16 15:10:55 +09:00
minjaesong
87242da9cc Terrarum Sans Bitmap imple on GDX -- wip 2017-06-16 15:09:19 +09:00
minjaesong
12c6f6fd04 more inlining and minor performance tweaks on LightmapRenderer 2017-06-12 04:04:54 +09:00
minjaesong
980c92f213 more minor changes 2017-06-11 18:01:03 +09:00
minjaesong
8a3c4fd65e LibGDX stuffs for issue #23 2017-06-11 18:00:48 +09:00
minjaesong
67ca216243 test watches 2017-06-11 01:22:46 +09:00
minjaesong
7bd7a6532d this fixes *some* case of abnormal displacement 2017-06-03 00:37:47 +09:00
minjaesong
c5765fc08a lightmap and skybox update 2017-06-03 00:07:47 +09:00
minjaesong
7f909e3796 lightmap aesthetics: blocks exposed to light are now rendered brighter 2017-06-02 00:46:45 +09:00
minjaesong
b4042f0060 fixed LB/RB/BR bug (actor jitters because of false positive collision?) with a hack 2017-06-01 23:10:08 +09:00
minjaesong
da2452c84e still sketchy, but at least I can only care about corner cases, as it's not generalised 2017-06-01 16:58:25 +09:00
minjaesong
f0a6c36f8a fixed a problem in prev commit msg somehow 2017-06-01 15:25:40 +09:00
minjaesong
fdb9d38e03 this new method should work (except can't escape after right/bottom collision) 2017-06-01 14:52:32 +09:00
minjaesong
799a77c929 some realisation after a bad idea (bad idea part is hidden/omitted/overridden in this commit) 2017-06-01 03:25:08 +09:00
minjaesong
41050337f4 I really have no idea if i'm doing it right or wrong 2017-05-30 01:10:10 +09:00
minjaesong
85ab2a2066 various patches and renaming; thai-variable font sheet 2017-05-27 20:05:12 +09:00
minjaesong
06cbac1cc5 phys for player works good (but not perfect); phys for objs are still fucked up 2017-05-27 20:04:41 +09:00
minjaesong
50b597de5f why it's not super-fied? 2017-05-27 15:54:01 +09:00
minjaesong
b96daa7d3d physics sorta works well with player, but not balls
- bounce for downward works, bounce for left/right wall hit does not
- headbutt is still undefined behaviour for all phys objs
2017-05-27 15:48:35 +09:00
minjaesong
80777fcccb now works for both LR but actor sticks to left cliff but not right 2017-05-25 22:30:36 +09:00
minjaesong
a601d4c57b removing 99999 for endX finally works 2017-05-25 22:02:36 +09:00
minjaesong
f7eaa4c4f0 with some hacks, I was able to make LR walk colliding work, but not the headbutt 2017-05-25 20:37:52 +09:00
minjaesong
f466f6f001 no message 2017-05-25 20:23:24 +09:00
minjaesong
5255ae60af Terrarum Sans Bitmap: wider hangul 2017-05-25 00:04:21 +09:00
minjaesong
2a575351d3 anti-stuck somewhat working 2017-05-25 00:03:12 +09:00
minjaesong
58b229a7fa houston, we have (bad) render 2017-05-24 15:40:58 +09:00
minjaesong
905ab1004c light de-banding when they exceed 255 out of 1023 2017-05-22 20:36:20 +09:00
minjaesong
b7ed3dd814 much failure, such note; wow 2017-05-12 17:02:29 +09:00
minjaesong
ccbf56b322 still glitchy but working? 2017-05-12 16:08:23 +09:00
minjaesong
87213e8fbd lcd font update 2017-05-12 04:35:28 +09:00
minjaesong
40e48eec21 pre-fuck-up commit inside of pre-fuck-up commit 2017-05-11 19:37:18 +09:00
minjaesong
b421dcf187 av fuck 2017-05-11 03:12:10 +09:00
minjaesong
2eb6e7c0a2 code cleanup unrelated 2017-05-10 21:02:57 +09:00
minjaesong
3de9cedec3 code cleanup related to ActorWithPhysics 2017-05-10 21:02:05 +09:00
minjaesong
f45dc6fde2 no ui toggle when console is open 2017-05-10 21:01:19 +09:00
minjaesong
31954f3ca7 physics almost works, except for bunch of TODOs and FIXMEs 2017-05-10 03:41:46 +09:00
minjaesong
4262b02faf fixed dividng by zero (Line 756) 2017-05-09 23:38:09 +09:00
minjaesong
46fe5fb1e2 That's it for the today, thanks for coding and have a nice day 2017-05-09 02:52:15 +09:00
minjaesong
23cc28d3bd Features that are reckoned are working (which means the full features are WIP) 2017-05-09 02:40:22 +09:00
minjaesong
9732c6d66f y-down blocking work (can jump down to hit the ground but not the ceiling) 2017-05-09 00:46:38 +09:00
minjaesong
566c76c1a2 removing moveDelta to utilise externalForce and controllerMoveDelta separately, for great justice 2017-05-08 21:19:28 +09:00
minjaesong
81220fa542 ground slide (balls) works; walking works; still no wall... 2017-05-08 02:55:12 +09:00
minjaesong
572fbb4b9c at least it snaps without hacks; adding one important documentaion 2017-05-08 00:47:21 +09:00
minjaesong
10a99b7db6 I can jump around at least, isTouching() needs more work 2017-05-08 00:10:58 +09:00
minjaesong
959873413d fucked up while making ActorValue delegated – not applicable; can't have default value
making commits for files to keep so that I can discard changes
2017-05-07 18:39:26 +09:00
minjaesong
14dfb5c963 I think I can ignore this CCD-ing bug but it's happening 2017-05-07 03:11:42 +09:00
minjaesong
86821d2d98 fuck it; we do it tomorrow (or Monday) 2017-05-07 02:17:38 +09:00
minjaesong
c9d786390c forgot to commit... 2017-05-07 00:48:57 +09:00
minjaesong
ade9592d67 sorta works? 2017-05-07 00:24:00 +09:00
minjaesong
22ad180e04 hitbox displacement rewritten 2017-05-05 02:03:29 +09:00
minjaesong
479c0ce91f does this plan look good? 2017-05-03 15:02:49 +09:00
minjaesong
a9d35678c5 why things are keep happening? 2017-05-03 14:41:09 +09:00
minjaesong
cbb4eaad94 more commits before the havoc 2017-05-03 03:07:35 +09:00
minjaesong
165ae1777b some organisation, Base32 password generator 2017-05-03 02:37:03 +09:00
Song Minjae
ecf775c664 no message 2017-05-01 08:00:07 +09:00
Song Minjae
1375f91505 A commit to save my soul as I'm going to fuck up things a bit... 2017-04-30 21:26:20 +09:00
Song Minjae
c9c761598a inventoryItem -> gameItem 2017-04-29 23:11:54 +09:00
Song Minjae
9a7885fc80 kotlin runtime update 2017-04-29 22:53:32 +09:00
Song Minjae
9508249533 blocks now have properly formatted ids 2017-04-29 00:05:10 +09:00
Song Minjae
3498a100a4 clean ice tex fix 2017-04-28 21:52:05 +09:00
Song Minjae
7a3e7546de Sandstone connectivity change
- TODO do the same with ice block
2017-04-28 17:07:45 +09:00
Song Minjae
93939f22bf quickslot works, new event for actor "actorValueChanged"
- "unpacking" fresh new tool would un-register quickslot desig.
- priority issue on "equipped by quickslot change" and "equipped by inventory UI"
2017-04-28 12:21:27 +09:00
Song Minjae
253260de6f blocks name update 2017-04-28 01:49:32 +09:00
Song Minjae
a7dea93744 Quickbar: all working except for equip/unequip 2017-04-28 01:48:51 +09:00
Song Minjae
26cbe6970a modularised lang 2017-04-27 23:41:19 +09:00
Song Minjae
3e54dcab2c working walls, quickbar and piemenu fixed 2017-04-27 17:22:56 +09:00
Song Minjae
56b77d1838 working quickbar and piemenu 2017-04-27 14:45:55 +09:00
Song Minjae
f4db93ca9e Tile -> Block && Map -> World 2017-04-27 01:57:45 +09:00
Song Minjae
a9eb1f579e Loading item from module using Groovy 2017-04-26 23:53:22 +09:00
Song Minjae
36a7983024 durability meter: stack of (new) tools displayed as intended
- displaying NOT based on their stacks but their health
2017-04-25 17:24:56 +09:00
Song Minjae
ab8f019109 removing stupidity which harmed AmmoMeterProxy 2017-04-25 15:29:24 +09:00
Song Minjae
ebc8174d2c fresh-new dynamic items (e.g. pickaxe) can be stacked 2017-04-25 02:59:59 +09:00
Song Minjae
c35ba8201a new ID for dynamic item work flawlessly with adding multiple at once 2017-04-24 21:31:53 +09:00
Song Minjae
5cd5ebbea3 Resolving issues #16 and #20 2017-04-24 02:23:13 +09:00
Song Minjae
6399c2d66b Resolving issue #18 and #19 2017-04-23 22:53:49 +09:00
Song Minjae
b342e7d042 working vital meter for tool durability 2017-04-21 18:11:30 +09:00
Song Minjae
c6e42ffbbe wenquanyi: fixed bad code point allocation 2017-04-20 20:48:23 +09:00
Song Minjae
e0a23f6089 more housecleaning 2017-04-19 22:56:10 +09:00
Song Minjae
c779baa72d compressing large font images 2017-04-19 22:31:55 +09:00
Song Minjae
aa4fbba711 about issue #17 2017-04-19 21:15:09 +09:00
Song Minjae
2895f4be6d Proper tga.gz loading using own imagedata 2017-04-19 20:53:03 +09:00
Song Minjae
fcd378c51a Some space saving, terrain reads GZip directly 2017-04-19 16:15:14 +09:00
Song Minjae
fe94ebbe4a terrain damage data is now properly removed when the tile is newly placed 2017-04-19 03:03:53 +09:00
Song Minjae
8689ab1565 does it work? 2017-04-18 01:24:54 +09:00
Song Minjae
4f43fdbd27 README update 2017-04-18 01:23:15 +09:00
Song Minjae
5fe604cf45 pickaxe working as intended 2017-04-18 01:14:25 +09:00
Song Minjae
f840dbe7de modular first test 2017-04-17 16:14:35 +09:00
Song Minjae
532c836553 mod support design wip 2017-04-17 04:03:58 +09:00
Song Minjae
7ebb21124c voi helvetti 2017-04-17 02:29:05 +09:00
Song Minjae
f2ae2d9449 fixes, bits and pieces, changes in ID referencing, terrain and wall takes damage, working test pickaxe, and a new issue 2017-04-17 02:18:52 +09:00
Song Minjae
6087072d3d 10-bit RGB conversion tool 2017-04-14 22:45:55 +09:00
Song Minjae
a47eb41d9a inventory ui update 2017-04-13 03:25:49 +09:00
Song Minjae
47b9b92797 font adjustments 2017-04-12 00:27:14 +09:00
Song Minjae
037e84d6e2 setting up the inventory using builder (during init) requires ingame.player to be nullable, lateinit won't work 2017-04-11 23:07:29 +09:00
Song Minjae
1301121aa9 sanity check on equipping the item 2017-04-11 21:12:51 +09:00
Song Minjae
d20190b2bd selecting and consuming item in inventory 2017-04-11 19:21:32 +09:00
Song Minjae
bb797a0910 clickable inventory for (un)equip 2017-04-11 02:30:34 +09:00
Song Minjae
d33d25f384 working inventory clicking ingame 2017-04-10 01:35:28 +09:00
Song Minjae
12015669c6 UIs will draw on "backing" framebuffer where skybox is 2017-04-09 22:22:29 +09:00
Song Minjae
671048e1e1 Inventory UI on ingame 2017-04-09 03:35:18 +09:00
Song Minjae
c5367f8f1c vt: new filesystem using tevd 2017-04-07 19:12:27 +09:00
Song Minjae
2332239ef2 global light matched to skybox 2017-04-07 19:11:56 +09:00
Song Minjae
25128d45e5 change in light
- darker night
- no blue in deep night, as in real life
2017-04-07 03:46:16 +09:00
Song Minjae
207c90d35e new WorldTime based on TIME_T 2017-04-05 02:52:00 +09:00
Song Minjae
1057e7d442 VT: shit is still rolling
- We might need virtual disk image...

Former-commit-id: c3278cd9fe1ddad8b26b45577fecb0500365d38b
2017-03-31 17:27:53 +09:00
Song Minjae
5bfc5c3a38 inventory now shows equipped position
Former-commit-id: 10950ffc409accfa914b9f531193b2fac0783f7d
2017-03-31 17:26:44 +09:00
Song Minjae
84f91e6a7a brighter soil and grass tex
Former-commit-id: 8457edfdd297ddef3ebc6c6327611a42d21dbb44
2017-03-31 17:26:01 +09:00
Song Minjae
4363bd4ba2 fixed a bug where for whatever reason io.read would return 0x0D (CR)
Former-commit-id: 769e2d3931472d14ce66cfef3a496a3913dc51be
2017-03-31 17:25:31 +09:00
Song Minjae
48315daa7d proper way of setting quickslot #
Former-commit-id: 5cd21f043def3c7622290df5bf11f0b3f0080d30
2017-03-28 03:44:43 +09:00
Song Minjae
cd710de280 inventory UI wip update
Two columns, some marginal spaces to make it look better


Former-commit-id: c26d11e499970280b78193772d29937295916ae2
2017-03-27 02:58:52 +09:00
Song Minjae
816502df3d inventory UI: quickslot designation
Former-commit-id: b2bddf7c271c678213f8f346d1de4b5c1dc27f60
2017-03-26 00:42:41 +09:00
Song Minjae
b6290134a9 runes: fixed numbers not coming up
Former-commit-id: 845b721d289842d39ea47043154a06ff7069be77
2017-03-25 02:28:49 +09:00
Song Minjae
1e3ffd2272 runes: fixing little mistakes
Former-commit-id: 2bfd0fd56a8219d44eed429671436ed2c638706f
2017-03-25 00:53:11 +09:00
Song Minjae
1f59082c15 runes update
Former-commit-id: 65a31563da924f46d5ce62c2af25549a97092762
2017-03-25 00:47:21 +09:00
Song Minjae
2e11676ee6 new runes impl and test
Former-commit-id: f92f6d528128ed19aadffee7e112daa5736d50e3
2017-03-24 23:59:57 +09:00
Song Minjae
f919b45e18 string for GPL 3
Former-commit-id: f114ac32817d94b1fca3bc7463a8afc24d166f74
2017-03-23 16:38:53 +09:00
Song Minjae
24de647284 inventory ui
icon in list


Former-commit-id: 7182dcda408d9710d77e25e357f3a67bdd42fff9
2017-03-22 23:58:18 +09:00
Song Minjae
accf1cf584 marking obsolete resources as _old_
Former-commit-id: f0919500afaafa91adaeb7f7c7377a5e2f10ef08
2017-03-21 23:39:15 +09:00
Song Minjae
6bea8af9db This project is now GPL3
Former-commit-id: 173c5833f232f3f6f7f091c02d56498cff600822
2017-03-17 23:52:10 +09:00
Song Minjae
d3547e47ca MIDI input test
Former-commit-id: 8ec51637782a2c4185716f3164c837477e648975
2017-03-17 23:49:48 +09:00
Song Minjae
208fd2ba15 added greek ano teleia
Former-commit-id: d2c67302b1e196949e8b6765b750ffffb38d2699
2017-03-17 19:23:40 +09:00
Song Minjae
72204fd5cd there was a mistake :D
Former-commit-id: 972b0f9481218f995e145e19dee3107dac912b72
2017-03-17 18:35:00 +09:00
Song Minjae
41da296bce font upd kana
Former-commit-id: c61920ca695eeafb3a9e200b5083b323b11814e6
2017-03-17 17:28:22 +09:00
Song Minjae
114bfe395f kana font wip
Former-commit-id: 0290410638e7ddd5981aba5d40acc2c1008b0658
2017-03-17 03:30:18 +09:00
Song Minjae
2491a03c99 inventory and its ui
Former-commit-id: b1a073c5636ac4516e6c9cf41bb97a844057de3f
2017-03-17 03:28:47 +09:00
Song Minjae
3d91023011 TextButtonList working kinematic background
Former-commit-id: 8976d3b3d1e40731adf13430ad747351a6401b24
2017-03-15 01:06:13 +09:00
Song Minjae
ff817c25e6 text labels now has background
Former-commit-id: 05f2767134b385960deb65c2e76c97432c8303ad
2017-03-14 15:08:18 +09:00
Song Minjae
f47c66db44 magic description language update
Former-commit-id: 9637f09aa90345c2c2f4889a85d69af9f9c1e584
2017-03-13 21:41:08 +09:00
Song Minjae
bc4fd8866a UI testing env and working text buttons
Former-commit-id: b8fd27c7f71f9bc8da259ae132badcbc9ce117ac
2017-03-13 21:40:50 +09:00
Song Minjae
0113ca5d09 new inventory UI idea
Former-commit-id: 0032d2b023d8ab3d2393541d452673ceeafc372e
2017-03-12 04:21:58 +09:00
Song Minjae
920d8085cd an idea
Former-commit-id: 2f1562b654b3e8eb9ad5c36ff371472858a1a9ec
2017-03-10 23:31:41 +09:00
Song Minjae
a10134db2e minor fixes in UI with aliases
Former-commit-id: 539604058bcf7e545de920b1c7a5958e30577a34
2017-03-10 21:23:51 +09:00
Song Minjae
edb2f5ce11 pre-assigned vital metre
Former-commit-id: 48d968d5b93ed6a4fb5a2f7fe63e2c24b7aaa476
2017-03-10 02:15:17 +09:00
Song Minjae
a22d27408c message notificator bug fixed where it would only work properly for first time
Former-commit-id: 640b113cb242ec572f17654feaa8b9be52c333c3
2017-03-10 02:14:58 +09:00
Minjae Song
dac69f504c Add contribution guide
Former-commit-id: 5d501e16b94c4056efb00ea96e9253aaa00a2578
2017-03-09 16:23:57 +00:00
Minjae Song
dfd71435de Update README.md
Former-commit-id: fd89faba7d151412ebce782ee76fe1c1fb2b08b1
2017-03-09 16:15:58 +00:00
Song Minjae
76fcb5b12f git gud
Former-commit-id: 86d4fba868dbe1c2841e1829f2857ff47187cc57
2017-03-05 01:31:40 +09:00
Song Minjae
e9572488be ordered vital metre -- you can display two or more vitals
Former-commit-id: 27767b632a1c65060750e49c55db7e71a0e443ae
Former-commit-id: b431478a0d43193ac60011a958f6305673334755
2017-03-05 00:28:20 +09:00
Song Minjae
08417be027 eliminated reddening on T+52300
Former-commit-id: 5106f760b5945f3b9a90f66d5de155e7a223cfab
Former-commit-id: 7dd1718d64e84e98d8e08a50cfa8ed50366bcc32
2017-03-05 00:27:50 +09:00
Song Minjae
edd97b45a7 vital metre prototype
Former-commit-id: c3f95f7ef280eabc5516ad6885386cb89d6ee35d
Former-commit-id: ab9cd5bd8daf27d37828a5ca4a737a723d76fa1a
2017-03-04 01:52:30 +09:00
Song Minjae
0a0aea9589 vital metre mockup
Former-commit-id: c49f7ba80cff854db6d79af1c9d50d77b0bae76d
Former-commit-id: bd62a24bfd4c9737e2f23b0bae1756df62a19acf
2017-03-03 18:42:47 +09:00
Song Minjae
f5db4cb2fb have no idea how LFS works :/
Former-commit-id: 81595f4fd40bb497150c26b063c994e7dd267cda
Former-commit-id: 94aeebbd5f3949f014497bcd79f8e83f6dd84d5a
2017-03-03 12:18:14 +09:00
Song Minjae
75ab8c6558 forgot gitattributes
Former-commit-id: 3283e9aa0f0cbb450a325f743033150b5b031c80
Former-commit-id: 0a4113e9280e66194ee627dedf6432a23cdf470b
2017-03-03 04:34:21 +09:00
Song Minjae
63ec3a8917 removing old test sounds
Former-commit-id: 916a2b8fb5f290451cfb604fe4b2b3b2abd5bc81
Former-commit-id: 2be333efeff82648db00057975d7c02bd7dfddda
2017-03-03 04:31:34 +09:00
Song Minjae
4c8ceaf301 updating old copyright notice
Former-commit-id: 49f0ae772e48f122919220accaffd4ebf73ed3e3
Former-commit-id: b2b7ad7cf731f5c51938e84714f354bd8ffd6e6e
2017-03-03 04:15:44 +09:00
Song Minjae
6d8f9d2901 still working on vt, still buggy :/
Former-commit-id: 9164ca8ef33917f7254c65f3947903b8a17dd654
Former-commit-id: 3ebf64f00a0b86d11a449c1d399e149f2714839c
2017-03-03 04:05:00 +09:00
Song Minjae
efd3284e30 some UI suggestion
Former-commit-id: 4526bc289a05ddd0fd205c8c9986785196bdd487
Former-commit-id: ce0bf7a3ce0f083e698cddf708419341f4a73fa9
2017-03-03 03:56:07 +09:00
Song Minjae
b29e6af643 working io.read from STDIN
Former-commit-id: b1168a53fd5fbd09c6a5a76506402560fc4e0fd7
Former-commit-id: a0d455da14a6eb7bf0127e136949273ec5a28628
2017-03-02 22:35:13 +09:00
Song Minjae
96c6cb2cc6 bunch of codes:
- Test InputStream() on VirtualComputer (blocking/unblocking using simple semaphore) -- no more dirty lua impl of io.read
- Typealias Kotlin 1.1
- Primitive box drawing on VideoCard
- Removing unnecessary fonts


Former-commit-id: cece88af3a3430678e685856eec78b4a9d598b4f
Former-commit-id: 22eed3a7beb9b4cb34636cbab2ff0e94989bdb31
2017-03-02 02:11:50 +09:00
Song Minjae
bdba27d776 Update to Kotlin 1.1
Former-commit-id: bd35f4973ce672c9fa4b36a1c8655bd719df5148
Former-commit-id: 010bb8907f6afa453de6a678cf97cc6c72483dd4
2017-03-01 21:33:46 +09:00
Song Minjae
71091cce98 vc ppu: some updates for Lua
Former-commit-id: 3d99a6788d05eaf3e90bffe8d412f0ab92e7f9bb
Former-commit-id: 306ed39d09f2b0b5461cb71d0cef96d7d5793769
2017-02-26 03:08:58 +09:00
Song Minjae
679a65a12e fixed lantern colour not update
Former-commit-id: 153d3f4fbdae65f71c7c63a3b0a87fee08677186
Former-commit-id: 732f527d49dc31bbc669bbfed4624018c471dbe0
2017-02-26 03:08:21 +09:00
Song Minjae
a3445d631a actor hit ceiling and now properly bounce back (again, gah!)
Former-commit-id: 05ce5bbae52337a92e26bd6937d610bd2c14cefb
Former-commit-id: 810db52f9f9f1756d2d667229487fb653f87898e
2017-02-26 03:07:54 +09:00
Song Minjae
b23f848d95 working real-time software blur
Former-commit-id: a545802b19188fb9d3b6168885f40d46e3376195
Former-commit-id: f71dbfa2521888cc847937f549e627f87625ea17
2017-02-25 02:50:48 +09:00
Song Minjae
3b7e88b0af no memory leak on ImageBuffer rendering
Turns out, <ImageBuffer>.image creates new Image instance which will NEVER be reclaimed (which causes OutOfMemoryError) unless manually destroy()ed.


Former-commit-id: 34840cf63e52e5635ec8acd5fb1bb78923c61063
Former-commit-id: aca4388320fae022a4744f75c1b0f66b544bdafb
2017-02-25 02:39:02 +09:00
Song Minjae
d7b49b0f9d graphics computer -- working sprite system
Former-commit-id: eedad5c99d0d8fa1d74a7a5b4e6250017d55163b
Former-commit-id: 0dc08e778cca3300ffc6f696ba395eb8ca2b154b
2017-02-24 17:35:32 +09:00
Song Minjae
0180c7cf0a yet another font update
Former-commit-id: 332bdbd2e55d148f42f3e3635dbc94a71f152f01
Former-commit-id: 27308c98fe0fe858bcbb42301dd714a49d92c81c
2017-02-20 23:27:00 +09:00
Song Minjae
b33f179a9b font upd, added ext-b
Former-commit-id: f8f324ea45e12608017c9a09c4a8994d341d91a1
Former-commit-id: 37fff79ddb4eec7bd5f3006ff0db1e1e3abd3653
2017-02-20 20:28:54 +09:00
Song Minjae
c48308efe1 font upd
Former-commit-id: bf42a690c7cd199d4f2ec00855213b83aecb144b
Former-commit-id: b992aac69b93c5d1632e96c4985cf61a6419b6a8
2017-02-20 01:43:26 +09:00
Song Minjae
076c5ba1f1 terrain tex upd
Former-commit-id: 19fe7efbde3db7d5655c8470489da1c5a5a188ec
Former-commit-id: 94c984500c0f8ef3b323e953c91306b525bd4623
2017-02-20 01:41:37 +09:00
Song Minjae
d7576ce844 New RNG for the game and Joise
Former-commit-id: 4a5b7f7ef6546d04be106d881e7d3f9dd6dc1b57
Former-commit-id: 90c15fa64cde39e33206ff7be645db9bceda1161
2017-02-20 01:41:01 +09:00
Song Minjae
1c0b969078 resolving issue #12
Former-commit-id: eee32f1d3b74a431626888ab32166e0cad14f522
Former-commit-id: e58fecf50f193d695f7a7852117183486a12cc62
2017-02-14 23:25:18 +09:00
Song Minjae
5d7349386e ActorWithSprite: correct offsetting on X axis
Former-commit-id: 7c981241889cff139b3523d751e85885af04f867
Former-commit-id: 33b93c99c94813afa2a7ce272f59e7b28faf9da1
2017-02-14 18:56:55 +09:00
Song Minjae
3065d642b5 finalising fonts
Former-commit-id: e85038e433c9e451761a25ce93fa976b847c9e1e
Former-commit-id: 0f59fe3a1b5a174ff63f5a79f11007f0e9d4a204
2017-02-14 18:51:55 +09:00
Song Minjae
d028593842 unhelpful git comment about the font
Former-commit-id: 272cb1b56834c4796d4db9c9ba3d5ead69084513
Former-commit-id: 0395adeefc72aa618d5a422c99db2932a05fe2c4
2017-02-13 14:13:40 +09:00
Song Minjae
5c4036e73f fixing mistakes
Former-commit-id: 2bb63bc0616d42937372781a5f7c779a2b1fb984
Former-commit-id: 80746e41232f5170b807ff54efa3b1e477ee9467
2017-02-13 02:29:39 +09:00
Song Minjae
a9b00bd909 more changes on greek
Former-commit-id: cfde7383844a9a183bf57edad3a772ae74f19af8
Former-commit-id: 178d7b4b788ffe43db64eb453543ea1e20d94acf
2017-02-12 16:45:03 +09:00
Song Minjae
add2be7109 new greek and more tweaks
Former-commit-id: 0c480dd7ce173a37f2f48b5b5d711c2641cbda00
Former-commit-id: 18492d01862bdeecb9c0eba825a3b25da76211b0
2017-02-12 04:12:26 +09:00
Song Minjae
226ae77ab4 cyrillic
Former-commit-id: b5b4c8495b387dbc6516829f3ddf0124f87d8500
Former-commit-id: 2c78b2fb6112199bc7bf4d55b3df01da10f14958
2017-02-11 23:57:42 +09:00
Song Minjae
5799cc39ce Basic Latin, Ext-A
Former-commit-id: 82df422b6a9b9e9c0fba0d11762cbdf2ca5b6f40
Former-commit-id: ff29dc32eb21b9626c78eb53518f5eff12439832
2017-02-11 23:22:35 +09:00
Song Minjae
afe197caf7 newfontsystem branch init commit
Former-commit-id: 5f03cdbec6058f90ef1354db5ee1c6dac9755feb
Former-commit-id: f132b6c4e1a51146fb7522686e24008640e88c45
2017-02-11 16:45:47 +09:00
Minjae Song
cc01ff62e6 citation needed
Former-commit-id: 92b35f459de0ce84064bc44a2ff54be07f06e711
Former-commit-id: 682ed520288e1144c15ac998d7a1b53971f7482d
2017-02-09 16:45:28 +00:00
Song Minjae
bd58c9e40b video card wip for virtual computer
Former-commit-id: 3c71eb0e8614e92e63fd3b29906a3cfd311c916f
Former-commit-id: 3472d6eb7d03a29bfd859e9207f76aeb23cef89b
2017-02-09 22:18:27 +09:00
Song Minjae
9ddf0dee63 data format docs
Former-commit-id: 5da80ac39d23d518bec0ed4e838fd0a4ae19bd11
Former-commit-id: f7ec7a4cd2c1d7a795aa19352065ee1ea1550fe4
2017-02-07 04:50:26 +09:00
Song Minjae
ad68309bc5 reading text from JInputField to support multilingual input
Former-commit-id: 4dc1228ba000f88d3af29569aa3954cb8acc4d90
Former-commit-id: 7fd7f8bd4f35e3be30cd9fa0da96684a48eedad3
2017-02-05 22:04:33 +09:00
Song Minjae
0a2bf64bff HumanoidNPC: explicit initialiser call no longer required
Former-commit-id: ecc822302182bc55f9a11ede39f74bfaf8fe6c87
Former-commit-id: 92f49eb574cb4f7bbf93dae8bf0ff32fa33a74ae
2017-02-05 03:05:18 +09:00
Song Minjae
e66304bea0 assets update
Former-commit-id: 2988c67408159e5b17dd40a10b3eca4ea187d10f
Former-commit-id: b255a9c812f71f13d17922e11257afde59648ada
2017-02-04 22:55:55 +09:00
Song Minjae
8e7b61ea0c Combined ItemProp to InventoryItem and introduced Material
Former-commit-id: d73882505cb26a99a5cc70ef5dc2b7e2d087823c
Former-commit-id: cf061fd2edb6fbe765ac812507cb5b0d7b77ee7b
2017-02-04 22:55:06 +09:00
Song Minjae
bb33d9e381 Actually utilising ActorAI interface to support AIs written in Kotlin as well as in Lua
Former-commit-id: 53901f5a5d53b33c4254091ec507be82289d57fd
Former-commit-id: 86ce8d2a646a1564ee5e33ef07c5affb338c028e
2017-02-04 22:53:36 +09:00
Song Minjae
65dec9661c killactor command
Former-commit-id: 9f5b3014c3023988e3d86317f8684d8fc7b714c5
Former-commit-id: 637d39819470a6b8c9d88c9805e49ef7cd4f5fb0
2017-01-31 19:07:06 +09:00
Song Minjae
2c9906888b bringing other memory info back
Former-commit-id: a189dc26e906a6cfd85ca68b4db849426c48ce52
Former-commit-id: 267e95f7d52c126b5d3787358477fc29fb50ad8e
2017-01-31 01:10:18 +09:00
Song Minjae
2f7eaea6b8 Merge branch 'newworldgen'
# Conflicts:
#	.idea/workspace.xml
#	src/net/torvald/terrarum/gameactors/Actor.kt


Former-commit-id: 533aeed3cd26565478a3b8c602c9e9aa7e15b43f
Former-commit-id: e7e851ed9734b47cc05144df1c6187ea50f7ecab
2017-01-31 01:05:38 +09:00
Song Minjae
abad2eb1a6 somehow fixed a phys bug where heavier objects accelerate more by gravity
Former-commit-id: 5a39d6495c861f9abe32b09db4bba8f26667de95
Former-commit-id: f9b8307b6371d553174f268f812a2edc71324a34
2017-01-31 01:01:51 +09:00
Song Minjae
12b04fabdf caves and stuff
Former-commit-id: 248077312d8561ad01819a43a4c4a5205c122ff4
Former-commit-id: f4dc915a66bd26338376b9d6008f136fb36b3060
2017-01-30 22:39:34 +09:00
Song Minjae
dbdee14481 new terrain gen
Former-commit-id: ef5db466ae4170c6054df806bc4018ed223fc87f
Former-commit-id: 1ea0525c992dd72532589bed963ea2f0804a0a2c
2017-01-30 03:57:03 +09:00
Song Minjae
172e5752ca more renaming things
Former-commit-id: 80e29fc17e431e350d8d4860273ec42bc4ad67df
Former-commit-id: d70546a097d66ade94de93b4be157b7c9637e98f
2017-01-29 20:48:55 +09:00
Song Minjae
c60a967050 more world settings
Former-commit-id: 5b9f7717ed2a4ad2f054e8db75b404b5c974539b
Former-commit-id: bc5d18446028a734a3a9707c928f069bcd1d5a7f
2017-01-29 02:04:19 +09:00
Song Minjae
361f322d78 just updating things so that I can have a backup point...
Former-commit-id: 0a5a6d7f68ee1a96562532572c8d45fe102d3c25
Former-commit-id: a1a78f61f2fe2a8707e47633caa6cd67a829b35e
2017-01-26 16:58:06 +09:00
Song Minjae
8b111ef262 not going to be easy; just renaming and changing things
Former-commit-id: 5cb93ffbd1b545e4a346fa3edc6bb874ec5b508e
Former-commit-id: 194e2ea1e057415bbc2a516346dc1d8d216d64cb
2017-01-26 16:57:16 +09:00
Song Minjae
df5f4771a1 more update
Former-commit-id: f64d9a30057d587ef0410ae692800795c29ccdb9
Former-commit-id: 8359b51c881035b3ef822bae1ca2c82e0cd83e93
2017-01-26 01:30:06 +09:00
Song Minjae
2d34db3022 adding/removing actors in game won't go wrong now (perhaps...)
Former-commit-id: c66db4b652e2fae34e66200aca4b101c16bab5d9
Former-commit-id: 5bafa85cabf7ead6db5f48475164d0694f66f15d
2017-01-26 01:29:17 +09:00
Song Minjae
5a76b1cc13 space saving by converting tga back to png on large matte images
Former-commit-id: 8f3289355692b3e73d383522ce037e1233651efc
Former-commit-id: 3710b500b5184c500eb67f44ff0373b7cf00012d
2017-01-25 17:54:05 +09:00
Song Minjae
9aab3d3664 fixed bad light calc from 1b83e7deb7 [formerly d900c0733a6d1dcbd9aaed8e9f7f1671c3866624] [formerly 5611e2d89f4601e57d014c45f0479600778217f6]
Former-commit-id: 7906df081a965ba70224fce4890ec3e067ea1636
Former-commit-id: f63552ac04de18ebc4b3283b87cf803eca5ae347
2017-01-25 17:53:06 +09:00
Song Minjae
c5b452f779 removed red tinge on t=52100+
Former-commit-id: 34c03b14a4103bf64c88fdceb82c5ed13e82858d
Former-commit-id: ad8f050b4906c5582ae895bb9e5032b1e180394c
2017-01-24 14:20:38 +09:00
Song Minjae
95ea8d9b7c more like real MT-32
Former-commit-id: c6af2f7dbf8745488e508127c13a0f5ef3132be9
Former-commit-id: 1df1334644896d4790b42cf2448ef4e902f34bca
2017-01-24 03:36:05 +09:00
Song Minjae
f02c931715 actor draw issue fixed for real this time
Former-commit-id: 16d315a8df6477748bdb78b567ee1c97ffc2f455
Former-commit-id: 96c8efc59b69c78ae7c861ebd371fc315d3be058
2017-01-24 03:35:37 +09:00
Song Minjae
225f2f2235 VT redraw on request
Former-commit-id: 3ada71215d9291760704a982cc3952061dbc7afe
Former-commit-id: ca1495e668e88bc7214429472ad918621a650189
2017-01-24 00:50:12 +09:00
Song Minjae
1b83e7deb7 tiles with light level <= 1 will be rendered as black square, phys support for non-self-moving bodies (e.g. balls)
Former-commit-id: 5611e2d89f4601e57d014c45f0479600778217f6
Former-commit-id: d900c0733a6d1dcbd9aaed8e9f7f1671c3866624
2017-01-23 19:06:12 +09:00
Song Minjae
e951a6285e replaced quick and dirty fix into proper fix
Former-commit-id: ee305ad1bb84716a0bb8c17e9aa873eafb0baa6e
Former-commit-id: a9d7e6495bbfdea42b253070f66a0978463a8814
2017-01-23 19:04:42 +09:00
Song Minjae
0717b883b4 README update
Former-commit-id: 425ceb7e5fec5ce0cbcc28bd657e7c6360d9d47f
Former-commit-id: e2e348bc8425861f4263ffba483f04a2837c5c51
2017-01-23 19:03:08 +09:00
Song Minjae
6c94dc9632 iterative circular array for slightly better performance (test might be wrong tho)
Former-commit-id: 95c4e576efca6e12af68c184ed5effa4b115d8c4
Former-commit-id: bbd74994f90f582d0643ebbbca58f40d097e2f82
2017-01-22 14:20:24 +09:00
Song Minjae
54b52b1b6e more efficient particles
Former-commit-id: 56dad88ecd715ad6e357e33b903851a47a358dcd
Former-commit-id: c85c0b759a447c0461563d98156f59879fa95db2
2017-01-22 04:13:45 +09:00
Song Minjae
4acc797fee actorwithbody splitted in favour of new particle type
Former-commit-id: 121bd069d0a9eeef60f5ecb085a11a93c4b4a84d
Former-commit-id: 539b4b6916e808c01298190cf347e928f61fe62e
2017-01-21 16:52:16 +09:00
Song Minjae
5db3aadaf4 ai won't jump if it sees tall ledge that can't jump over
Former-commit-id: c74b12206547838c72301d3d2223a98c9098687d
Former-commit-id: a1f7c29cc42758f92c202d20d28e47820546c900
2017-01-20 01:56:29 +09:00
Song Minjae
02f38eab3c actor jump slowdown in water
Former-commit-id: 45fdd22f084ec4e9a9017bd617393c9e6acd56e8
Former-commit-id: bf1bbc9210bd2232381116312447724976aaf1f8
2017-01-19 13:43:38 +09:00
Song Minjae
b08060bffc fixme: fixed
Former-commit-id: a8beadca625c0714d687784c95a39e1ddbf7559c
Former-commit-id: 936a978f2d50e313611f3417f0e5a7cee716896e
2017-01-19 04:10:31 +09:00
Song Minjae
fdecb83ebf correct actor walk velo/accel control even when submerged; new tileprop Viscosity
Former-commit-id: 164238c9e5e0b33f9291cb09d804e2ce2f2e1721
Former-commit-id: ec07a206dd980b9ee73530f0beab876393030656
2017-01-19 04:05:57 +09:00
Song Minjae
e139fb891f proper impl of walk friction control (WIP submerged case)
Former-commit-id: cf8c11dee3eed491893bbfa61167e47863524366
Former-commit-id: 30a8fbedcc05cb6aee5f131708152d4db1fd9415
2017-01-19 03:25:22 +09:00
Song Minjae
efbb654b45 skybox
Former-commit-id: 839fda074d5cf6a3fe1a0a16e10da67908bc4f03
Former-commit-id: 4ed8324110eafc434fd00f09fe48f3858ad5fd3a
2017-01-18 21:24:59 +09:00
Song Minjae
ea4c4bdb2b new sunlight and skybox colouring collected from real world measurements (reports TBA)
Former-commit-id: 6abaa1e16d0fd7a71f95bd0265809aad9e34a425
Former-commit-id: bb871bd87072f27b9cc29594f9eed615351df5f8
2017-01-17 23:42:25 +09:00
Song Minjae
e9c7ef4930 PNG -> TGA
Former-commit-id: 394d3af24b5f1a125c40197a09f47867cc6fc566
Former-commit-id: 5428b1d2d7370b5a912851d5f5aa9f6b036f64f5
2017-01-16 18:24:19 +09:00
Song Minjae
1f1e2f6899 colorutil update, some code cleanup
Former-commit-id: 47b13e7e899dc9151f7a1ae71977ed8d4b403345
Former-commit-id: 136f9c787b76aec75d76535891cf264170bd3b04
2017-01-15 20:51:42 +09:00
Song Minjae
e7276513d7 new hair finished
Former-commit-id: bed636531552e3c6e6f2abf80d1e2550f22075d2
Former-commit-id: ced0e4dc213a6f711b7f450458ec745fff5d91e1
2017-01-14 16:00:43 +09:00
Song Minjae
8ae07c8d20 working tapestry decoder and fixture object
Former-commit-id: dd61b61e6061cfb3dc2ad9d9f65fd1b272475718
Former-commit-id: 7acc72a0e59203c0ea56c355eadaeed1474e3ac1
2017-01-14 16:00:07 +09:00
Song Minjae
bac246cd9a corrected candlelight colour (using Yxy instead of Lab)
Former-commit-id: 7d784a840c2339a49f1dfc5a739bf8ce306ec2e4
Former-commit-id: d3b18605dd51ceb779841835c88802b8cf3afaa4
2017-01-13 12:33:02 +09:00
Song Minjae
ec73d2ea1e Parallel: wait for all ths to die
Former-commit-id: d95a5fc60c424cb1722d70ced610a81237ddb681
Former-commit-id: 64d1177a164a2a53e9beabe634a6f5997cfa8d7b
2017-01-12 21:05:23 +09:00
Song Minjae
213831ad31 StateBlurTest from blur test (gah)
Former-commit-id: ea7d2b3cd9c5f072846aea102b43f09226f73a57
Former-commit-id: 3d716699cbf6ed344c5e7b2ab5a2f8b121f828a8
2017-01-12 21:04:29 +09:00
Song Minjae
b52d6f89f7 new hair (wip?)
Former-commit-id: 31cd1b402be82b34487b92c3fd3f05da15d5e2f6
Former-commit-id: 826df0dfc7e8a885ba681dc9ba0c05fa610eb44f
2017-01-12 21:03:44 +09:00
Song Minjae
dfb769c982 test image from blur test
Former-commit-id: 6f4ebae0f8fe170567082f1e9973763d5c0e3654
Former-commit-id: 48712cd1144ab3718e568945b9dd39d8db710708
2017-01-12 21:03:31 +09:00
Song Minjae
9e9bca3442 now torch colour from colourimeter mesurement
Former-commit-id: 8bd0eb9ef67e2a5c259137ea779b857daac792bc
Former-commit-id: 5aa153a8cd3e94fc663d071f033fe3d5cdafed1b
2017-01-12 21:02:59 +09:00
Song Minjae
b1686ec5ab blur test
Former-commit-id: 33120239e532c01aedbc409dd224fdf3e6b58ee1
Former-commit-id: 8dd650ee0704c9dfbf83dc81b4c3c7b53af52647
2017-01-12 21:01:58 +09:00
Song Minjae
d076676a2f sample code for software rendering
Former-commit-id: a9d5b8e49305af4a406a7842469086438494b12c
Former-commit-id: 372ef77b6562942fd74128dffda22bf34a5df7fa
2017-01-12 02:27:06 +09:00
Song Minjae
1e89ddfec7 added endianness
Former-commit-id: c3ec99b381816d0a4afb245a1dc4623db2f59f88
Former-commit-id: 19d8e083f74f0281ae91df8bf89f046cb7b78d43
2017-01-10 00:02:19 +09:00
Song Minjae
1c5ee6f32c data formats doc update
Former-commit-id: b1e1da4b568e9d282874e73e867a6449560337b4
Former-commit-id: df35e8acb0b981122402736735f69009820af960
2017-01-09 23:48:57 +09:00
Song Minjae
083197f4cb updated pal on TextTerminal to match the game's 16 pal
Former-commit-id: f96c58b1a29e71d9877c824631dd252956dbc321
Former-commit-id: 1224ec4e300d44fa05a7aef39eedbaea0cad4f56
2017-01-09 23:28:21 +09:00
Song Minjae
135f8f86e8 fixed discrepancy between 64- and 16-colour palettes
Former-commit-id: 71fdc236220f77fd3f3eb7fef9bf9c75d1a10996
Former-commit-id: d3ffbfa92e18fdd36e07607faddaadb8faa5739d
2017-01-09 23:25:57 +09:00
Song Minjae
f7d055806b sprites!
Former-commit-id: 099c7d1b27988830f6c2d876684d4675078170e9
Former-commit-id: eea5b0ff2a04142e1a19505a98c252a6ca5aa666
2017-01-09 23:22:31 +09:00
Song Minjae
5944a215df README update
Former-commit-id: 79ea4bbfe747c18b4401e037aa350c23a9dc7fa2
Former-commit-id: 4feab90a769c9a8a52acc3a0b7223813c193756a
2017-01-09 23:21:58 +09:00
Song Minjae
0f8f64cddf wall now uses terrain tileset
Former-commit-id: 13b5389d905c1c302ec4e7991fbfdd06ed333814
Former-commit-id: 1416055d9aa0755147c461512f9b638e25df908e
2017-01-09 22:56:15 +09:00
Song Minjae
0b7485fd57 less saturated red sands
Former-commit-id: fc87746519435da0e77fe4381190a9a9e52ac3cb
Former-commit-id: 132451d755ed806850af59c9f660c21a88666142
2017-01-09 19:46:42 +09:00
Song Minjae
e499c24c0d AI auto jump test
Former-commit-id: f48972fa48a526e8f697a47cde90b26240f549a3
Former-commit-id: c45dcbcae2f7d85c801ed87c049c403609a6d6d0
2017-01-07 00:37:46 +09:00
Song Minjae
aab8da6ac7 "heavier" jump control, closing issue #10
Former-commit-id: 5329d496cff482083243e2002472496347c624f3
Former-commit-id: 99dd9f51f4790444ea950368453f74aef8441d44
2017-01-06 03:59:09 +09:00
Song Minjae
ea73ff3153 16/64 tapestry palettes, sample tapestry image (theworld)
Former-commit-id: 74858cf3203e1da643e50d57b277d18d4a516735
Former-commit-id: 92a626c5a2e340d0d6995d14c7724e7de58bc1e6
2017-01-06 00:02:49 +09:00
Song Minjae
4b54fb3b67 lang update
Former-commit-id: 89a4f1725dbe386aede2954d88c3465ffaa8dba2
Former-commit-id: 7ba3fee3c2ca48dfabd879c9e19c0b3fb8deadf0
2017-01-06 00:00:41 +09:00
Song Minjae
4d8ff11ece issue #9
Former-commit-id: 8e4257f62c97c5b8defd9d722624fb1448e0209a
Former-commit-id: 01e47cdbe82ab0832695f6d6b0cbd6cf5ddf1458
2017-01-04 23:04:27 +09:00
Song Minjae
3eb1fe98cd sprite updates
Former-commit-id: a52e024a231e54e7e837b7c717606f4f0d187758
Former-commit-id: fcdb5a9e12802c9671bea24481c94a8876dfd418
2017-01-04 22:46:51 +09:00
Song Minjae
df8c0813c3 fuck
Former-commit-id: c48f789e138b5d9f78422a5ec93f4f973225fe2f
Former-commit-id: 9843d2c1482d6bd38c65bc2036696dce5901dd91
2017-01-02 14:32:23 +09:00
Song Minjae
ae97310bf7 circular (octagon actually) propagation of light
Former-commit-id: 1e67a3284ea298a0d8f27309d9d8ca800a8525c8
Former-commit-id: a5067df80d1053ceec6d78b6fda6cf0afa3c286c
2017-01-02 14:08:24 +09:00
Song Minjae
0c2cb48135 ThreadPool renamed to PhreadParallel, tweaks on font
Former-commit-id: 52c6d53764449cecd9ab1aa96b23810e5e406cc2
Former-commit-id: cf8ff86f3c62851c8be2370774b426e09410ad6f
2017-01-01 15:06:19 +09:00
Song Minjae
f5f0fcb077 Copyright update 2017
Former-commit-id: 8c662c7cb637ae4565e95e661b0e627d9bfd7e5a
Former-commit-id: 4a5279b47f7c8f4fadb62ee6843b3848f803f433
2017-01-01 00:04:43 +09:00
Song Minjae
d3080ffb78 added sources for Slick
Former-commit-id: 1647fa32ef6894bd7db44f741f07c2f4dcdf9054
Former-commit-id: 0e5810dcfbe1fd59b13e7cabe9f1e93c5542da2d
2016-12-30 23:29:12 +09:00
Song Minjae
d1f01a203d getActorByID now searches for inactive actors
Former-commit-id: 1828e2819bc5575d590e51b616415c91645cad56
Former-commit-id: 5b470d524401135358f9926587651ae932d4d5e9
2016-12-30 23:28:44 +09:00
Song Minjae
da06e0fa93 mouse buttons now configurable
Former-commit-id: 789b34a0a80553afc7fa7f563ffa33350310ac21
Former-commit-id: 8b3687ee15aa53fb6decb8480ebdf6897b5cce61
2016-12-30 23:28:06 +09:00
Song Minjae
0b024dcf70 issue #7 implemented
Former-commit-id: e63de56e81e19c842c519c77019b9750d751851e
Former-commit-id: 6b018d6ac3bb471d5997c1eece4485f967f82ded
2016-12-30 18:07:36 +09:00
Song Minjae
ac05b5edf1 separated Camera from TileDrawer (was MapCamera)
Former-commit-id: b2fe7716722634b03f3750fade420d26022500f9
Former-commit-id: 521826d176c6902007646e6b9b9c7b5d4f3468cf
2016-12-30 02:47:15 +09:00
Song Minjae
9a8090038e improved ActorValueTracker: can now change actor currently tracking
Former-commit-id: 71daf44209f700b8702f2b73294583edefda49c9
Former-commit-id: 3ab76c6509086490ba6ea9501b1ba08e444a7e53
2016-12-30 02:22:58 +09:00
Song Minjae
0e60380718 skybox will now scaled properly according to screen zoom
Former-commit-id: 619bfcad7bd14313d8f94c291350ddb5bb9684b4
Former-commit-id: c42d41c7e32a2c44cffc7d1450fa550d7d5c32f7
2016-12-30 02:22:10 +09:00
Song Minjae
71294a6bd1 64 colour palette test
Former-commit-id: 44420079369d6a7ea4752d390608ca2174594a99
Former-commit-id: 84c6fcd4f7deb0e8648e0e8a8b6cf578ff872cb4
2016-12-29 21:35:46 +09:00
Song Minjae
f4332afd3c better character shading
Former-commit-id: 8c10062edbb66c1a184f24067873deaf59d0447f
Former-commit-id: 4193fcfa61d3d14e82622f6bf6849cd75377c4ee
2016-12-29 21:35:28 +09:00
Song Minjae
f7365ea47b more AI, divided ACCELBUFF and ACCELMULT_MOVEMENT
Former-commit-id: f3b4c390c363612dcc58c3d50cb7a47ba7452567
Former-commit-id: 95f71db97104cf55af7aba8e0289eb89efc078a4
2016-12-29 21:10:42 +09:00
Song Minjae
63bc018550 new debugging tool ActorsList
Former-commit-id: 51109b6766a1ebd92613055064e3fa8bd69c37fc
Former-commit-id: d5fc3d52b208d3cbbdcec47758cd73aef3240dc8
2016-12-29 21:09:44 +09:00
Song Minjae
bc36cc946d highest ID of dynamicItem reduced to 1048575
Former-commit-id: b1e36d020a57aac497eff5d3db7142940f590fe4
Former-commit-id: c437e8447ba2a58fdc7dfd05f1ac80284f845702
2016-12-29 20:45:42 +09:00
Song Minjae
767802e75f new debugging tool ActorValueTracker
Former-commit-id: f30d2a859521082609425722edb91d3c366fbc58
Former-commit-id: 1486ad6b0a85415124c87522f07c012d4a335567
2016-12-29 20:31:05 +09:00
Song Minjae
a6bbf256f0 Issue #6 resolved
Former-commit-id: 643ca0b3757f329107a7677fe3bf5f43ffac7639
Former-commit-id: caa5582abb797485e90b8c3e47a6307b177ff456
2016-12-28 18:17:48 +09:00
Song Minjae
e253641471 ActorAI's walk speed can be adjusted now
Former-commit-id: 556677bddf9cc29358471c81f7febc40e8e6cc7d
Former-commit-id: 35b994001dd034e166ba6c6709cb92fd5dca073e
2016-12-28 00:17:52 +09:00
Song Minjae
2e2e4a0281 buffed Teleport command
Former-commit-id: adc06bc2b24f9ac3ef4dc48756a8e3aa006f620f
Former-commit-id: be364044a1a790da69a4a5012f8d6b832f16abd9
2016-12-27 22:43:30 +09:00
Song Minjae
433612ebdb random roam around AI
Former-commit-id: 5edf7e848f519d440ecb915b7d6e27e9ead8dd6f
Former-commit-id: e89bfcd8b443c77e88d5ec7090f836b77ae5f02b
2016-12-27 22:43:15 +09:00
Song Minjae
f06c6f7502 Joise updated to 1.0.2
Former-commit-id: 8fdfe95a5a2be895b55785b1cfc57ae16e10100a
Former-commit-id: 52248306c1b226bca423415d76b0f929e285103e
2016-12-27 22:08:33 +09:00
Song Minjae
81e9539381 AI script is now persistent (you can keep variables)
Former-commit-id: 20ca0a8e80f0712c4a3d6a21ee9ae5f15c46c406
Former-commit-id: 2f1cfc2c9b60981053e928a3e7b07117d3b18919
2016-12-27 21:56:34 +09:00
Song Minjae
e88124f065 "mult" renamed to "buff" to prevent confusion with pre-calculated "mult" (character variants)
Former-commit-id: 104d0a57bc67491427d823c2f91688c85e8841c5
Former-commit-id: 5a835c7a759006df25d8783f4f97b568a1517104
2016-12-27 21:56:03 +09:00
Song Minjae
35a723ee0f actor AI from Lua script
Former-commit-id: 184160efc59c4f846f1cc154fe3e60d21b301ee3
Former-commit-id: 4e228542975ea52945a597b7ca1bc06b407c3be7
2016-12-26 23:55:54 +09:00
Song Minjae
d0109a88af remove hard-drawn shadow from images, they're now drawn by the software
Former-commit-id: fe09a6ba3dd3b2f9e53874c854210f4f73bac160
Former-commit-id: f2b1571609c36cf4e177488ed2978df671ffa80a
2016-12-26 12:50:10 +09:00
Song Minjae
5e2cb526ee cp949 -> cp437 (wrong name)
Former-commit-id: 07e737dfa438bac2b42271a35f3e1d3aa0e9f041
Former-commit-id: 158c2c7c6dbd324f55727eed057c21bdb2cf8908
2016-12-26 12:36:02 +09:00
Song Minjae
8e6fc55f46 javadoc for LWJGL
Former-commit-id: c9c053368cf5b7bbaf7aa2aa1a986611c3dad698
Former-commit-id: a9835ae3c2b484bcb5b1ee6fa57504c406c61490
2016-12-26 12:00:28 +09:00
Song Minjae
ae45cf32a7 new blending function for SpriteGlow, which now uses no alpha channel; reduced the number of framebuffer used to draw a world from 2 to 1.
Former-commit-id: 823182690f0c0dfc73a46474e194cbf6470fe5ad
Former-commit-id: 9c4e041ef2799841d905c2b6dc32d578d9c082a3
2016-12-25 16:33:56 +09:00
Song Minjae
a9a2b93341 visible actors are defaulted to Visible, SpriteAnimations now has "parent" actors and uses its Visible property
Former-commit-id: 0e240de4ca38a59724f364df4624c8dc79c0112d
Former-commit-id: b017b24ab7591ea2fd2518308bd5656597c14f47
2016-12-23 20:49:29 +09:00
Song Minjae
639f1c158e multithreading now should divide jobs evenly without any job missing out
Former-commit-id: 0511065489b0813fef82361b74369040fc2ad887
Former-commit-id: fe23e50fa33d6cf0c5118916bb29669d69bed5b9
2016-12-23 00:38:21 +09:00
Song Minjae
1362f6921e resolving issue #5
Former-commit-id: 12d11b683a242172a7c3ec831efb7d65f552951f
Former-commit-id: fd276318b77ac5ef9b1963e84fb33380ddbae45c
2016-12-22 22:20:49 +09:00
Song Minjae
611b78ffa5 texture update
Former-commit-id: 8b056329db1403b163e635e22141e0d021580805
Former-commit-id: c9e0605ba6021ac4889f199799268df61517a794
2016-12-22 13:21:03 +09:00
Song Minjae
c1e7b3537d noise texture generator: multithreded
Former-commit-id: 4d9539a53aa058eff1fe47f6fce95528a44dff40
Former-commit-id: a0301f167412d1c67ca0cc6956d9e7683e82efaf
2016-12-22 13:19:40 +09:00
Song Minjae
72e348b5e5 messing around w/ GL blend equations, think got something working...
Former-commit-id: 6c9bb1a9d49c9ea0a5f8a68f4b2d05b0d8390b96
Former-commit-id: 7947f3b32dbe0d17a7bd206b3fd8850fdf3ea9c1
2016-12-22 03:05:13 +09:00
Song Minjae
e76f8840ba updating TODO tags
Former-commit-id: f0ce830cc72911b9c1974a394581003726dfc4e1
Former-commit-id: dfc012568d8362de583b7efa95fd79e35a22b83a
2016-12-22 02:20:23 +09:00
Song Minjae
656aa07e8b new dirt tex
Former-commit-id: 963c5f0ec46eeb950b56a357df3cfe352c9d60c1
Former-commit-id: 38e1c52cbf3001013399d015c3bca678f77745dc
2016-12-22 02:19:57 +09:00
Song Minjae
4548a2fe3d noise pattern generator (loops x and y)
Former-commit-id: 548612468f454aaf037544e5c3a86deb4f30fc63
Former-commit-id: 1026b3d7420fd5a14117e4c295009dc5831862ad
2016-12-22 02:02:13 +09:00
Song Minjae
70d85398ce cavegen now loops (fine-tune required)
Former-commit-id: 5a59323f39ca1cfcfcc0c89c0d7f71f0e2d92762
Former-commit-id: f7d35ae69fcb49af0d1342624eb9f3b0027db398
2016-12-21 01:06:05 +09:00
Song Minjae
dd60448cae seamlessly looped terrain generation WIP (resolving issue #4)
Former-commit-id: cb2110fc1574ddfbff9ea6bd21596945c5895e13
Former-commit-id: 4f17d4d0bb1b1ed1ee61872651abfeb046de8b9c
2016-12-20 21:01:22 +09:00
Song Minjae
8c8a0cbb23 modified light penetration to penetrate less
Former-commit-id: 43b6fa9456ab58d6c59b738c718d0dcbe27799d1
Former-commit-id: ac3da567accddaea19ede6f7fcf59aff4cc10c9a
2016-12-20 14:37:29 +09:00
Song Minjae
e0665db121 fixed bug in commandinterpreter where space(s) behind semicolon, without secondary command (e.g. "nc; ") caused crash
Former-commit-id: 6b7afd141964ecefaae4f8952551859ca6c25c9d
Former-commit-id: dd21356206c45bde1c9f17fc604755d372189d7e
2016-12-20 14:35:49 +09:00
Song Minjae
aeb377a857 more sprite glow (test)
Former-commit-id: 857997e5a00ccbb3f3d2ca7be5065f4f66487a4f
Former-commit-id: 232ae9161a43762730fad1e77003b4033d72bb2a
2016-12-19 00:56:59 +09:00
Song Minjae
e501b356cd colourmaps for virtualcomputers, adding 64-col
Former-commit-id: 7db2015263d5a48eda8f96e215352d62f6e23602
Former-commit-id: c0df19ce699cc19c72e0a67133dba129cd98f9dd
2016-12-19 00:15:54 +09:00
Song Minjae
01def757e9 minor edits
Former-commit-id: 727c880ff913f72cf17f89155c35966f38224c07
Former-commit-id: 65d4bf1045440de7d23efd3ef43176e1cddfa1e4
2016-12-18 23:21:51 +09:00
Song Minjae
ea1e90b035 working platform rendering
Former-commit-id: ec50eeb7f6fbf5799d197a88b036f60e51693336
Former-commit-id: 4172ffc733b8df89bc839b59476c57ac6bf3572d
2016-12-18 16:18:41 +09:00
Song Minjae
0db1130b41 working zoom out
Former-commit-id: a53ed485163ef36cf5b59941eb657761cde166d5
Former-commit-id: a2b575150e128ceb7894d9ba4eb0db127d071bcb
2016-12-18 03:09:20 +09:00
Song Minjae
1ad9f2611d working ZOOM IN (zoom out still broken)
Former-commit-id: 40d72f2ebfcaffe40e1875a7a76d05ff06ad0323
Former-commit-id: c5fae728ab10693f0fb7ae1ece109ad88cbedd0c
2016-12-18 02:41:23 +09:00
Song Minjae
9c7e7ed266 fixed roundworld anormaly, camera zoom still broken
Former-commit-id: ec08c302349c962992a111e820b60eb0a46d7c2e
Former-commit-id: 5bcf3baf2ec194c431b009aa2839ff11caa4d82d
2016-12-18 01:39:03 +09:00
Song Minjae
56530a6041 code cleanup, shortening things
Former-commit-id: d1c81cf3207fff4dd311e9b6c3beb04c194aebc5
Former-commit-id: 26f5042ba41cd577e681a22465435945434c864b
2016-12-17 14:16:42 +09:00
Song Minjae
af8516be68 cleaning up code, adaptive CCD displacement tick
Former-commit-id: dff86e81e174f3cb12a3b5fde54d67104f84f146
Former-commit-id: 349213aafe52ddbd52ed7b58d42a81237a84ee3d
2016-12-17 11:38:43 +09:00
Song Minjae
9df31df54f no more gradle
Former-commit-id: 0f6743976fa4337a40e60eb18b7b3e3a91ca0a7d
Former-commit-id: e8749adce56c47c03a86249edc2199884b1ab148
2016-12-17 00:59:54 +09:00
Song Minjae
b66b02ceeb forEach codes for occupying and feet tiles
Former-commit-id: f8a719b262420d673b3672f7e21764a0dbc754b9
Former-commit-id: e09af27d09cb7ab1dbe08637b4a8690ab612466c
2016-12-17 00:31:19 +09:00
Song Minjae
7a7fac776a tilewiseHitbox takes nextHitbox
Former-commit-id: c6bc5c935f4a79687eecf14ef321c16066607e35
Former-commit-id: 72a0f51b7c676f5206848ed56cc62b1f7fe94e52
2016-12-17 00:30:47 +09:00
Song Minjae
d179d090c5 tiles won't place to the position where occupied by actors
Former-commit-id: 745558470933aea8d1f03da30ca5042a82c69eac
Former-commit-id: 09e741f5eaec3eb18b8a76c82fcc2aa62378e82e
2016-12-16 23:57:46 +09:00
Song Minjae
174a0f9101 added sugar to the Hitbox: Can use both (x1, y1, x2, y2) and (x1, y1, w, h)
Former-commit-id: d8d62440493bf1ffe4f15420f85d0973c9de79ed
Former-commit-id: c66228059d46a1258257c2c0ceb64da99ecd2871
2016-12-16 23:57:08 +09:00
Song Minjae
fd7a629757 UML updates and an error correction
Former-commit-id: 2458f3e7485f766644ce7382552084889aea8b96
Former-commit-id: 8cc0ce08fcfd8f61b38152de95e484cad2034639
2016-12-16 23:11:40 +09:00
Song Minjae
a5ca82f2c7 get operator on Tile/ItemPropCodex
Former-commit-id: f6c4ecbad8c0ce2486524be70e68292d6aae799e
Former-commit-id: 9738a693eb55861d1292e59d8df2bec7f5603c40
2016-12-16 23:07:14 +09:00
Song Minjae
4552d7b7db Inventory now stores objects instead of item IDs
Former-commit-id: 6d7397fe82c986a3ac48ce86fe9fa75a354cf5d3
Former-commit-id: 46b759e0707fe2f7cb207e215708118034aff4f4
2016-12-16 23:02:21 +09:00
Song Minjae
fe994621c0 InventoryItem is now abstract class
Former-commit-id: b7d22a2cc169a89cbe82aae8b13277b1be747b94
Former-commit-id: dcbf2bf830046b97673a0d2bab65e53c4451966f
2016-12-16 23:01:17 +09:00
Song Minjae
5dc99f5612 equip item by body parts
Former-commit-id: 34294de21d16c03da98427edae3b3c6ed94088aa
Former-commit-id: b37fe27635b1643e72e8f714bfea6ce214006931
2016-12-16 18:56:13 +09:00
Song Minjae
1d1769a2c3 working proof-of-concept inventory system
Former-commit-id: 1be5d6d10d0a5c93bceaf12f15d2ee50602cb602
Former-commit-id: 44f25a27c3b5d196210f4efcc3fef4dec8e30ff7
2016-12-14 15:41:20 +09:00
Song Minjae
7078ecfed4 Echo().execute(message) is now just Echo(message)
Former-commit-id: 851e141fc91b170190d6027f42f59906dda0f31f
Former-commit-id: 03dbb9da1788e1c50e84ae33d95f76194ad9a08d
2016-12-14 12:40:53 +09:00
Song Minjae
1dd156d172 still WIP inventory impl, held item impl
Former-commit-id: 9468cfae21ff09c3dd30352a849910364e01d780
Former-commit-id: 50247ccebf3284f739877a1d6c6d8574449a9824
2016-12-14 00:28:42 +09:00
Song Minjae
22bb5d83e1 Object-ified console commands (singleton!)
Former-commit-id: d04fc939a659fc4a6b952d64894bd28edf97bc38
Former-commit-id: 6c20526f3bdda2d9d08dc156b3b0fe271e89bffb
2016-12-14 00:28:09 +09:00
Song Minjae
e1642c799c WIP inventory implementation
Former-commit-id: ce7d2125209c2c4f49b7d755b068ce72387f5e8f
Former-commit-id: f413b2699ee7448f3d3b70775ca7b679ade66475
2016-12-12 23:29:13 +09:00
Song Minjae
870c9b36ff youcankillmenow;)
Former-commit-id: 906db790ab715ecdb1b7b9df11c74bc188afceb0
Former-commit-id: c229422f3faeafe31c44870183fa753564b32fa7
2016-12-12 20:35:00 +09:00
310 changed files with 9659 additions and 2943 deletions

22
.gitignore vendored
View File

@@ -1,15 +1,33 @@
# Build-related
out/*
bin/*
build/*
.gradle/*
# Java native errors
hs_err_pid*
# OS files
Thumbs.db
*.jar
.DS_Store
~$*
# Resources that should not be tracked
*.jar
assets/mods/basegame/demoworld
assets/mods/basegame/demoworld.gz
external_resource_packs.zip
# IntelliJ
workspace.xml
# Temporary files
.tmp*
tmp_*
~$*
# Eclipse MAT heap files
*.hprof
*.bin
*.index
*.threads
*_Leak_Suspects.zip

View File

@@ -1,6 +1,6 @@
*Terrarum*
Copyright (C) 2013-2018 Minjaesong (Torvald)
Copyright (C) 2013-2019 Minjaesong (Torvald)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -19,7 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*Terrarum Sans Bitmap*
Copyright (c) 2017 Minjae Song (Torvald) and the contributors
Copyright (c) 2017-2019 Minjae Song (Torvald) and the contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -3,10 +3,10 @@
|0..4095|Tiles (4096 possible)|
|4096..8191|Walls (4096 possible)|
|8192..8447|Wires (256 possible)|
|8448..32767|Items (static) (24320 possible)|
|32768..0x0FFF_FFFF|Items (dynamic\*) (268M possible)|
|0x1000_0000..0x7FFF_FFFF|Actors|
|-2147483648..-1 (all negative numbers)|Faction|
|8448..0x0F_FFFF|Items (static) (1M possible)|
|0x10_0000..0x0FFF_FFFF|Items (dynamic\*) (267M possible)|
|0x1000_0000..0x7FFF_FFFF|Actors (1879M possible)|
|-2147483648..-1 (all negative numbers)|Faction (2147M possible)|
* dynamic items have own properties that will persist through savegame.
@@ -14,7 +14,8 @@ Actors range in-depth
|Range|Description|
|-----|-----------|
|0x1000_0000..0x1FFF_FFFF|Rendered behind (e.g. tapestries)
|0x2000_0000..0x5FFF_FFFF|Regular actors (e.g. almost all of them)
|0x6000_0000..0x6FFF_FFFF|Special (e.g. weapon swung, bullets, dropped item, particles)
|0x7000_0000..0x7FFF_FFFF|Rendered front (e.g. fake tile)
|0x1000_0000..0x1FFF_FFFF|Rendered behind (e.g. tapestries)|
|0x2000_0000..0x4FFF_FFFF|Regular actors (e.g. almost all of them)|
|0x5000_0000..0x5FFF_FFFF|Special (e.g. weapon swung, bullets, dropped item, particles)|
|0x6000_0000..0x6FFF_FFFF|Rendered front (e.g. fake tile)|
|0x7000_0000..0x7FFF_FFFF|Rendered as screen overlay, not affected by light nor environment overlays|

View File

@@ -1,4 +1,4 @@
#version 100
#version 120
#ifdef GL_ES
precision mediump float;
#endif

Binary file not shown.

View File

@@ -10,9 +10,9 @@ uniform sampler2D u_texture;
// "steps" of R, G and B. Must be integer && equal or greater than 2
uniform float rcount = 32.0;
uniform float gcount = 32.0;
uniform float bcount = 32.0;
uniform float rcount = 64.0;
uniform float gcount = 64.0;
uniform float bcount = 64.0;
uniform float acount = 1.0;
int bayer[14 * 14] = int[](131,187,8,78,50,18,134,89,155,102,29,95,184,73,22,86,113,171,142,105,34,166,9,60,151,128,40,110,168,137,45,28,64,188,82,54,124,189,80,13,156,56,7,61,186,121,154,6,108,177,24,100,38,176,93,123,83,148,96,17,88,133,44,145,69,161,139,72,30,181,115,27,163,47,178,65,164,14,120,48,5,127,153,52,190,58,126,81,116,21,106,77,173,92,191,63,99,12,76,144,4,185,37,149,192,39,135,23,117,31,170,132,35,172,103,66,129,79,3,97,57,159,70,141,53,94,114,20,49,158,19,146,169,122,183,11,104,180,2,165,152,87,182,118,91,42,67,25,84,147,43,85,125,68,16,136,71,10,193,112,160,138,51,111,162,26,194,46,174,107,41,143,33,74,1,101,195,15,75,140,109,90,32,62,157,98,167,119,179,59,36,130,175,55,0,150);

View File

@@ -1 +1,3 @@
Air tile (tile 0,0) must have colour of 0x00000000, NOT 0xFFFFFF00. You can modify the tga file directly to correct bad exporter behaviour.
Air tile (tile 0,0) must have colour of 0x00000000, NOT 0xFFFFFF00. You can modify the tga file directly to correct bad exporter behaviour.
All TGA must have alpha premultiplied.

View File

@@ -1,182 +1,158 @@
"id";"drop";"name" ; "shdr"; "shdg"; "shdb"; "shduv";"strength";"dsty";"mate";"fluid";"solid";"clear";"wall"; "lumr"; "lumg"; "lumb";"lumuv";"fall";"dlfn";"vscs";"fv";"friction"
"0"; "0";"BLOCK_AIR" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "1";"null"; "0"; "0"; "1"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"4"
"16"; "17";"BLOCK_STONE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"rock"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"17"; "17";"BLOCK_STONE_QUARRIED" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"rock"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"18"; "18";"BLOCK_STONE_TILE_WHITE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"rock"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"19"; "19";"BLOCK_STONE_BRICKS" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"rock"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"32"; "32";"BLOCK_DIRT" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"dirt"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"33"; "32";"BLOCK_GRASS" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"grss"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"34"; "34";"BLOCK_GRASSWALL" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"grss"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"35"; "35";"BLOCK_FOLIAGE_GREEN" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"grss"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"36"; "36";"BLOCK_FOLIAGE_LIME" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"grss"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"37"; "37";"BLOCK_FOLIAGE_GOLD" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"grss"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"38"; "38";"BLOCK_FOLIAGE_RED" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"grss"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"39"; "39";"BLOCK_FOLIAGE_ICEBLUE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"grss"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"40"; "40";"BLOCK_FOLIAGE_PURPLE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"grss"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"48"; "48";"BLOCK_PLANK_NORMAL" ;"0.1252";"0.1252";"0.1252";"0.1252"; "16"; "740";"wood"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"49"; "49";"BLOCK_PLANK_EBONY" ;"0.1252";"0.1252";"0.1252";"0.1252"; "19";"1200";"wood"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"50"; "50";"BLOCK_PLANK_BIRCH" ;"0.1252";"0.1252";"0.1252";"0.1252"; "15"; "670";"wood"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"51"; "51";"BLOCK_PLANK_BLOODROSE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "17"; "900";"wood"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"64"; "64";"BLOCK_TRUNK_NORMAL" ;"0.1252";"0.1252";"0.1252";"0.1252"; "16"; "740";"wood"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"65"; "65";"BLOCK_TRUNK_EBONY" ;"0.1252";"0.1252";"0.1252";"0.1252"; "19";"1200";"wood"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"66"; "66";"BLOCK_TRUNK_BIRCH" ;"0.1252";"0.1252";"0.1252";"0.1252"; "15"; "670";"wood"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"67"; "67";"BLOCK_TRUNK_BLOODROSE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "17"; "900";"wood"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"80"; "80";"BLOCK_SAND" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"2400";"sand"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "1"; "0"; "N/A"; "0";"16"
"81"; "81";"BLOCK_SAND_WHITE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"2400";"sand"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "1"; "0"; "N/A"; "0";"16"
"82"; "82";"BLOCK_SAND_RED" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"2400";"sand"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "1"; "0"; "N/A"; "0";"16"
"83"; "83";"BLOCK_SAND_DESERT" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"2400";"sand"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "1"; "0"; "N/A"; "0";"16"
"84"; "84";"BLOCK_SAND_BLACK" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"2400";"sand"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "1"; "0"; "N/A"; "0";"16"
"85"; "85";"BLOCK_SAND_GREEN" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"2400";"sand"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "1"; "0"; "N/A"; "0";"16"
"96"; "96";"BLOCK_GRAVEL" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"2400";"grvl"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "1"; "0"; "N/A"; "0";"16"
"97"; "97";"BLOCK_GRAVEL_GREY" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"2400";"grvl"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "1"; "0"; "N/A"; "0";"16"
"112"; "112";"BLOCK_ORE_MALACHITE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"rock"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"113"; "113";"BLOCK_ORE_HEMATITE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"rock"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"114"; "114";"BLOCK_ORE_NATURAL_GOLD" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"rock"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"115"; "115";"BLOCK_ORE_NATURAL_SILVER" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"rock"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"116"; "116";"BLOCK_ORE_RUTILE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"rock"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"117"; "117";"BLOCK_ORE_AURICHALCUMITE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"rock"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"128"; "128";"BLOCK_GEM_RUBY" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"rock"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"129"; "129";"BLOCK_GEM_EMERALD" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"rock"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"130"; "130";"BLOCK_GEM_SAPPHIRE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"rock"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"131"; "131";"BLOCK_GEM_TOPAZ" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"rock"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"132"; "132";"BLOCK_GEM_DIAMOND" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"rock"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"133"; "133";"BLOCK_GEM_AMETHYST" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"rock"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"144"; "144";"BLOCK_SNOW" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24"; "500";"snow"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"145"; "0";"BLOCK_ICE_FRAGILE" ;"0.0508";"0.0508";"0.0508";"0.0508"; "5"; "930";"icei"; "0"; "1"; "1"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0"; "4"
"146"; "146";"BLOCK_ICE_NATURAL" ;"0.1016";"0.1016";"0.1016";"0.1016"; "35"; "930";"icei"; "0"; "1"; "1"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0"; "4"
"147"; "147";"BLOCK_ICE_CLEAR_MAGICAL" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"3720";"icex"; "0"; "1"; "1"; "1";"0.0744";"0.1252";"0.2268";"0.0000"; "0"; "0"; "N/A"; "0"; "4"
"148"; "148";"BLOCK_GLASS_CRUDE" ;"0.0120";"0.0040";"0.0120";"0.0080"; "5";"2500";"glas"; "0"; "1"; "1"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"149"; "149";"BLOCK_GLASS_CLEAN" ;"0.0040";"0.0040";"0.0040";"0.0020"; "5";"2203";"glas"; "0"; "1"; "1"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"160"; "160";"BLOCK_PLATFORM_STONE" ;"0.0312";"0.0312";"0.0312";"0.0312"; "5"; "N/A";"rock"; "0"; "0"; "1"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"161"; "161";"BLOCK_PLATFORM_WOODEN" ;"0.0312";"0.0312";"0.0312";"0.0312"; "5"; "N/A";"wood"; "0"; "0"; "1"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"162"; "162";"BLOCK_PLATFORM_EBONY" ;"0.0312";"0.0312";"0.0312";"0.0312"; "5"; "N/A";"wood"; "0"; "0"; "1"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"163"; "163";"BLOCK_PLATFORM_BIRCH" ;"0.0312";"0.0312";"0.0312";"0.0312"; "5"; "N/A";"wood"; "0"; "0"; "1"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"164"; "164";"BLOCK_PLATFORM_BLOODROSE" ;"0.0312";"0.0312";"0.0312";"0.0312"; "5"; "N/A";"wood"; "0"; "0"; "1"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"176"; "176";"BLOCK_TORCH" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"fxtr"; "0"; "0"; "1"; "0";"1.0000";"0.6372";"0.0000";"0.0000"; "0"; "1"; "N/A"; "0";"16"
"177"; "177";"BLOCK_TORCH_FROST" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"fxtr"; "0"; "0"; "1"; "0";"0.3048";"0.4848";"1.0000";"0.0000"; "0"; "1"; "N/A"; "0";"16"
"192"; "176";"BLOCK_TORCH" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"fxtr"; "0"; "0"; "1"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"193"; "177";"BLOCK_TORCH_FROST" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"fxtr"; "0"; "0"; "1"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"208"; "208";"BLOCK_ILLUMINATOR_WHITE" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.9270";"0.9414";"0.8519";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"209"; "209";"BLOCK_ILLUMINATOR_YELLOW" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"1.0000";"0.8408";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"210"; "210";"BLOCK_ILLUMINATOR_ORANGE" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"1.0000";"0.5294";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"211"; "211";"BLOCK_ILLUMINATOR_RED" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.9188";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"212"; "212";"BLOCK_ILLUMINATOR_FUCHSIA" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.9188";"0.0000";"0.7156";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"213"; "213";"BLOCK_ILLUMINATOR_PURPLE" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.7156";"0.0000";"0.9188";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"214"; "214";"BLOCK_ILLUMINATOR_BLUE" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.0000";"0.1996";"0.9188";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"215"; "215";"BLOCK_ILLUMINATOR_CYAN" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.4621";"1.4188";"1.2368";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"216"; "216";"BLOCK_ILLUMINATOR_GREEN" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.2112";"1.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"217"; "217";"BLOCK_ILLUMINATOR_GREEN_DARK";"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.1252";"0.4068";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"218"; "218";"BLOCK_ILLUMINATOR_BROWN" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.3324";"0.1252";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"219"; "219";"BLOCK_ILLUMINATOR_TAN" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.5864";"0.4068";"0.2032";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"220"; "220";"BLOCK_ILLUMINATOR_GREY_LIGHT";"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.7392";"0.7392";"0.7392";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"221"; "221";"BLOCK_ILLUMINATOR_GREY_MED" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.4576";"0.4576";"0.4576";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"222"; "222";"BLOCK_ILLUMINATOR_GREY_DARK" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.2540";"0.2540";"0.2540";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"223"; "223";"BLOCK_ILLUMINATOR_BLACK" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.2140";"0.0000";"0.4932";"3.7499"; "0"; "0"; "N/A"; "0";"16"
"224"; "208";"BLOCK_ILLUMINATOR_WHITE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"225"; "209";"BLOCK_ILLUMINATOR_YELLOW" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"226"; "210";"BLOCK_ILLUMINATOR_ORANGE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"227"; "211";"BLOCK_ILLUMINATOR_RED" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"228"; "212";"BLOCK_ILLUMINATOR_FUCHSIA" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"229"; "213";"BLOCK_ILLUMINATOR_PURPLE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"230"; "214";"BLOCK_ILLUMINATOR_BLUE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"231"; "215";"BLOCK_ILLUMINATOR_CYAN" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"232"; "216";"BLOCK_ILLUMINATOR_GREEN" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"233"; "217";"BLOCK_ILLUMINATOR_GREEN_DARK";"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"234"; "218";"BLOCK_ILLUMINATOR_BROWN" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"235"; "219";"BLOCK_ILLUMINATOR_TAN" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"236"; "220";"BLOCK_ILLUMINATOR_GREY_LIGHT";"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"237"; "221";"BLOCK_ILLUMINATOR_GREY_MED" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"238"; "222";"BLOCK_ILLUMINATOR_GREY_DARK" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"239"; "223";"BLOCK_ILLUMINATOR_BLACK" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"240"; "240";"BLOCK_SANDSTONE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"1900";"rock"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"241"; "241";"BLOCK_SANDSTONE_WHITE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"1900";"rock"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"242"; "242";"BLOCK_SANDSTONE_RED" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"1900";"rock"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"243"; "243";"BLOCK_SANDSTONE_DESERT" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"1900";"rock"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"244"; "244";"BLOCK_SANDSTONE_BLACK" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"1900";"rock"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"245"; "245";"BLOCK_SANDSTONE_GREEN" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"1900";"rock"; "0"; "1"; "0"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"256"; "256";"BLOCK_LANTERN_IRON_REGULAR" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"fxtr"; "0"; "0"; "1"; "0";"1.0000";"0.6372";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"257"; "257";"BLOCK_SUNSTONE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"rock"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "2"; "N/A"; "0";"16"
"258"; "258";"BLOCK_DAYLIGHT_CAPACITOR" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"glas"; "0"; "1"; "0"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "3"; "N/A"; "0";"16"
"4064"; "0";"BLOCK_LAVA" ;"0.9696";"0.9696";"0.9696";"0.9696"; "100";"2600";"rock"; "1"; "0"; "1"; "0";"0.7664";"0.2032";"0.0000";"0.0000"; "0"; "0"; "32"; "0";"16"
"4065"; "0";"BLOCK_LAVA" ;"0.9696";"0.9696";"0.9696";"0.9696"; "100";"2600";"rock"; "1"; "0"; "1"; "0";"0.7664";"0.2032";"0.0000";"0.0000"; "0"; "0"; "32"; "0";"16"
"4066"; "0";"BLOCK_LAVA" ;"0.9696";"0.9696";"0.9696";"0.9696"; "100";"2600";"rock"; "1"; "0"; "1"; "0";"0.7664";"0.2032";"0.0000";"0.0000"; "0"; "0"; "32"; "0";"16"
"4067"; "0";"BLOCK_LAVA" ;"0.9696";"0.9696";"0.9696";"0.9696"; "100";"2600";"rock"; "1"; "0"; "1"; "0";"0.7664";"0.2032";"0.0000";"0.0000"; "0"; "0"; "32"; "0";"16"
"4068"; "0";"BLOCK_LAVA" ;"0.9696";"0.9696";"0.9696";"0.9696"; "100";"2600";"rock"; "1"; "0"; "1"; "0";"0.7664";"0.2032";"0.0000";"0.0000"; "0"; "0"; "32"; "0";"16"
"4069"; "0";"BLOCK_LAVA" ;"0.9696";"0.9696";"0.9696";"0.9696"; "100";"2600";"rock"; "1"; "0"; "1"; "0";"0.7664";"0.2032";"0.0000";"0.0000"; "0"; "0"; "32"; "0";"16"
"4070"; "0";"BLOCK_LAVA" ;"0.9696";"0.9696";"0.9696";"0.9696"; "100";"2600";"rock"; "1"; "0"; "1"; "0";"0.7664";"0.2032";"0.0000";"0.0000"; "0"; "0"; "32"; "0";"16"
"4071"; "0";"BLOCK_LAVA" ;"0.9696";"0.9696";"0.9696";"0.9696"; "100";"2600";"rock"; "1"; "0"; "1"; "0";"0.7664";"0.2032";"0.0000";"0.0000"; "0"; "0"; "32"; "0";"16"
"4072"; "0";"BLOCK_LAVA" ;"0.9696";"0.9696";"0.9696";"0.9696"; "100";"2600";"rock"; "1"; "0"; "1"; "0";"0.7664";"0.2032";"0.0000";"0.0000"; "0"; "0"; "32"; "0";"16"
"4073"; "0";"BLOCK_LAVA" ;"0.9696";"0.9696";"0.9696";"0.9696"; "100";"2600";"rock"; "1"; "0"; "1"; "0";"0.7664";"0.2032";"0.0000";"0.0000"; "0"; "0"; "32"; "0";"16"
"4074"; "0";"BLOCK_LAVA" ;"0.9696";"0.9696";"0.9696";"0.9696"; "100";"2600";"rock"; "1"; "0"; "1"; "0";"0.7664";"0.2032";"0.0000";"0.0000"; "0"; "0"; "32"; "0";"16"
"4075"; "0";"BLOCK_LAVA" ;"0.9696";"0.9696";"0.9696";"0.9696"; "100";"2600";"rock"; "1"; "0"; "1"; "0";"0.7664";"0.2032";"0.0000";"0.0000"; "0"; "0"; "32"; "0";"16"
"4076"; "0";"BLOCK_LAVA" ;"0.9696";"0.9696";"0.9696";"0.9696"; "100";"2600";"rock"; "1"; "0"; "1"; "0";"0.7664";"0.2032";"0.0000";"0.0000"; "0"; "0"; "32"; "0";"16"
"4077"; "0";"BLOCK_LAVA" ;"0.9696";"0.9696";"0.9696";"0.9696"; "100";"2600";"rock"; "1"; "0"; "1"; "0";"0.7664";"0.2032";"0.0000";"0.0000"; "0"; "0"; "32"; "0";"16"
"4078"; "0";"BLOCK_LAVA" ;"0.9696";"0.9696";"0.9696";"0.9696"; "100";"2600";"rock"; "1"; "0"; "1"; "0";"0.7664";"0.2032";"0.0000";"0.0000"; "0"; "0"; "32"; "0";"16"
"4079"; "0";"BLOCK_LAVA" ;"0.9696";"0.9696";"0.9696";"0.9696"; "100";"2600";"rock"; "1"; "0"; "1"; "0";"0.7664";"0.2032";"0.0000";"0.0000"; "0"; "0"; "32"; "0";"16"
"4080"; "0";"BLOCK_WATER" ;"0.1016";"0.0744";"0.0508";"0.0508"; "100";"1000";"watr"; "1"; "0"; "1"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "16"; "0";"16"
"4081"; "0";"BLOCK_WATER" ;"0.1016";"0.0744";"0.0508";"0.0508"; "100";"1000";"watr"; "1"; "0"; "1"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "16"; "0";"16"
"4082"; "0";"BLOCK_WATER" ;"0.1016";"0.0744";"0.0508";"0.0508"; "100";"1000";"watr"; "1"; "0"; "1"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "16"; "0";"16"
"4083"; "0";"BLOCK_WATER" ;"0.1016";"0.0744";"0.0508";"0.0508"; "100";"1000";"watr"; "1"; "0"; "1"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "16"; "0";"16"
"4084"; "0";"BLOCK_WATER" ;"0.1016";"0.0744";"0.0508";"0.0508"; "100";"1000";"watr"; "1"; "0"; "1"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "16"; "0";"16"
"4085"; "0";"BLOCK_WATER" ;"0.1016";"0.0744";"0.0508";"0.0508"; "100";"1000";"watr"; "1"; "0"; "1"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "16"; "0";"16"
"4086"; "0";"BLOCK_WATER" ;"0.1016";"0.0744";"0.0508";"0.0508"; "100";"1000";"watr"; "1"; "0"; "1"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "16"; "0";"16"
"4087"; "0";"BLOCK_WATER" ;"0.1016";"0.0744";"0.0508";"0.0508"; "100";"1000";"watr"; "1"; "0"; "1"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "16"; "0";"16"
"4088"; "0";"BLOCK_WATER" ;"0.1016";"0.0744";"0.0508";"0.0508"; "100";"1000";"watr"; "1"; "0"; "1"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "16"; "0";"16"
"4089"; "0";"BLOCK_WATER" ;"0.1016";"0.0744";"0.0508";"0.0508"; "100";"1000";"watr"; "1"; "0"; "1"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "16"; "0";"16"
"4090"; "0";"BLOCK_WATER" ;"0.1016";"0.0744";"0.0508";"0.0508"; "100";"1000";"watr"; "1"; "0"; "1"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "16"; "0";"16"
"4091"; "0";"BLOCK_WATER" ;"0.1016";"0.0744";"0.0508";"0.0508"; "100";"1000";"watr"; "1"; "0"; "1"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "16"; "0";"16"
"4092"; "0";"BLOCK_WATER" ;"0.1016";"0.0744";"0.0508";"0.0508"; "100";"1000";"watr"; "1"; "0"; "1"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "16"; "0";"16"
"4093"; "0";"BLOCK_WATER" ;"0.1016";"0.0744";"0.0508";"0.0508"; "100";"1000";"watr"; "1"; "0"; "1"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "16"; "0";"16"
"4094"; "0";"BLOCK_WATER" ;"0.1016";"0.0744";"0.0508";"0.0508"; "100";"1000";"watr"; "1"; "0"; "1"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "16"; "0";"16"
"4095"; "0";"BLOCK_WATER" ;"0.1016";"0.0744";"0.0508";"0.0508"; "100";"1000";"watr"; "1"; "0"; "1"; "0";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "16"; "0";"16"
"-1"; "0";"BLOCK_NULL" ;"4.0000";"4.0000";"4.0000";"4.0000"; "-1";"2600";"null"; "0"; "0"; "1"; "1";"0.0000";"0.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
"id";"drop";"name" ; "shdr"; "shdg"; "shdb"; "shduv";"str";"dsty";"mate";"solid";"plat";"clear";"wall";"fall";"dlfn";"vscs";"fv";"fr"; "lumr"; "lumg"; "lumb"; "lumuv"
"0"; "0";"BLOCK_AIR" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "1";"NULL"; "0"; "0"; "1"; "1"; "0"; "0"; "N/A"; "0"; "4";"0.0000";"0.0000";"0.0000";"0.0000"
"1"; "1";"BLOCK_MIASMA" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "1";"NULL"; "0"; "0"; "1"; "1"; "0"; "0"; "N/A"; "0"; "4";"0.0000";"0.0000";"0.0000";"0.0000"
"16"; "17";"BLOCK_STONE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"17"; "17";"BLOCK_STONE_QUARRIED" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"18"; "18";"BLOCK_STONE_TILE_WHITE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"19"; "19";"BLOCK_STONE_BRICKS" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"32"; "32";"BLOCK_DIRT" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"DIRT"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"33"; "32";"BLOCK_GRASS" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"GRSS"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"34"; "34";"BLOCK_GRASSWALL" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"GRSS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"35"; "35";"BLOCK_FOLIAGE_GREEN" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"GRSS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"36"; "36";"BLOCK_FOLIAGE_LIME" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"GRSS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"37"; "37";"BLOCK_FOLIAGE_GOLD" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"GRSS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"38"; "38";"BLOCK_FOLIAGE_RED" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"GRSS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"39"; "39";"BLOCK_FOLIAGE_ICEBLUE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"GRSS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"40"; "40";"BLOCK_FOLIAGE_PURPLE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"GRSS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"48"; "48";"BLOCK_PLANK_NORMAL" ;"0.1252";"0.1252";"0.1252";"0.1252"; "16"; "740";"WOOD"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"49"; "49";"BLOCK_PLANK_EBONY" ;"0.1252";"0.1252";"0.1252";"0.1252"; "19";"1200";"WOOD"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"50"; "50";"BLOCK_PLANK_BIRCH" ;"0.1252";"0.1252";"0.1252";"0.1252"; "15"; "670";"WOOD"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"51"; "51";"BLOCK_PLANK_BLOODROSE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "17"; "900";"WOOD"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"64"; "64";"BLOCK_TRUNK_NORMAL" ;"0.1252";"0.1252";"0.1252";"0.1252"; "16"; "740";"WOOD"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"65"; "65";"BLOCK_TRUNK_EBONY" ;"0.1252";"0.1252";"0.1252";"0.1252"; "19";"1200";"WOOD"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"66"; "66";"BLOCK_TRUNK_BIRCH" ;"0.1252";"0.1252";"0.1252";"0.1252"; "15"; "670";"WOOD"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"67"; "67";"BLOCK_TRUNK_BLOODROSE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "17"; "900";"WOOD"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"80"; "80";"BLOCK_SAND" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"2400";"SAND"; "1"; "0"; "0"; "0"; "1"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"81"; "81";"BLOCK_SAND_WHITE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"2400";"SAND"; "1"; "0"; "0"; "0"; "1"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"82"; "82";"BLOCK_SAND_RED" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"2400";"SAND"; "1"; "0"; "0"; "0"; "1"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"83"; "83";"BLOCK_SAND_DESERT" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"2400";"SAND"; "1"; "0"; "0"; "0"; "1"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"84"; "84";"BLOCK_SAND_BLACK" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"2400";"SAND"; "1"; "0"; "0"; "0"; "1"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"85"; "85";"BLOCK_SAND_GREEN" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"2400";"SAND"; "1"; "0"; "0"; "0"; "1"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"96"; "96";"BLOCK_GRAVEL" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"2400";"GRVL"; "1"; "0"; "0"; "0"; "1"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"97"; "97";"BLOCK_GRAVEL_GREY" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"2400";"GRVL"; "1"; "0"; "0"; "0"; "1"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"112"; "112";"BLOCK_ORE_MALACHITE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"113"; "113";"BLOCK_ORE_HEMATITE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"114"; "114";"BLOCK_ORE_NATURAL_GOLD" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"115"; "115";"BLOCK_ORE_NATURAL_SILVER" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"116"; "116";"BLOCK_ORE_RUTILE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"117"; "117";"BLOCK_ORE_AURICHALCUMITE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"128"; "128";"BLOCK_GEM_RUBY" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"129"; "129";"BLOCK_GEM_EMERALD" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"130"; "130";"BLOCK_GEM_SAPPHIRE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"131"; "131";"BLOCK_GEM_TOPAZ" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"132"; "132";"BLOCK_GEM_DIAMOND" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"133"; "133";"BLOCK_GEM_AMETHYST" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"144"; "144";"BLOCK_SNOW" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24"; "500";"SNOW"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"145"; "0";"BLOCK_ICE_FRAGILE" ;"0.0508";"0.0508";"0.0508";"0.0508"; "5"; "930";"ICEI"; "1"; "0"; "1"; "0"; "0"; "0"; "N/A"; "0"; "4";"0.0000";"0.0000";"0.0000";"0.0000"
"146"; "146";"BLOCK_ICE_NATURAL" ;"0.1016";"0.1016";"0.1016";"0.1016"; "35"; "930";"ICEI"; "1"; "0"; "1"; "1"; "0"; "0"; "N/A"; "0"; "4";"0.0000";"0.0000";"0.0000";"0.0000"
"147"; "147";"BLOCK_ICE_CLEAR_MAGICAL" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"3720";"ICEX"; "1"; "0"; "1"; "1"; "0"; "0"; "N/A"; "0"; "4";"0.0744";"0.1252";"0.2268";"0.0000"
"148"; "148";"BLOCK_GLASS_CRUDE" ;"0.0120";"0.0040";"0.0120";"0.0080"; "5";"2500";"GLAS"; "1"; "0"; "1"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"149"; "149";"BLOCK_GLASS_CLEAN" ;"0.0040";"0.0040";"0.0040";"0.0020"; "5";"2203";"GLAS"; "1"; "0"; "1"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"160"; "160";"BLOCK_PLATFORM_STONE" ;"0.0312";"0.0312";"0.0312";"0.0312"; "5"; "N/A";"ROCK"; "0"; "1"; "1"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"161"; "161";"BLOCK_PLATFORM_WOODEN" ;"0.0312";"0.0312";"0.0312";"0.0312"; "5"; "N/A";"WOOD"; "0"; "1"; "1"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"162"; "162";"BLOCK_PLATFORM_EBONY" ;"0.0312";"0.0312";"0.0312";"0.0312"; "5"; "N/A";"WOOD"; "0"; "1"; "1"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"163"; "163";"BLOCK_PLATFORM_BIRCH" ;"0.0312";"0.0312";"0.0312";"0.0312"; "5"; "N/A";"WOOD"; "0"; "1"; "1"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"164"; "164";"BLOCK_PLATFORM_BLOODROSE" ;"0.0312";"0.0312";"0.0312";"0.0312"; "5"; "N/A";"WOOD"; "0"; "1"; "1"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"176"; "176";"BLOCK_TORCH" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"FXTR"; "0"; "0"; "1"; "0"; "0"; "1"; "N/A"; "0";"16";"1.0000";"0.6372";"0.0000";"0.0000"
"177"; "177";"BLOCK_TORCH_FROST" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"FXTR"; "0"; "0"; "1"; "0"; "0"; "1"; "N/A"; "0";"16";"0.3048";"0.4848";"1.0000";"0.0000"
"192"; "176";"BLOCK_TORCH" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"FXTR"; "0"; "0"; "1"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"193"; "177";"BLOCK_TORCH_FROST" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"FXTR"; "0"; "0"; "1"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"208"; "208";"BLOCK_ILLUMINATOR_WHITE" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.9270";"0.9414";"0.8519";"0.0000"
"209"; "209";"BLOCK_ILLUMINATOR_YELLOW" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"1.0000";"0.8408";"0.0000";"0.0000"
"210"; "210";"BLOCK_ILLUMINATOR_ORANGE" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"1.0000";"0.5294";"0.0000";"0.0000"
"211"; "211";"BLOCK_ILLUMINATOR_RED" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.9188";"0.0000";"0.0000";"0.0000"
"212"; "212";"BLOCK_ILLUMINATOR_FUCHSIA" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.9188";"0.0000";"0.7156";"0.0000"
"213"; "213";"BLOCK_ILLUMINATOR_PURPLE" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.7156";"0.0000";"0.9188";"0.0000"
"214"; "214";"BLOCK_ILLUMINATOR_BLUE" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.1996";"0.9188";"0.0000"
"215"; "215";"BLOCK_ILLUMINATOR_CYAN" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.4621";"1.4188";"1.2368";"0.0000"
"216"; "216";"BLOCK_ILLUMINATOR_GREEN" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.2112";"1.0000";"0.0000";"0.0000"
"217"; "217";"BLOCK_ILLUMINATOR_GREEN_DARK";"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.1252";"0.4068";"0.0000";"0.0000"
"218"; "218";"BLOCK_ILLUMINATOR_BROWN" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.3324";"0.1252";"0.0000";"0.0000"
"219"; "219";"BLOCK_ILLUMINATOR_TAN" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.5864";"0.4068";"0.2032";"0.0000"
"220"; "220";"BLOCK_ILLUMINATOR_GREY_LIGHT";"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.7392";"0.7392";"0.7392";"0.0000"
"221"; "221";"BLOCK_ILLUMINATOR_GREY_MED" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.4576";"0.4576";"0.4576";"0.0000"
"222"; "222";"BLOCK_ILLUMINATOR_GREY_DARK" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.2540";"0.2540";"0.2540";"0.0000"
"223"; "223";"BLOCK_ILLUMINATOR_BLACK" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.2140";"0.0000";"0.4932";"3.7499"
"224"; "208";"BLOCK_ILLUMINATOR_WHITE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"225"; "209";"BLOCK_ILLUMINATOR_YELLOW" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"226"; "210";"BLOCK_ILLUMINATOR_ORANGE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"227"; "211";"BLOCK_ILLUMINATOR_RED" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"228"; "212";"BLOCK_ILLUMINATOR_FUCHSIA" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"229"; "213";"BLOCK_ILLUMINATOR_PURPLE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"230"; "214";"BLOCK_ILLUMINATOR_BLUE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"231"; "215";"BLOCK_ILLUMINATOR_CYAN" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"232"; "216";"BLOCK_ILLUMINATOR_GREEN" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"233"; "217";"BLOCK_ILLUMINATOR_GREEN_DARK";"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"234"; "218";"BLOCK_ILLUMINATOR_BROWN" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"235"; "219";"BLOCK_ILLUMINATOR_TAN" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"236"; "220";"BLOCK_ILLUMINATOR_GREY_LIGHT";"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"237"; "221";"BLOCK_ILLUMINATOR_GREY_MED" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"238"; "222";"BLOCK_ILLUMINATOR_GREY_DARK" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"239"; "223";"BLOCK_ILLUMINATOR_BLACK" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"240"; "240";"BLOCK_SANDSTONE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"1900";"ROCK"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"241"; "241";"BLOCK_SANDSTONE_WHITE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"1900";"ROCK"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"242"; "242";"BLOCK_SANDSTONE_RED" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"1900";"ROCK"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"243"; "243";"BLOCK_SANDSTONE_DESERT" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"1900";"ROCK"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"244"; "244";"BLOCK_SANDSTONE_BLACK" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"1900";"ROCK"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"245"; "245";"BLOCK_SANDSTONE_GREEN" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"1900";"ROCK"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"256"; "256";"BLOCK_LANTERN_IRON_REGULAR" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"FXTR"; "0"; "0"; "1"; "0"; "0"; "0"; "N/A"; "0";"16";"1.0000";"0.6372";"0.0000";"0.0000"
"257"; "257";"BLOCK_SUNSTONE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"ROCK"; "1"; "0"; "0"; "0"; "0"; "2"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"258"; "258";"BLOCK_DAYLIGHT_CAPACITOR" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "0"; "0"; "3"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"4094"; "0";"BLOCK_LAVA" ;"0.9696";"0.9696";"0.9696";"0.9696";"100";"2600";"ROCK"; "0"; "0"; "1"; "0"; "0"; "0"; "32"; "0";"16";"0.7664";"0.2032";"0.0000";"0.0000"
"4095"; "0";"BLOCK_WATER" ;"0.1016";"0.0744";"0.0508";"0.0508";"100";"1000";"WATR"; "0"; "0"; "1"; "0"; "0"; "0"; "16"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"-1"; "0";"BLOCK_NULL" ;"4.0000";"4.0000";"4.0000";"4.0000"; "-1";"2600";"NULL"; "0"; "0"; "1"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
## Notes ##
#
# Lava/Water props are left for future references, do not delete them until FluidCodex is built #
#
# id: Block ID
# drop: Drop ID
#
# shdr/g/b, lumr/g/b: Shade RGB/ Lum RGB.
# valid range: float of 0..4; 1.0 for 255
# Friction: 0: frictionless, <16: slippery, 16: regular, >16: sticky
#
# solid: whether the tile has full collision (affects physics; flowers are not solid, glass is solid)
# clear: whether the tile has trnasparency (affects render; flowers AND glass is clear)
# clear: [PENDING FOR REMOVAL] whether the tile has trnasparency (affects render; flowers AND glass is clear)
# plat: if the block is a Platform (applicable target: actual platforms, furniture filler block that collision == PLATFORM)
#
# vscs: viscosity, (velocity) / (1 + (n/16)), 16 halves movement speed, can be used to non-fluid tiles (sticky hazard, tarmac road in Terraria)
#
# str: strength
#
# dsty: density. As we are putting water an 1000, it is identical to specific gravity. [g/l]
#
# dlfn: dynamic luminosity function.
# 0-static, 1-torch flicker, 2-current global light (sun, star, moon), 3-daylight at noon,
# 4-slow breath, 5-pulsate
#
# mate: material, four-letter code
#
# fv: vertical friction (boolean)
# fr: horizontal friction. 0: frictionless, <16: slippery, 16: regular, >16: sticky
#
#
## Illuminators ##
# Illuminator white: Mercury Lamp; CIELAB of (94, -5.131, 10.613), which is made out of CIEXYZ of (0.947638, 1.146481, 0.482263), measured with ColorMunki Spectrometer (If you want high CRI lamp, collect a daylight!)
#
# Illuminator white: Mercury Lamp; CIELAB of (94, -5.131, 10.613), which is made out of CIEXYZ of (0.947638, 1.146481, 0.482263), measured with ColorMunki Spectrometer (If you don't want green tinge, collect a daylight!)
# Illuminator orange: Sodium Lamp; CIE xy of (0.5375, 0.4153), CIEXYZ of (352.531139, 272.379377, 30.980339), measured with ColorMunki Spectrometer
# Defalut torch : Y 64 x 0.55183 y 0.40966 (Planckian ~1 770 K); real candlelight colour taken from Spyder5 colorimeter (for I couldn't afford i1DisplayPro/Colormunki)
# Defalut torch : Y 64 x 0.55183 y 0.40966 (Planckian ~1 770 K); real candlelight colour taken from Spyder5 colorimeter (for I couldn't afford i1DisplayPro/Colormunki -- at least back then!)
# Sunstone: Artificial sunlight, change colour over time in sync with sunlight. The light is set by game's code.
# Sunlight capacitor: daylight at noon. Set by game's code.
#
# BLOCK_ILLUMINATOR_CYAN is actually a SUPER_LUMINATOR, cyan colour is used as:
# 1. It has quite a brightness on RGB colour space
# 2. Helmholz-Kohlraush effect
#
#
## Tiles ##
#
# 16 colour palette : games's 16-colour palette
# Magical ice: theoretical __metallic__ ice that might form under super-high pressure (> 5 TPa). Its density is a wild guess.
#
#
## References ##
#
# * Density of various woods : http://www.engineeringtoolbox.com/wood-density-d_40.html
# * Density of various phases of ice : http://www1.lsbu.ac.uk/water/ice_phases.html
#
Can't render this file because it contains an unexpected character in line 1 and column 20.

View File

@@ -0,0 +1,157 @@
"id";"drop";"name" ; "shdr"; "shdg"; "shdb"; "shduv";"str";"dsty";"mate";"solid";"plat";"clear";"wall";"fall";"dlfn";"vscs";"fv";"fr"; "lumr"; "lumg"; "lumb"; "lumuv"
"0"; "0";"BLOCK_AIR" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "1";"NULL"; "0"; "0"; "1"; "1"; "0"; "0"; "N/A"; "0"; "4";"0.0000";"0.0000";"0.0000";"0.0000"
"16"; "17";"BLOCK_STONE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"17"; "17";"BLOCK_STONE_QUARRIED" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"18"; "18";"BLOCK_STONE_TILE_WHITE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"19"; "19";"BLOCK_STONE_BRICKS" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"32"; "32";"BLOCK_DIRT" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"DIRT"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"33"; "32";"BLOCK_GRASS" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"GRSS"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"34"; "34";"BLOCK_GRASSWALL" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"GRSS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"35"; "35";"BLOCK_FOLIAGE_GREEN" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"GRSS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"36"; "36";"BLOCK_FOLIAGE_LIME" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"GRSS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"37"; "37";"BLOCK_FOLIAGE_GOLD" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"GRSS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"38"; "38";"BLOCK_FOLIAGE_RED" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"GRSS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"39"; "39";"BLOCK_FOLIAGE_ICEBLUE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"GRSS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"40"; "40";"BLOCK_FOLIAGE_PURPLE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"1400";"GRSS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"48"; "48";"BLOCK_PLANK_NORMAL" ;"0.1252";"0.1252";"0.1252";"0.1252"; "16"; "740";"WOOD"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"49"; "49";"BLOCK_PLANK_EBONY" ;"0.1252";"0.1252";"0.1252";"0.1252"; "19";"1200";"WOOD"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"50"; "50";"BLOCK_PLANK_BIRCH" ;"0.1252";"0.1252";"0.1252";"0.1252"; "15"; "670";"WOOD"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"51"; "51";"BLOCK_PLANK_BLOODROSE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "17"; "900";"WOOD"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"64"; "64";"BLOCK_TRUNK_NORMAL" ;"0.1252";"0.1252";"0.1252";"0.1252"; "16"; "740";"WOOD"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"65"; "65";"BLOCK_TRUNK_EBONY" ;"0.1252";"0.1252";"0.1252";"0.1252"; "19";"1200";"WOOD"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"66"; "66";"BLOCK_TRUNK_BIRCH" ;"0.1252";"0.1252";"0.1252";"0.1252"; "15"; "670";"WOOD"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"67"; "67";"BLOCK_TRUNK_BLOODROSE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "17"; "900";"WOOD"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"80"; "80";"BLOCK_SAND" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"2400";"SAND"; "1"; "0"; "0"; "0"; "1"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"81"; "81";"BLOCK_SAND_WHITE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"2400";"SAND"; "1"; "0"; "0"; "0"; "1"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"82"; "82";"BLOCK_SAND_RED" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"2400";"SAND"; "1"; "0"; "0"; "0"; "1"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"83"; "83";"BLOCK_SAND_DESERT" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"2400";"SAND"; "1"; "0"; "0"; "0"; "1"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"84"; "84";"BLOCK_SAND_BLACK" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"2400";"SAND"; "1"; "0"; "0"; "0"; "1"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"85"; "85";"BLOCK_SAND_GREEN" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"2400";"SAND"; "1"; "0"; "0"; "0"; "1"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"96"; "96";"BLOCK_GRAVEL" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"2400";"GRVL"; "1"; "0"; "0"; "0"; "1"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"97"; "97";"BLOCK_GRAVEL_GREY" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24";"2400";"GRVL"; "1"; "0"; "0"; "0"; "1"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"112"; "112";"BLOCK_ORE_MALACHITE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"113"; "113";"BLOCK_ORE_HEMATITE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"114"; "114";"BLOCK_ORE_NATURAL_GOLD" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"115"; "115";"BLOCK_ORE_NATURAL_SILVER" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"116"; "116";"BLOCK_ORE_RUTILE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"117"; "117";"BLOCK_ORE_AURICHALCUMITE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"128"; "128";"BLOCK_GEM_RUBY" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"129"; "129";"BLOCK_GEM_EMERALD" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"130"; "130";"BLOCK_GEM_SAPPHIRE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"131"; "131";"BLOCK_GEM_TOPAZ" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"132"; "132";"BLOCK_GEM_DIAMOND" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"133"; "133";"BLOCK_GEM_AMETHYST" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"2400";"ROCK"; "1"; "0"; "0"; "0"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"144"; "144";"BLOCK_SNOW" ;"0.1252";"0.1252";"0.1252";"0.1252"; "24"; "500";"SNOW"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "4";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"145"; "0";"BLOCK_ICE_FRAGILE" ;"0.0508";"0.0508";"0.0508";"0.0508"; "5"; "930";"ICEI"; "1"; "0"; "1"; "0"; "0"; "0"; "N/A"; "0"; "4";"0.0000";"0.0000";"0.0000";"0.0000"
"146"; "146";"BLOCK_ICE_NATURAL" ;"0.1016";"0.1016";"0.1016";"0.1016"; "35"; "930";"ICEI"; "1"; "0"; "1"; "1"; "0"; "0"; "N/A"; "0"; "4";"0.0000";"0.0000";"0.0000";"0.0000"
"147"; "147";"BLOCK_ICE_CLEAR_MAGICAL" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"3720";"ICEX"; "1"; "0"; "1"; "1"; "0"; "0"; "N/A"; "0"; "4";"0.0744";"0.1252";"0.2268";"0.0000"
"148"; "148";"BLOCK_GLASS_CRUDE" ;"0.0120";"0.0040";"0.0120";"0.0080"; "5";"2500";"GLAS"; "1"; "0"; "1"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"149"; "149";"BLOCK_GLASS_CLEAN" ;"0.0040";"0.0040";"0.0040";"0.0020"; "5";"2203";"GLAS"; "1"; "0"; "1"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"160"; "160";"BLOCK_PLATFORM_STONE" ;"0.0312";"0.0312";"0.0312";"0.0312"; "5"; "N/A";"ROCK"; "0"; "1"; "1"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"161"; "161";"BLOCK_PLATFORM_WOODEN" ;"0.0312";"0.0312";"0.0312";"0.0312"; "5"; "N/A";"WOOD"; "0"; "1"; "1"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"162"; "162";"BLOCK_PLATFORM_EBONY" ;"0.0312";"0.0312";"0.0312";"0.0312"; "5"; "N/A";"WOOD"; "0"; "1"; "1"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"163"; "163";"BLOCK_PLATFORM_BIRCH" ;"0.0312";"0.0312";"0.0312";"0.0312"; "5"; "N/A";"WOOD"; "0"; "1"; "1"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"164"; "164";"BLOCK_PLATFORM_BLOODROSE" ;"0.0312";"0.0312";"0.0312";"0.0312"; "5"; "N/A";"WOOD"; "0"; "1"; "1"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"176"; "176";"BLOCK_TORCH" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"FXTR"; "0"; "0"; "1"; "0"; "0"; "1"; "N/A"; "0";"16";"1.0000";"0.6372";"0.0000";"0.0000"
"177"; "177";"BLOCK_TORCH_FROST" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"FXTR"; "0"; "0"; "1"; "0"; "0"; "1"; "N/A"; "0";"16";"0.3048";"0.4848";"1.0000";"0.0000"
"192"; "176";"BLOCK_TORCH" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"FXTR"; "0"; "0"; "1"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"193"; "177";"BLOCK_TORCH_FROST" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"FXTR"; "0"; "0"; "1"; "0"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"208"; "208";"BLOCK_ILLUMINATOR_WHITE" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.9270";"0.9414";"0.8519";"0.0000"
"209"; "209";"BLOCK_ILLUMINATOR_YELLOW" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"1.0000";"0.8408";"0.0000";"0.0000"
"210"; "210";"BLOCK_ILLUMINATOR_ORANGE" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"1.0000";"0.5294";"0.0000";"0.0000"
"211"; "211";"BLOCK_ILLUMINATOR_RED" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.9188";"0.0000";"0.0000";"0.0000"
"212"; "212";"BLOCK_ILLUMINATOR_FUCHSIA" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.9188";"0.0000";"0.7156";"0.0000"
"213"; "213";"BLOCK_ILLUMINATOR_PURPLE" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.7156";"0.0000";"0.9188";"0.0000"
"214"; "214";"BLOCK_ILLUMINATOR_BLUE" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.1996";"0.9188";"0.0000"
"215"; "215";"BLOCK_ILLUMINATOR_CYAN" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.4621";"1.4188";"1.2368";"0.0000"
"216"; "216";"BLOCK_ILLUMINATOR_GREEN" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.2112";"1.0000";"0.0000";"0.0000"
"217"; "217";"BLOCK_ILLUMINATOR_GREEN_DARK";"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.1252";"0.4068";"0.0000";"0.0000"
"218"; "218";"BLOCK_ILLUMINATOR_BROWN" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.3324";"0.1252";"0.0000";"0.0000"
"219"; "219";"BLOCK_ILLUMINATOR_TAN" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.5864";"0.4068";"0.2032";"0.0000"
"220"; "220";"BLOCK_ILLUMINATOR_GREY_LIGHT";"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.7392";"0.7392";"0.7392";"0.0000"
"221"; "221";"BLOCK_ILLUMINATOR_GREY_MED" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.4576";"0.4576";"0.4576";"0.0000"
"222"; "222";"BLOCK_ILLUMINATOR_GREY_DARK" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.2540";"0.2540";"0.2540";"0.0000"
"223"; "223";"BLOCK_ILLUMINATOR_BLACK" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.2140";"0.0000";"0.4932";"3.7499"
"224"; "208";"BLOCK_ILLUMINATOR_WHITE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"225"; "209";"BLOCK_ILLUMINATOR_YELLOW" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"226"; "210";"BLOCK_ILLUMINATOR_ORANGE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"227"; "211";"BLOCK_ILLUMINATOR_RED" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"228"; "212";"BLOCK_ILLUMINATOR_FUCHSIA" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"229"; "213";"BLOCK_ILLUMINATOR_PURPLE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"230"; "214";"BLOCK_ILLUMINATOR_BLUE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"231"; "215";"BLOCK_ILLUMINATOR_CYAN" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"232"; "216";"BLOCK_ILLUMINATOR_GREEN" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"233"; "217";"BLOCK_ILLUMINATOR_GREEN_DARK";"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"234"; "218";"BLOCK_ILLUMINATOR_BROWN" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"235"; "219";"BLOCK_ILLUMINATOR_TAN" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"236"; "220";"BLOCK_ILLUMINATOR_GREY_LIGHT";"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"237"; "221";"BLOCK_ILLUMINATOR_GREY_MED" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"238"; "222";"BLOCK_ILLUMINATOR_GREY_DARK" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"239"; "223";"BLOCK_ILLUMINATOR_BLACK" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"240"; "240";"BLOCK_SANDSTONE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"1900";"ROCK"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"241"; "241";"BLOCK_SANDSTONE_WHITE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"1900";"ROCK"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"242"; "242";"BLOCK_SANDSTONE_RED" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"1900";"ROCK"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"243"; "243";"BLOCK_SANDSTONE_DESERT" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"1900";"ROCK"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"244"; "244";"BLOCK_SANDSTONE_BLACK" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"1900";"ROCK"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"245"; "245";"BLOCK_SANDSTONE_GREEN" ;"0.1252";"0.1252";"0.1252";"0.1252"; "48";"1900";"ROCK"; "1"; "0"; "0"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"256"; "256";"BLOCK_LANTERN_IRON_REGULAR" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"FXTR"; "0"; "0"; "1"; "0"; "0"; "0"; "N/A"; "0";"16";"1.0000";"0.6372";"0.0000";"0.0000"
"257"; "257";"BLOCK_SUNSTONE" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"ROCK"; "1"; "0"; "0"; "0"; "0"; "2"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"258"; "258";"BLOCK_DAYLIGHT_CAPACITOR" ;"0.1252";"0.1252";"0.1252";"0.1252"; "1"; "N/A";"GLAS"; "1"; "0"; "0"; "0"; "0"; "3"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"4094"; "0";"BLOCK_LAVA" ;"0.9696";"0.9696";"0.9696";"0.9696";"100";"2600";"ROCK"; "0"; "0"; "1"; "0"; "0"; "0"; "32"; "0";"16";"0.7664";"0.2032";"0.0000";"0.0000"
"4095"; "0";"BLOCK_WATER" ;"0.1016";"0.0744";"0.0508";"0.0508";"100";"1000";"WATR"; "0"; "0"; "1"; "0"; "0"; "0"; "16"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
"-1"; "0";"BLOCK_NULL" ;"4.0000";"4.0000";"4.0000";"4.0000"; "-1";"2600";"NULL"; "0"; "0"; "1"; "1"; "0"; "0"; "N/A"; "0";"16";"0.0000";"0.0000";"0.0000";"0.0000"
## Notes ##
#
# Lava/Water props are left for future references, do not delete them until FluidCodex is built #
#
# id: Block ID
# drop: Drop ID
#
# shdr/g/b, lumr/g/b: Shade RGB/ Lum RGB.
# valid range: float of 0..4; 1.0 for 255
#
# solid: whether the tile has full collision (affects physics; flowers are not solid, glass is solid)
# clear: [PENDING FOR REMOVAL] whether the tile has trnasparency (affects render; flowers AND glass is clear)
# plat: if the block is a Platform (applicable target: actual platforms, furniture filler block that collision == PLATFORM)
#
# vscs: viscosity, (velocity) / (1 + (n/16)), 16 halves movement speed, can be used to non-fluid tiles (sticky hazard, tarmac road in Terraria)
#
# str: strength
#
# dsty: density. As we are putting water an 1000, it is identical to specific gravity. [g/l]
#
# dlfn: dynamic luminosity function.
# 0-static, 1-torch flicker, 2-current global light (sun, star, moon), 3-daylight at noon,
# 4-slow breath, 5-pulsate
#
# mate: material, four-letter code
#
# fv: vertical friction (boolean)
# fr: horizontal friction. 0: frictionless, <16: slippery, 16: regular, >16: sticky
#
#
## Illuminators ##
#
# Illuminator white: Mercury Lamp; CIELAB of (94, -5.131, 10.613), which is made out of CIEXYZ of (0.947638, 1.146481, 0.482263), measured with ColorMunki Spectrometer (If you don't want green tinge, collect a daylight!)
# Illuminator orange: Sodium Lamp; CIE xy of (0.5375, 0.4153), CIEXYZ of (352.531139, 272.379377, 30.980339), measured with ColorMunki Spectrometer
# Defalut torch : Y 64 x 0.55183 y 0.40966 (Planckian ~1 770 K); real candlelight colour taken from Spyder5 colorimeter (for I couldn't afford i1DisplayPro/Colormunki -- at least back then!)
# Sunstone: Artificial sunlight, change colour over time in sync with sunlight. The light is set by game's code.
# Sunlight capacitor: daylight at noon. Set by game's code.
#
# BLOCK_ILLUMINATOR_CYAN is actually a SUPER_LUMINATOR, cyan colour is used as:
# 1. It has quite a brightness on RGB colour space
# 2. Helmholz-Kohlraush effect
#
#
## Tiles ##
#
# 16 colour palette : games's 16-colour palette
# Magical ice: theoretical __metallic__ ice that might form under super-high pressure (> 5 TPa). Its density is a wild guess.
#
#
## References ##
#
# * Density of various woods : http://www.engineeringtoolbox.com/wood-density-d_40.html
# * Density of various phases of ice : http://www1.lsbu.ac.uk/water/ice_phases.html
#
Can't render this file because it contains an unexpected character in line 1 and column 20.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,13 +1,13 @@
"idst";"dsty";"forcemod";"endurance";"comments"
"rock";"2400"; "1"; "0.42";
"cupr";"1000"; "2"; "1.00";"copper"
"egls";"2500"; "4"; "0.82";"elven glass"
"iron";"1000"; "5"; "1.42";
"argn";"1000"; "9"; "0.91";"argentum/silver"
"stal";"1000"; "14"; "1.73";"steel"
"eaur";"1000"; "21"; "1.36";"elven aurichalcum"
"tial";"1000"; "33"; "2.16";"titanium alloy (Ti6Al4V)"
"admt";"1000"; "71"; "3.42";"adamant"
"ROCK";"2400"; "1"; "0.42";
"CUPR";"1000"; "2"; "1.00";"copper"
"EGLS";"2500"; "4"; "0.82";"elven glass"
"IRON";"1000"; "5"; "1.42";
"ARGN";"1000"; "9"; "0.91";"argentum/silver"
"STAL";"1000"; "14"; "1.73";"steel"
"EAUR";"1000"; "21"; "1.36";"elven aurichalcum"
"TIAL";"1000"; "33"; "2.16";"titanium alloy (Ti6Al4V)"
"ADMT";"1000"; "71"; "3.42";"adamant"
# idst: ID_STRING
1 idst dsty forcemod endurance comments
2 rock ROCK 2400 1 0.42
3 cupr CUPR 1000 2 1.00 copper
4 egls EGLS 2500 4 0.82 elven glass
5 iron IRON 1000 5 1.42
6 argn ARGN 1000 9 0.91 argentum/silver
7 stal STAL 1000 14 1.73 steel
8 eaur EAUR 1000 21 1.36 elven aurichalcum
9 tial TIAL 1000 33 2.16 titanium alloy (Ti6Al4V)
10 admt ADMT 1000 71 3.42 adamant
11 # idst: ID_STRING
12 # forcemod: related to attack points
13 # Attack points = `4 * forcemod.sqrt()` for each strike

View File

@@ -0,0 +1,35 @@
# complete file name is: SPRITESHEET + bodypart name + EXTENSION
SPRITESHEET=mods/basegame/sprites/sprite_assembler_test_assets/test_
EXTENSION=.tga
# defines frame size and origin point. Origin point is given as: (originx, size.y - 1)
CONFIG=SIZE 48,56;ORIGINX 29
# note to self: don't implement skeleton hierarchy: there's too many exceptions
# besides, you have "ALL" key.
! a skeleton also defines what body parts (images) be used.
! you can also write multiline text using reverse solidus; this is a feature of .properties
! skeleton joints are ordered: foremost-drawn object comes first, which means lowermost object IN THIS LIST
! are painted first, and any object that comes before it will paint over it. In other words, this list is
! first reversed then being iterated.
! Joints' original point is defined in the document sprite_joints.psd. It also has visual representations.
# TODO right now accessory points are explicitly defined. Should they be injected in run-time?
SKELETON_STAND=HEADGEAR 0,32;HAIR_FORE 0,32;\
ARM_REST_RIGHT -7,23;HAND_REST_RIGHT -6,11;HELD_ITEM -6,11;\
HAIR 0,32;HEAD 0,32;\
UPPER_TORSO 0,23;LOWER_TORSO 0,15;\
FOOT_RIGHT -2,2;LEG_REST_RIGHT -2,7;\
FOOT_LEFT 2,2;LEG_REST_LEFT 2,7;\
ARM_REST_LEFT 5,24;HAND_REST_LEFT 6,12
# skeleton_stand is used for testing purpose
ANIM_RUN=DELAY 0.15;ROW 2;SKELETON SKELETON_STAND
ANIM_RUN_1=LEG_REST_RIGHT 1,1;FOOT_RIGHT 1,1;LEG_REST_LEFT -1,0;FOOT_LEFT -1,0
ANIM_RUN_2=ALL 0,1;LEG_REST_RIGHT 0,-1;FOOT_RIGHT 0,-1;LEG_REST_LEFT 0,1;FOOT_LEFT 0,1
ANIM_RUN_3=LEG_REST_RIGHT -1,0;FOOT_RIGHT -1,0;LEG_REST_LEFT 1,1;FOOT_LEFT 1,1
ANIM_RUN_4=ALL 0,1;LEG_REST_RIGHT 0,1;FOOT_RIGHT 0,1;LEG_REST_LEFT 0,-1;FOOT_LEFT 0,-1
ANIM_IDLE=DELAY 2;ROW 1;SKELETON SKELETON_STAND
ANIM_IDLE_1=
! ANIM_IDLE_1 will not make any transformation
ANIM_IDLE_2=UPPER_TORSO 0,-1;HEAD 0,-1;HAIR 0,-1;HELD_ITEM 0,-1;ARM_REST_LEFT 0,-1;ARM_REST_RIGHT 0,-1;HAND_REST_LEFT 0,-1;HAND_REST_RIGHT 0,-1;HAIR_FORE 0,-1;HEADGEAR 0,-1

View File

@@ -1,3 +1,13 @@
/*
Texture binding:
0 <- Tiles atlas
1 <- Tiles buffer that holds tiles to be drawn
2 <- Fluid tiles atlas
*/
#version 120
#ifdef GL_ES
precision mediump float;
@@ -16,10 +26,11 @@ uniform vec2 screenDimension;
uniform vec2 tilesInAxes; // vec2(tiles_in_horizontal, tiles_in_vertical)
uniform ivec2 tilemapDimension;
uniform sampler2D tilemap; // RGB888, A is optional and will be completely ignored
uniform sampler2D tilemap; // RGBA8888
uniform sampler2D tilesAtlas;
uniform sampler2D backgroundTexture;
uniform sampler2D tilesAtlas; // terrain, wire, fluids, etc.
uniform sampler2D tilesBlendAtlas; // weather mix (e.g. yellowed grass)
uniform float tilesBlend = 0.0; // percentage of blending [0f..1f]. 0: draws tilesAtlas, 1: draws tilesBlendAtlas
uniform ivec2 tilesInAtlas = ivec2(256, 256);
uniform ivec2 atlasTexSize = ivec2(4096, 4096);
@@ -34,18 +45,18 @@ ivec2 getTileXY(int tileNumber) {
return ivec2(tileNumber % int(tilesInAtlas.x), tileNumber / int(tilesInAtlas.x));
}
// return: int=0xrrggbb
// return: int=0xaarrggbb
int _colToInt(vec4 color) {
return int(color.b * 255) | (int(color.g * 255) << 8) | (int(color.r * 255) << 16);
return int(color.b * 255) | (int(color.g * 255) << 8) | (int(color.r * 255) << 16) | (int(color.a * 255) << 24);
}
// 0x0rggbb where int=0xaarrggbb
// return: [0..1048575]
int getTileFromColor(vec4 color) {
return _colToInt(color) & 0x0FFFFF;
return _colToInt(color) & 0xFFFFF;
}
// 0xr00000 where int=0xaarrggbb
// 0x00r00000 where int=0xaarrggbb
// return: [0..15]
int getBreakageFromColor(vec4 color) {
return (_colToInt(color) >> 20) & 0xF;
@@ -56,6 +67,7 @@ void main() {
// READ THE FUCKING MANUAL, YOU DONKEY !! //
// This code purposedly uses flipped fragcoord. //
// Make sure you don't use gl_FragCoord unknowingly! //
// Remember, if there's a compile error, shader SILENTLY won't do anything //
// default gl_FragCoord takes half-integer (represeting centre of the pixel) -- could be useful for phys solver?
@@ -91,9 +103,15 @@ void main() {
// blending a breakage tex with main tex
vec4 finalTile = texture2D(tilesAtlas, finalUVCoordForTile);
vec4 tileCol = texture2D(tilesAtlas, finalUVCoordForTile);
vec4 tileAltCol = texture2D(tilesBlendAtlas, finalUVCoordForTile);
vec4 finalTile = mix(tileCol, tileAltCol, tilesBlend);
vec4 finalBreakage = texture2D(tilesAtlas, finalUVCoordForBreakage);
gl_FragColor = colourFilter * (mix(finalTile, finalBreakage, finalBreakage.a));
vec4 finalColor = mix(finalTile, finalBreakage, finalBreakage.a);
gl_FragColor = colourFilter * finalColor;
}

View File

@@ -42,4 +42,34 @@ compileTestKotlin {
jar {
baseName = 'Terrarum'
version = '0.2'
}
}
// should be same as plain old 'gradlew run'
task game(type: JavaExec) {
classpath sourceSets.main.runtimeClasspath
main = 'net.torvald.terrarum.AppLoader'
group = "Application"
description = "Launches the game. Should be the same as 'gradlew run'."
}
task gamedebug(type: JavaExec) {
classpath sourceSets.main.runtimeClasspath
main = 'net.torvald.terrarum.AppLoader'
group = "Application"
description = "Launches the game with debuy key."
args = ["isdev=true"]
}
task spriteassembler(type: JavaExec) {
classpath sourceSets.main.runtimeClasspath
main = 'net.torvald.spriteassembler.SpriteAssemblerAppKt'
group = "Application"
description = "Launches the Sprite Assembler."
}
task csveditor(type: JavaExec) {
classpath sourceSets.main.runtimeClasspath
main = 'net.torvald.terrarum.debuggerapp.CSVEditor'
group = "Application"
description = "Launches the CSV Editor. (for Blocks?)"
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,116 @@
package com.badlogic.gdx.graphics;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.utils.StreamUtils;
import java.io.IOException;
import java.io.OutputStream;
/**
* Created by minjaesong on 2019-01-07.
*/
public class PixmapIO2 {
// REMEMBER: to the GL's perspective, this game's FBOs are always Y-flipped. //
public static void writeTGAHappy(FileHandle file, Pixmap pixmap, boolean flipY) throws IOException {
OutputStream output = file.write(false);
try {
_writeTGA(output, pixmap, false, flipY);
} finally {
StreamUtils.closeQuietly(output);
}
}
public static void writeTGA(FileHandle file, Pixmap pixmap, boolean flipY) throws IOException {
OutputStream output = file.write(false);
try {
_writeTGA(output, pixmap, true, flipY);
} finally {
StreamUtils.closeQuietly(output);
}
}
private static void _writeTGA(OutputStream out, Pixmap pixmap, boolean verbatim, boolean flipY) throws IOException {
byte[] width = toShortLittle(pixmap.getWidth());
byte[] height = toShortLittle(pixmap.getHeight());
byte[] zero = toShortLittle(0);
out.write(0); // ID field: empty
out.write(0); // no colour map, but should be ignored anyway as it being unmapped RGB
out.write(2); // 2 means unmapped RGB
out.write(new byte[]{0,0,0,0,0}); // color map spec: empty
out.write(zero); // x origin: 0
out.write(zero); // y origin: 0
out.write(width); // width
out.write(height); // height
out.write(32); // image pixel size: we're writing 32-bit image (8bpp BGRA)
out.write(8); // image descriptor: dunno, Photoshop writes 8 in there
// write actual image data
// since we're following Photoshop's conventional header, we also follows Photoshop's
// TGA saving scheme, that is:
// 1. BGRA order
// 2. Y-Flipped but not X-Flipped
if (!flipY) {
for (int y = pixmap.getHeight() - 1; y >= 0; y--) {
for (int x = 0; x < pixmap.getWidth(); x++) {
writeTga(x, y, verbatim, pixmap, out);
}
}
}
else {
for (int y = 0; y < pixmap.getHeight(); y++) {
for (int x = 0; x < pixmap.getWidth(); x++) {
writeTga(x, y, verbatim, pixmap, out);
}
}
}
// write footer
// 00 00 00 00 00 00 00 00 TRUEVISION-XFILE 2E 00
out.write(new byte[]{0,0,0,0,0,0,0,0});
if (verbatim)
out.write("TRUEVISION-XFILE".getBytes());
else
out.write("TerrarumHappyTGA".getBytes());
out.write(new byte[]{0x2E,0});
out.flush();
out.close();
}
private static byte[] zeroalpha = new byte[]{0,0,0,0};
private static void writeTga(int x, int y, boolean verbatim, Pixmap pixmap, OutputStream out) throws IOException {
int color = pixmap.getPixel(x, y);
// if alpha == 0, write special value instead
if (verbatim && (color & 0xFF) == 0) {
out.write(zeroalpha);
}
else {
out.write(RGBAtoBGRA(color));
}
}
private static byte[] toShortLittle(int i) {
return new byte[]{
(byte) (i & 0xFF),
(byte) ((i >>> 8) & 0xFF)
};
}
private static byte[] RGBAtoBGRA(int rgba) {
return new byte[]{
(byte) ((rgba >>> 8) & 0xFF),
(byte) ((rgba >>> 16) & 0xFF),
(byte) ((rgba >>> 24) & 0xFF),
(byte) (rgba & 0xFF)
};
}
}

View File

@@ -1,7 +1,7 @@
package net.torvald.colourutil
import com.jme3.math.FastMath
import com.badlogic.gdx.graphics.Color
import com.jme3.math.FastMath
/**
* Created by minjaesong on 2017-01-12.
@@ -11,25 +11,27 @@ object CIEXYZUtil {
/**
* 0..255 -> 0.0..1.0
*/
private val rgbLineariseLUT = Array<Float>(257, {
val step = minOf(it, 255) / 255f
private val rgbLinLUT = FloatArray(256) {
val step = it / 255f
if (step > 0.04045f)
((step + 0.055f) / 1.055f).powerOf(2.4f)
else step / 12.92f
})
}
/**
* 0..255 -> 0.0..1.0
*/
private val rgbUnLineariseLUT = Array<Float>(257, {
val step = minOf(it, 255) / 255f
private val rgbUnLinLUT = FloatArray(256) {
val step = it / 255f
if (step > 0.0031308f)
1.055f * step.powerOf(1f / 2.4f) - 0.055f
else
step * 12.92f
})
}
private val rgbToXyzLut_XR = FloatArray(256) { 0.4124564f * (it / 255f) }
@@ -65,8 +67,35 @@ object CIEXYZUtil {
fun Color.toXYZ(): CIEXYZ = RGB(this).toXYZ()
/**
* "Linearise" the sRGB triads. This use lookup table to speed up calculation.
* Integer values (1/255, 2/255, .. , 254/255, 255/255) are accurate but any values in between are
* linearly interpolated and thus slightly less accurate. Visually there's little-to-no difference,
* but may not optimal for rigorous maths.
*/
fun RGB.linearise(): RGB {
/*val newR = if (r > 0.04045f)
val out = floatArrayOf(0f, 0f, 0f)
for (i in 0..2) {
val value = when (i) {
0 -> this.r
1 -> this.g
2 -> this.b
else -> throw InternalError("Fuck you")
}
val step = value.clampOne() * 255f // 0.0 .. 255.0
val intStep = step.toInt() // 0 .. 255
val NeXTSTEP = minOf(intStep + 1, 255) // 1 .. 255
out[i] = interpolateLinear(step - intStep, rgbLinLUT[intStep], rgbLinLUT[NeXTSTEP])
}
return RGB(out[0], out[1], out[2], alpha)
}
/** Suitable for rigorous maths but slower */
fun RGB.lineariseSuper(): RGB {
val newR = if (r > 0.04045f)
((r + 0.055f) / 1.055f).powerOf(2.4f)
else r / 12.92f
val newG = if (g > 0.04045f)
@@ -77,28 +106,38 @@ object CIEXYZUtil {
else b / 12.92f
return RGB(newR, newG, newB, alpha)*/
return RGB(newR, newG, newB, alpha)
}
/**
* "Un-linearise" the RGB triads. That is, codes the linear RGB into sRGB. This use lookup table to speed up calculation.
* Integer values (1/255, 2/255, .. , 254/255, 255/255) are accurate but any values in between are
* linearly interpolated and thus slightly less accurate. Visually there's little-to-no difference,
* but may not optimal for rigorous maths.
*/
fun RGB.unLinearise(): RGB {
val out = floatArrayOf(0f, 0f, 0f)
for (i in 0..2) {
val value = when (i) {
0 -> this.r
1 -> this.g
2 -> this.b
else -> throw Exception("Fuck you")
else -> throw InternalError("Fuck you")
}
val step = value.clampOne() * 255f
val intStep = step.toInt()
val step = value.clampOne() * 255f // 0.0 .. 255.0
val intStep = step.toInt() // 0 .. 255
val NeXTSTEP = minOf(intStep + 1, 255) // 1 .. 255
out[i] = interpolateLinear(step - intStep, rgbLineariseLUT[intStep], rgbLineariseLUT[intStep + 1])
out[i] = interpolateLinear(step - intStep, rgbUnLinLUT[intStep], rgbUnLinLUT[NeXTSTEP])
}
return RGB(out[0], out[1], out[2], alpha)
}
fun RGB.unLinearise(): RGB {
/*val newR = if (r > 0.0031308f)
/** Suitable for rigorous maths but slower */
fun RGB.unLineariseSuper(): RGB {
val newR = if (r > 0.0031308f)
1.055f * r.powerOf(1f / 2.4f) - 0.055f
else
r * 12.92f
@@ -112,24 +151,7 @@ object CIEXYZUtil {
b * 12.92f
return RGB(newR, newG, newB, alpha)*/
val out = floatArrayOf(0f, 0f, 0f)
for (i in 0..2) {
val value = when (i) {
0 -> this.r
1 -> this.g
2 -> this.b
else -> throw Exception("Fuck you")
}
val step = value.clampOne() * 255f
val intStep = step.toInt()
out[i] = interpolateLinear(step - intStep, rgbUnLineariseLUT[intStep], rgbUnLineariseLUT[intStep + 1])
}
return RGB(out[0], out[1], out[2], alpha)
return RGB(newR, newG, newB, alpha)
}
fun RGB.toXYZ(): CIEXYZ {

View File

@@ -1,7 +1,8 @@
package net.torvald.colourutil
import com.jme3.math.FastMath
import com.badlogic.gdx.graphics.Color
import com.jme3.math.FastMath
import net.torvald.colourutil.CIEXYZUtil.linearise
/**
* Created by minjaesong on 2016-07-26.
@@ -20,4 +21,17 @@ object ColourUtil {
return Color(r, g, b, a)
}
/** Get luminosity level using CIEXYZ colour space. Slow but accurate. */
fun RGB.getLuminosity(): Float {
val new = this.linearise()
return 0.2126729f * new.r + 0.7151522f * new.g + 0.0721750f * new.b // from RGB.toXYZ
}
/** Get luminosity level using CIEXYZ colour space. Slow but accurate. */
fun Color.getLuminosity() = RGB(this).getLuminosity()
/** Get luminosity level using NTSC standard. Fast, less accurate but should be good enough. */
fun RGB.getLuminosityQuick() = 0.3f * this.r + 0.59f * this.g + 0.11f * this.b // NTSC standard
/** Get luminosity level using NTSC standard. Fast, less accurate but should be good enough. */
fun Color.getLuminosityQuick() = 0.3f * this.r + 0.59f * this.g + 0.11f * this.b // NTSC standard
}

View File

@@ -2,6 +2,8 @@ package net.torvald.dataclass
/**
* buffer[head] contains the most recent item, whereas buffer[tail] contains the oldest one.
*
* Notes for particle storage:
* Particles does not need to be removed, just let it overwrite as their operation is rather
* lightweight. So, just flagDespawn = true if it need to be "deleted" so that it won't update
@@ -12,57 +14,67 @@ package net.torvald.dataclass
class CircularArray<T>(val size: Int) {
val buffer: Array<T> = arrayOfNulls<Any>(size) as Array<T>
var tail: Int = 0
var head: Int = 0
var tail: Int = 0; private set
var head: Int = -1; private set
private var unreliableAddCount = 0
val lastIndex = size - 1
/**
* Number of elements that forEach() or fold() would iterate.
*/
val elemCount: Int
get() = if (tail >= head) tail - head else size
get() = minOf(unreliableAddCount, size)
fun add(item: T) {
buffer[tail] = item // overwrites oldest item when eligible
tail = (tail + 1) % size
if (tail == head) {
head = (head + 1) % size
if (unreliableAddCount <= size) unreliableAddCount += 1
head = (head + 1) % size
if (unreliableAddCount > size) {
tail = (tail + 1) % size
}
buffer[head] = item // overwrites oldest item when eligible
//println("$this $unreliableAddCount")
}
inline fun forEach(action: (T) -> Unit) {
fun getHeadElem(): T = buffer[head]
fun getTailElem(): T = buffer[tail]
/**
* Iterates the array with oldest element first.
*/
fun forEach(action: (T) -> Unit) {
// has slightly better iteration performance than lambda
if (tail >= head) {
for (i in head..tail - 1)
if (unreliableAddCount <= size) {
for (i in 0..head)
action(buffer[i])
}
else {
for (i in 0..size - 1)
action(buffer[(i + head) % size])
action(buffer[(i + tail) % size])
}
}
// FIXME not working as intended
inline fun <R> fold(initial: R, operation: (R, T) -> R): R {
fun <R> fold(initial: R, operation: (R, T) -> R): R {
var accumulator = initial
//for (element in buffer) accumulator = operation(accumulator, element)
if (tail >= head) {
for (i in head..tail - 1)
operation(accumulator, buffer[i])
if (unreliableAddCount <= size) {
for (i in 0..head)
accumulator = operation(accumulator, buffer[i])
}
else {
for (i in 0..size - 1)
operation(accumulator, buffer[(i + head) % size])
accumulator = operation(accumulator, buffer[(i + tail) % size])
}
return accumulator
}
inline fun forEachConcurrent(action: (T) -> Unit) {
TODO()
}
inline fun forEachConcurrentWaitFor(action: (T) -> Unit) {
TODO()
}
override fun toString(): String {
return "CircularArray(size=" + buffer.size + ", head=" + head + ", tail=" + tail + ")"

View File

@@ -0,0 +1,59 @@
package net.torvald.spriteanimation
import com.badlogic.gdx.files.FileHandle
import com.badlogic.gdx.graphics.Texture
import net.torvald.spriteassembler.ADProperties
import net.torvald.spriteassembler.AssembleSheetPixmap
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
/**
* Created by minjaesong on 2019-01-18.
*/
interface HasAssembledSprite {
var animDesc: FileHandle
// FIXME sometimes the animmation is invisible (row and nFrames mismatch -- row is changed to 1 but it's drawing 3rd frame?)
fun reassembleSprite(sprite: SpriteAnimation) {
_rebuild(ADProperties(animDesc.read()), sprite)
}
/*fun rebuild(animDesc: String, spriteAnimation: SpriteAnimation) {
_rebuild(ADProperties(StringReader(animDesc)), spriteAnimation)
}
fun rebuild(animDesc: FileHandle, spriteAnimation: SpriteAnimation) {
_rebuild(ADProperties(animDesc.read()), spriteAnimation)
}
fun rebuild(javaProp: Properties, spriteAnimation: SpriteAnimation) {
_rebuild(ADProperties(javaProp), spriteAnimation)
}*/
private fun _rebuild(ad: ADProperties, sprite: SpriteAnimation) {
// TODO injecting held item/armour pictures? Would it be AssembleSheetPixmap's job?
val pixmap = AssembleSheetPixmap(ad)
val texture = Texture(pixmap)
texture.setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest)
pixmap.dispose()
val regionPack = TextureRegionPack(texture, ad.frameWidth, ad.frameHeight)
val newAnimDelays = FloatArray(ad.animations.size)
val newAnimFrames = IntArray(ad.animations.size)
ad.animations.forEach { t, u ->
val index = u.row - 1
newAnimDelays[index] = u.delay
newAnimFrames[index] = u.frames
}
sprite.setSpriteImage(regionPack)
sprite.delays = newAnimDelays
sprite.nFrames = newAnimFrames
sprite.nRows = newAnimDelays.size
}
}

View File

@@ -7,6 +7,7 @@ package net.torvald.spriteanimation
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.g2d.SpriteBatch
import com.jme3.math.FastMath
import net.torvald.terrarum.Second
import net.torvald.terrarum.gameactors.ActorWBMovable
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
@@ -16,12 +17,29 @@ class SpriteAnimation(val parentActor: ActorWBMovable) {
var currentFrame = 0
var currentRow = 0
var nFrames: Int = 1
private set
var nFrames: IntArray = intArrayOf(1)
internal set
var nRows: Int = 1
private set
var delay = 200f
internal set
private val currentDelay: Second
get() = delays[currentRow]
/**
* Sets delays for each rows. Array size must be the same as the rows of the sheet
*/
var delays: FloatArray = floatArrayOf(0.2f)
set(value) {
if (value.filter { it <= 0f }.isNotEmpty()) {
throw IllegalArgumentException("Delay array contains zero or negative value: $delays")
}
field = value
}
private var delta = 0f
val looping = true
private var animationRunning = true
var flipHorizontal = false
@@ -53,7 +71,15 @@ class SpriteAnimation(val parentActor: ActorWBMovable) {
*/
fun setRowsAndFrames(nRows: Int, nFrames: Int) {
this.nRows = nRows
this.nFrames = nFrames
this.nFrames = IntArray(nRows) { nFrames }
}
fun setFramesOf(row: Int, frameCount: Int) {
nFrames[row] = frameCount
}
fun setFramesCount(framesCount: IntArray) {
nFrames = framesCount
}
fun update(delta: Float) {
@@ -61,17 +87,23 @@ class SpriteAnimation(val parentActor: ActorWBMovable) {
//skip this if animation is stopped
this.delta += delta
//println("delta accumulation: $delta, currentDelay: $currentDelay")
//check if it's time to advance the frame
if (this.delta >= this.delay) {
//if set to not loop, keep the frame at the last frame
if (this.currentFrame == this.nFrames && !this.looping) {
this.currentFrame = this.nFrames - 1
while (this.delta >= currentDelay) {
// advance frame
if (looping) { // looping, wrap around
currentFrame = (currentFrame + 1) % nFrames[currentRow]
}
else if (currentFrame < nFrames[currentRow] - 1) { // not looping and haven't reached the end
currentFrame += 1
}
//advance one frame, then reset delta counter
this.currentFrame = this.currentFrame % this.nFrames
this.delta = 0f
// discount counter
this.delta -= currentDelay
}
//println("row, frame: $currentRow, $currentFrame")
}
}
@@ -86,13 +118,13 @@ class SpriteAnimation(val parentActor: ActorWBMovable) {
* *
* @param scale
*/
@JvmOverloads fun render(batch: SpriteBatch, posX: Float, posY: Float, scale: Float = 1f) {
fun render(batch: SpriteBatch, posX: Float, posY: Float, scale: Float = 1f) {
if (cellWidth == 0 || cellHeight == 0) {
throw Error("Sprite width or height is set to zero! ($cellWidth, $cellHeight); master: $parentActor")
}
if (visible) {
val region = textureRegion.get(currentRow, currentFrame)
val region = textureRegion.get(currentFrame, currentRow)
batch.color = colorFilter
if (flipHorizontal && flipVertical) {
@@ -131,20 +163,9 @@ class SpriteAnimation(val parentActor: ActorWBMovable) {
}
fun switchRow(newRow: Int) {
currentRow = newRow % nRows
//if beyond the frame index then reset
if (currentFrame > nFrames) {
reset()
}
}
fun setSpriteDelay(newDelay: Float) {
if (newDelay > 0) {
delay = newDelay
}
else {
throw IllegalArgumentException("Delay equal or less than zero")
if (newRow != currentRow) {
currentRow = newRow
currentFrame = 1
}
}

View File

@@ -0,0 +1,314 @@
package net.torvald.spriteassembler
import net.torvald.terrarum.linearSearchBy
import java.io.InputStream
import java.io.Reader
import java.util.*
import kotlin.collections.HashMap
import kotlin.collections.HashSet
internal data class Joint(val name: String, val position: ADPropertyObject.Vector2i) {
override fun toString() = "$name $position"
}
internal data class Skeleton(val name: String, val joints: List<Joint>) {
override fun toString() = "$name=$joints"
}
/**
* @param name You know it
* @param delay Delay between each frame in seconds
* @param row STARTS AT ONE! Row in the final spritesheet, also act as the animation index.
* @param frames number of frames this animation has
* @param skeleton list of joints to be transformed
*/
internal data class Animation(val name: String, val delay: Float, val row: Int, val frames: Int, val skeleton: Skeleton) {
override fun toString() = "$name delay: $delay, row: $row, frames: $frames, skeleton: ${skeleton.name}"
}
/** Later the 'translate' can be changed so that it represents affine transformation (Matrix2d) */
internal data class Transform(val joint: Joint, val translate: ADPropertyObject.Vector2i) {
override fun toString() = "$joint transform: $translate"
}
class ADProperties {
private val javaProp = Properties()
/** Every key is CAPITALISED */
private val propTable = HashMap<String, List<ADPropertyObject>>()
/** list of bodyparts used by all the skeletons (HEAD, UPPER_TORSO, LOWER_TORSO) */
lateinit var bodyparts: List<String>; private set
lateinit var bodypartFiles: List<String>; private set
/** properties that are being used as skeletons (SKELETON_STAND) */
internal lateinit var skeletons: HashMap<String, Skeleton>; private set
/** properties that are recognised as animations (ANIM_RUN, ANIM)IDLE) */
internal lateinit var animations: HashMap<String, Animation>; private set
/** an "animation frame" property (ANIM_RUN_1, ANIM_RUN_2) */
internal lateinit var transforms: HashMap<String, List<Transform>>; private set
private val reservedProps = listOf("SPRITESHEET", "EXTENSION")
private val animMustContain = listOf("DELAY", "ROW", "SKELETON")
lateinit var baseFilename: String; private set
lateinit var extension: String; private set
var frameWidth: Int = -1; private set
var frameHeight: Int = -1; private set
var originX: Int = -1; private set
var originY: Int = -1; private set
internal val origin: ADPropertyObject.Vector2i
get() = ADPropertyObject.Vector2i(originX, originY)
private val animFrameSuffixRegex = Regex("""_[0-9]+""")
private val ALL_JOINT = Joint(ALL_JOINT_SELECT_KEY, ADPropertyObject.Vector2i(0, 0))
var rows = -1; private set
var cols = -1; private set
companion object {
const val ALL_JOINT_SELECT_KEY = "ALL"
}
constructor(reader: Reader) {
javaProp.load(reader)
continueLoad()
}
constructor(inputStream: InputStream) {
javaProp.load(inputStream)
continueLoad()
}
constructor(javaProp: Properties) {
this.javaProp.putAll(javaProp.toMap())
}
private fun continueLoad() {
javaProp.keys.forEach { propName ->
val propsStr = javaProp.getProperty(propName as String)
val propsList = propsStr.split(';').map { ADPropertyObject(it) }
propTable[propName.toUpperCase()] = propsList
}
// set reserved values for the animation: filename, extension
baseFilename = get("SPRITESHEET")[0].name
extension = get("EXTENSION")[0].name
val frameSizeVec = get("CONFIG").linearSearchBy { it.name == "SIZE" }!!.input as ADPropertyObject.Vector2i
frameWidth = frameSizeVec.x
frameHeight = frameSizeVec.y
originX = (get("CONFIG").linearSearchBy { it.name == "ORIGINX" }!!.input as Float).toInt()
originY = frameHeight - 1
var maxColFinder = -1
var maxRowFinder = -1
val bodyparts = HashSet<String>()
val skeletons = HashMap<String, Skeleton>()
val animations = HashMap<String, Animation>()
val animFrames = HashMap<String, Int>()
val transforms = HashMap<String, List<Transform>>()
// scan every props, write down anim frames for later use
propTable.keys.forEach {
if (animFrameSuffixRegex.containsMatchIn(it)) {
val animName = getAnimNameFromFrame(it)
val frameNumber = getFrameNumberFromName(it)
// if animFrames does not have our entry, add it.
// otherwise, max() against the existing value
if (animFrames.containsKey(animName)) {
animFrames[animName] = maxOf(animFrames[animName]!!, frameNumber)
}
else {
animFrames[animName] = frameNumber
}
maxColFinder = maxOf(maxColFinder, frameNumber)
}
}
// populate skeletons and animations
forEach { s, list ->
// Map-ify. If it has variable == "SKELETON", the 's' is likely an animation
// and thus, uses whatever the "input" used by the SKELETON is a skeleton
val propsHashMap = HashMap<String, Any?>()
list.forEach {
propsHashMap[it.name.toUpperCase()] = it.input
}
// if it is indeed anim, populate animations list
if (propsHashMap.containsKey("SKELETON")) {
val skeletonName = propsHashMap["SKELETON"] as String
val skeletonDef = get(skeletonName)
skeletons[skeletonName] = Skeleton(skeletonName, skeletonDef.toJoints())
animations[s] = Animation(
s,
propsHashMap["DELAY"] as Float,
(propsHashMap["ROW"] as Float).toInt(),
animFrames[s]!!,
Skeleton(skeletonName, skeletonDef.toJoints())
)
maxRowFinder = maxOf(maxRowFinder, animations[s]!!.row)
}
}
// populate the bodyparts using skeletons
skeletons.forEach { (_, prop: Skeleton) ->
prop.joints.forEach {
bodyparts.add(it.name)
}
}
// populate transforms
animations.forEach { t, u ->
for (fc in 1..u.frames) {
val frameName = "${t}_$fc"
val prop = get(frameName)
var emptyList = prop.size == 1 && prop[0].name.isEmpty()
val transformList = if (!emptyList) {
List(prop.size) { index ->
val jointNameToSearch = prop[index].name.toUpperCase()
val joint = if (jointNameToSearch == "ALL")
ALL_JOINT
else
u.skeleton.joints.linearSearchBy { it.name == jointNameToSearch }
?: throw NullPointerException("No such joint: $jointNameToSearch")
val translate = prop[index].input as ADPropertyObject.Vector2i
Transform(joint, translate)
}
}
else {
// to make real empty list
List(0) { Transform(ALL_JOINT, ADPropertyObject.Vector2i(0, 0)) }
}
transforms[frameName] = transformList
}
}
this.bodyparts = bodyparts.toList().sorted()
this.skeletons = skeletons
this.animations = animations
this.bodypartFiles = this.bodyparts.map { toFilename(it) }
this.transforms = transforms
cols = maxColFinder
rows = maxRowFinder
}
operator fun get(identifier: String) = propTable[identifier.toUpperCase()]!!
val keys
get() = propTable.keys
fun containsKey(key: String) = propTable.containsKey(key)
fun forEach(predicate: (String, List<ADPropertyObject>) -> Unit) = propTable.forEach(predicate)
fun toFilename(partName: String) =
"${this.baseFilename}${partName.toLowerCase()}${this.extension}"
internal fun getAnimByFrameName(frameName: String) = animations[getAnimNameFromFrame(frameName)]!!
internal fun getFrameNumberFromName(frameName: String) = frameName.substring(frameName.lastIndexOf('_') + 1 until frameName.length).toInt()
internal fun getSkeleton(name: String) = skeletons[name]!!
internal fun getTransform(name: String) = transforms[name]!!
private fun getAnimNameFromFrame(s: String) = s.substring(0 until s.lastIndexOf('_'))
private fun List<ADPropertyObject>.toJoints() = List(this.size) {
Joint(this[it].name.toUpperCase(), this[it].input!! as ADPropertyObject.Vector2i)
}
}
/**
* @param propertyRaw example inputs:
* - ```DELAY 0.15```
* - ```LEG_RIGHT 0,-1```
*
* Created by minjaesong on 2019-01-05.
*/
class ADPropertyObject(propertyRaw: String) {
/** If the input is like ```UPPER_TORSO``` (that is, not a variable-input pair), this holds the string UPPER_TORSO. */
val name: String
val input: Any?
get() = when (type) {
ADPropertyType.IVEC2 -> field!! as Vector2i
ADPropertyType.FLOAT -> field!! as Float
ADPropertyType.STRING_PAIR -> field!! as String
else -> null
}
val type: ADPropertyType
init {
val propPair = propertyRaw.split(variableInputSepRegex)
if (isADvariable(propertyRaw)) {
name = propPair[0]
val inputStr = propPair[1]
if (isADivec2(inputStr)) {
type = ADPropertyType.IVEC2
input = toADivec2(inputStr)
}
else if (isADfloat(inputStr)) {
type = ADPropertyType.FLOAT
input = toADfloat(inputStr)
}
else {
type = ADPropertyType.STRING_PAIR
input = inputStr
}
}
else {
name = propertyRaw
input = null
type = ADPropertyType.NAME_ONLY
}
}
internal companion object {
private val floatRegex = Regex("""-?[0-9]+(\.[0-9]*)?""")
private val ivec2Regex = Regex("""-?[0-9]+,-?[0-9]+""")
private val variableInputSepRegex = Regex(""" +""")
fun isADivec2(s: String) = ivec2Regex.matches(s)
fun isADfloat(s: String) = floatRegex.matches(s) && !ivec2Regex.containsMatchIn(s)
fun toADivec2(s: String) = if (isADivec2(s))
Vector2i(s.substringBefore(',').toInt(), s.substringAfter(',').toInt())
else throw IllegalArgumentException("Input not in ivec2 format: $s")
fun toADfloat(s: String) = if (isADfloat(s))
s.toFloat()
else throw IllegalArgumentException("Input not in ivec2 format: $s")
/** example valid input: ```LEG_RIGHT 0,1``` */
fun isADvariable(property: String) = variableInputSepRegex.containsMatchIn(property)
/** example valid input: ```sprites/test``` */
fun isADstring(property: String) = !isADvariable(property)
}
internal data class Vector2i(var x: Int, var y: Int) {
override fun toString() = "($x, $y)"
operator fun plus(other: Vector2i) = Vector2i(this.x + other.x, this.y + other.y)
operator fun minus(other: Vector2i) = Vector2i(this.x - other.x, this.y - other.y)
fun invertY() = Vector2i(this.x, -this.y)
}
enum class ADPropertyType {
NAME_ONLY, // "sprite/test.tga" to nothing
IVEC2, // "LEG_RIGHT" to (1,-1)
FLOAT, // "DELAY" to 0.15
STRING_PAIR // "SKELETON" to "SKELETON_DEFAULT"
}
override fun toString(): String {
return "$name ${input ?: ""}: ${type.toString().toLowerCase()}"
}
}

View File

@@ -0,0 +1,119 @@
## Animation Description Language
This is a text version of my drawing of same name. 2018-01-04 CuriousTorvald
Author's node: yet another non-JSON domain-specific language because why not?
## Objective
* Java .properties-compatible
* Case insensitive
## Example code
```
SPRITESHEET=sprites/test
EXTENSION=.tga.gz
ANIM_RUN=DELAY 0.15;ROW 2
ANIM_RUN_BODYPARTS=HEAD;UPPER_TORSO;LOWER_TORSO;ARM_FWD_LEFT;ARM_FWD_RIGHT;LEG_LEFT;LEG_RIGHT
ANIM_RUN_1=LEG_RIGHT 1,-1;LEG_LEFT -1,0
ANIM_RUN_2=ALL 0,-1;LEG_RIGHT 0,1;LEG_LEFT 0,-1
ANIM_RUN_3=LEG_RIGHT -1,0;LEG_LEFT 1,-1
ANIM_RUN_4=ALL 0,-1;LEG_RIGHT 0,-1;LEG_LEFT 0,1
ANIM_IDLE=DELAY 2;ROW 1
ANIM_IDLE_BODYPARTS=HEAD;UPPER_TORSO;LOWER_TORSO;ARM_REST_LEFT;ARM_REST_RIGHT;LEG_LEFT;LEG_RIGHT
ANIM_IDLE_1=
! ANIM_IDLE_1 will not make any transformation
ANIM_IDLE_2=UPPER_TORSO 0,-1
ANIM_CROUCH=DELAY 1;ROW 3
ANIM_CROUCH_BODYPARTS=HEAD;UPPER_TORSO;LOWER_TORSO;ARM_FWD_LEFT;ARM_FWD_RIGHT;LEG_CROUCH_LEFT;LEG_CROUCH_RIGHT
ANIM_CROUCH_1=
...
```
### In-detail
```
ANIM_RUN=DELAY 0.15;ROW 2
```
Each line defines one property. A property is a field-value pair. In this code, field is ```ANIM_RUN```, and the value is ```DELAY 0.15;ROW 2```
The values are further parsed using ```;``` (semicolon with NO spaces attached) as a separator.
```
In this example, ANIM_RUN contains two variables:
DELAY = 0.15
ROW = 2
```
A value of the field is consisted of zero or more variable-input pairs. Variable and the input are separated with one or more connected spaces.
#### Variables
Variables can have only one of the two types: ```float``` and ```ivec2```. Single integer value ('2' in the ROW) are regarded as a float.
Float and Ivec2 are determined by:
* Ivec2: inputs that are matched by the regex ```-?[0-9]+,-?[0-9]+``` (we call this "ivec2 regex")
* Float: inputs that are matched by the regex ```-?[0-9]+(\.[0-9]*)?```, but not even partially matched by the ivec2 regex.
Any argument to the body parts takes ivec2, to move the parts accordingly.
#### Just one exception: SPRITESHEET and EXTENSION
SPRITESHEET and EXTENSION property is not parsed as a property, it's just a single string like the original .properties
### Naming convention of properties
If a field is recognised as an animation (in this case ANIM_RUN), the assembler will look for the fields named like ANIM_RUN_1, ANIM_RUN_2, ... , ANIM_RUN_9, ANIM_RUN_10 and beyond.
### Naming convention of files
If the animation specifies a "body part" (in this example LEG_LEFT and LEG_RIGHT), the assembler will look for a file ```sprites/test_leg_left.tga.gz``` and ```sprites/test_leg_right.tga.gz``` respectively. Filenames are advised to be kept all lowercase.
### Reserved keywords
These values must exist so that the file can be parsed successfully.
#### Root
|Name|Type|Meaning|
|---|---|---|
|SPRITESHEET|properties: NAME_ONLY|Base file name of the images|
|EXTENSION|properties: NAME_ONLY|Extension of the base file|
|CONFIG|properties: 2 variables|Frame size and origin-x position, 0 being left|
#### Animation
Remember that 'variables' are contained within 'properties'
|Name|Type|Meaning|
|---|---|---|
|DELAY|variable: float|Delay between frames, in seconds|
|ROW|variable: float|which row the animation goes in the spritesheet|
|SKELETON|variable: string_pair|Which skeleton this animation uses
#### Transforms
Things like ```LEG_RIGHT -1,0``` within ```ANIM_RUN_3``` are called 'Transform'
|Name|Type|Meaning|
|---|---|---|
|ALL|variable: ivec2|Shifts (translates) everything by set value|
### Notes
* All indices are one-based
## Operation
* Each line describes transformation
* Transformation are applied sequentially from left to right. In other words, their order matters. Be wary of the clipping that may occur! (really?)
* The Field is an identifier the game code -- sprite assembler -- recognises.
* The Field of animation's name is the name the game code looks for. Example: ```this.setAnim("ANIM_RUN")```
* Coord system is Y-Up, meaning Y=0 is the bottommost position.

View File

@@ -0,0 +1,125 @@
package net.torvald.spriteassembler
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.graphics.Pixmap
import net.torvald.terrarum.AppLoader
import net.torvald.terrarum.linearSearch
import java.io.File
/**
* Assembles the single frame of the animation, outputs GDX Pixmap.
*
* The entire rendering is done by using pixmap. That is, no GPU access.
*
* Created by minjaesong on 2019-01-06.
*/
object AssembleSheetPixmap {
operator fun invoke(properties: ADProperties): Pixmap {
val canvas = Pixmap(properties.cols * properties.frameWidth, properties.rows * properties.frameHeight, Pixmap.Format.RGBA8888)
canvas.blending = Pixmap.Blending.SourceOver
// actually draw
properties.transforms.forEach { t, _ ->
drawThisFrame(t, canvas, properties)
}
return canvas
}
private fun drawThisFrame(frameName: String,
canvas: Pixmap,
properties: ADProperties
) {
val theAnim = properties.getAnimByFrameName(frameName)
val skeleton = theAnim.skeleton.joints.reversed()
val transforms = properties.getTransform(frameName)
val bodyparts = Array<Pixmap?>(skeleton.size) {
// if file does not exist, null it
val file = File("assets/" + properties.toFilename(skeleton[it].name))
//printdbg(this, "Loading file ${file.absolutePath}, exists: ${file.exists()}")
/*return*/if (file.exists()) {
Pixmap(Gdx.files.internal(file.path))
}
else {
null
}
}
val transformList = AssembleFrameBase.makeTransformList(skeleton, transforms)
val animRow = theAnim.row
val animFrame = properties.getFrameNumberFromName(frameName)
AppLoader.printdbg(this, "Frame to draw: $frameName (R$animRow C$animFrame)")
drawFrame(animRow, animFrame, canvas, properties, bodyparts, transformList)
bodyparts.forEach { it?.dispose() }
}
private fun drawFrame(row: Int, column: Int,
canvas: Pixmap,
props: ADProperties,
bodyparts: Array<Pixmap?>,
transformList: List<Pair<String, ADPropertyObject.Vector2i>>
) {
val tmpFrame = Pixmap(props.frameWidth, props.frameHeight, Pixmap.Format.RGBA8888)
bodyparts.forEachIndexed { index, image ->
if (image != null) {
val imgCentre = AssembleFrameBase.getCentreOf(image)
val drawPos = transformList[index].second.invertY() + props.origin - imgCentre
tmpFrame.drawPixmap(image, drawPos.x, drawPos.y)
}
}
canvas.drawPixmap(
tmpFrame,
(column - 1) * props.frameWidth,
(row - 1) * props.frameHeight
)
tmpFrame.dispose()
}
}
internal object AssembleFrameBase {
/**
* Returns joints list with tranform applied.
* @param skeleton list of joints
* @param transform ordered list of transforms should be applied. First come first serve.
* @return List of pairs that contains joint name on left, final transform value on right
*/
fun makeTransformList(joints: List<Joint>, transforms: List<Transform>): List<Pair<String, ADPropertyObject.Vector2i>> {
// make our mutable list
val out = ArrayList<Pair<String, ADPropertyObject.Vector2i>>()
joints.forEach {
out.add(it.name to it.position)
}
// process transform queue
transforms.forEach { transform ->
if (transform.joint.name == ADProperties.ALL_JOINT_SELECT_KEY) {
// transform applies to all joints
for (c in 0 until out.size) {
out[c] = out[c].first to (out[c].second + transform.translate)
}
}
else {
val i = out.linearSearch { it.first == transform.joint.name }!!
// transform applies to one specific joint in the list (one specific joint is a search result)
out[i] = out[i].first to (out[i].second + transform.translate)
}
}
return out.toList()
}
fun getCentreOf(pixmap: Pixmap) = ADPropertyObject.Vector2i(pixmap.width / 2, pixmap.height / 2)
}

View File

@@ -0,0 +1,322 @@
package net.torvald.spriteassembler
import com.badlogic.gdx.Game
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.backends.lwjgl.LwjglApplication
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.Pixmap
import com.badlogic.gdx.graphics.PixmapIO2
import com.badlogic.gdx.graphics.Texture
import com.badlogic.gdx.graphics.g2d.SpriteBatch
import net.torvald.terrarum.gdxClearAndSetBlend
import net.torvald.terrarum.inUse
import java.awt.BorderLayout
import java.awt.Font
import java.awt.event.MouseAdapter
import java.awt.event.MouseEvent
import java.io.StringReader
import java.util.*
import javax.swing.*
import javax.swing.tree.DefaultMutableTreeNode
import javax.swing.tree.DefaultTreeModel
/**
* Created by minjaesong on 2019-01-05.
*/
class SpriteAssemblerApp(val gdxWindow: SpriteAssemblerPreview) : JFrame() {
private val panelProperties = JTree()
private val panelAnimationsList = JList<String>()
private val panelBodypartsList = JList<String>()
private val panelImageFilesList = JList<String>()
private val panelSkeletonsList = JList<String>()
private val panelTransformsList = JList<String>()
private val panelStatList = JList<String>()
private val panelCode = JTextPane()
private val statBar = JTextArea("Null.")
private lateinit var adProperties: ADProperties
private val props = Properties()
private val lang = Properties()
private val captionProperties = "" + // dummy string to make IDE happy with the auto indent
"id=ID of this block\n" +
"drop=ID of the block this very block should drop when mined\n" +
"name=String identifier of the block\n" +
"shdr=Shade Red (light absorption). Valid range 0.0-4.0\n" +
"shdg=Shade Green (light absorption). Valid range 0.0-4.0\n" +
"shdb=Shade Blue (light absorption). Valid range 0.0-4.0\n" +
"shduv=Shade UV (light absorbtion). Valid range 0.0-4.0\n" +
"lumr=Luminosity Red (light intensity). Valid range 0.0-4.0\n" +
"lumg=Luminosity Green (light intensity). Valid range 0.0-4.0\n" +
"lumb=Luminosity Blue (light intensity). Valid range 0.0-4.0\n" +
"lumuv=Luminosity UV (light intensity). Valid range 0.0-4.0\n" +
"str=Strength of the block\n" +
"dsty=Density of the block. Water have 1000 in the in-game scale\n" +
"mate=Material of the block\n" +
"solid=Whether the file has full collision\n" +
"plat=Whether the block should behave like a platform\n" +
"wall=Whether the block can be used as a wall\n" +
"fall=Whether the block should fall through the empty space\n" +
"dlfn=Dynamic Light Function. 0=Static. Please see <strong>notes</strong>\n" +
"fv=Vertical friction when player slide on the cliff. 0 means not slide-able\n" +
"fr=Horizontal friction. &lt;16:slippery 16:regular &gt;16:sticky\n"
/**
* ¤ is used as a \n marker
*/
private val translations = "" +
"WARNING_CONTINUE=Continue?\n" +
"WARNING_YOUR_DATA_WILL_GONE=Existing edits will be lost.\n" +
"OPERATION_CANCELLED=Operation cancelled.\n" +
"NO_SUCH_FILE=No such file exists, operation cancelled.\n" +
"NEW_ROWS=Enter the number of rows to initialise the new CSV.¤Remember, you can always add or delete rows later.\n" +
"ADD_ROWS=Enter the number of rows to add:\n" +
"WRITE_FAIL=Writing to file has failed:\n" +
"STAT_INIT=Creating a new CSV. You can still open existing file.\n" +
"STAT_SAVE_TGA_SUCCESSFUL=Spritesheet exported successfully.\n" +
"STAT_LOAD_SUCCESSFUL=File loaded successfully.\n" +
"ERROR_INTERNAL=Something went wrong.\n" +
"ERROR_PARSE_FAIL=Parsing failed\n" +
"SPRITE_DEF_LOAD_SUCCESSFUL=Sprite definition loaded.\n" +
"SPRITE_ASSEMBLE_SUCCESSFUL=Sprite assembled."
init {
// setup application properties //
try {
props.load(StringReader(captionProperties))
lang.load(StringReader(translations))
}
catch (e: Throwable) {
}
panelCode.font = Font(Font.MONOSPACED, Font.PLAIN, 12)
panelAnimationsList.model = DefaultListModel()
panelBodypartsList.model = DefaultListModel()
panelImageFilesList.model = DefaultListModel()
panelSkeletonsList.model = DefaultListModel()
panelTransformsList.model = DefaultListModel()
panelStatList.model = DefaultListModel()
val panelPartsList = JTabbedPane(JTabbedPane.TOP)
panelPartsList.add("Animations", JScrollPane(panelAnimationsList))
panelPartsList.add("Bodyparts", JScrollPane(panelBodypartsList))
panelPartsList.add("Images", JScrollPane(panelImageFilesList))
panelPartsList.add("Skeletons", JScrollPane(panelSkeletonsList))
panelPartsList.add("Transforms", JScrollPane(panelTransformsList))
panelPartsList.add("Stats", JScrollPane(panelStatList))
val panelDataView = JSplitPane(JSplitPane.VERTICAL_SPLIT, JScrollPane(panelProperties), panelPartsList)
panelDataView.resizeWeight = 0.333
// to disable text wrap
//val panelCodeNoWrap = JPanel(BorderLayout())
//panelCodeNoWrap.add(panelCode)
val panelMain = JSplitPane(JSplitPane.HORIZONTAL_SPLIT, JScrollPane(panelCode), panelDataView)
panelMain.resizeWeight = 0.666
val menu = JMenuBar()
menu.add(JMenu("Parse")).addMouseListener(object : MouseAdapter() {
override fun mousePressed(e: MouseEvent?) {
try {
adProperties = ADProperties(StringReader(panelCode.text))
statBar.text = lang.getProperty("SPRITE_DEF_LOAD_SUCCESSFUL")
val propRoot = DefaultMutableTreeNode("Properties")
adProperties.forEach { s, list ->
// build tree node for the properties display
val propNode = DefaultMutableTreeNode(s)
propRoot.add(propNode)
list.forEach {
propNode.add(DefaultMutableTreeNode(it.toString()))
}
}
panelProperties.model = DefaultTreeModel(propRoot)
// clean the data views
panelAnimationsList.model = DefaultListModel()
panelBodypartsList.model = DefaultListModel()
panelImageFilesList.model = DefaultListModel()
panelSkeletonsList.model = DefaultListModel()
panelTransformsList.model = DefaultListModel()
panelStatList.model = DefaultListModel()
// populate animations view
adProperties.animations.forEach {
(panelAnimationsList.model as DefaultListModel).addElement("${it.value}")
}
// populate bodyparts view
adProperties.bodyparts.forEach { partName ->
(panelBodypartsList.model as DefaultListModel).addElement(partName)
}
// populate image file list view
adProperties.bodypartFiles.forEach { partName ->
(panelImageFilesList.model as DefaultListModel).addElement(partName)
}
// populate skeletons view
adProperties.skeletons.forEach {
(panelSkeletonsList.model as DefaultListModel).addElement("${it.value}")
}
// populate transforms view
adProperties.transforms.forEach {
(panelTransformsList.model as DefaultListModel).addElement("$it")
}
// populate stats
(panelStatList.model as DefaultListModel).addElement("Spritesheet rows: ${adProperties.rows}")
(panelStatList.model as DefaultListModel).addElement("Spritesheet columns: ${adProperties.cols}")
(panelStatList.model as DefaultListModel).addElement("Frame size: ${adProperties.frameWidth}, ${adProperties.frameHeight}")
(panelStatList.model as DefaultListModel).addElement("Origin position: ${adProperties.originX}, ${adProperties.originY}")
}
catch (fehler: Throwable) {
displayError("ERROR_PARSE_FAIL", fehler)
fehler.printStackTrace()
}
}
})
menu.add(JMenu("Run")).addMouseListener(object : MouseAdapter() {
override fun mousePressed(e: MouseEvent?) {
try {
gdxWindow.requestAssemblyTest(adProperties)
statBar.text = lang.getProperty("SPRITE_ASSEMBLE_SUCCESSFUL")
}
catch (fehler: Throwable) {
displayError("ERROR_PARSE_FAIL", fehler)
fehler.printStackTrace()
}
}
})
menu.add(JMenu("Export")).addMouseListener(object : MouseAdapter() {
override fun mousePressed(e: MouseEvent?) {
val fileChooser = JFileChooser()
fileChooser.showSaveDialog(null)
if (fileChooser.selectedFile != null) {
gdxWindow.requestExport(fileChooser.selectedFile.absolutePath)
statBar.text = lang.getProperty("STAT_SAVE_TGA_SUCCESSFUL")
} // else, do nothing
}
})
this.layout = BorderLayout()
this.add(menu, BorderLayout.NORTH)
this.add(panelMain, BorderLayout.CENTER)
this.add(statBar, BorderLayout.SOUTH)
this.title = "Terrarum Sprite Assembler and Viewer"
this.isVisible = true
this.setSize(1154, 768)
this.defaultCloseOperation = WindowConstants.EXIT_ON_CLOSE
}
private fun displayMessage(messageKey: String) {
JOptionPane.showOptionDialog(
null,
lang.getProperty(messageKey), null,
JOptionPane.DEFAULT_OPTION,
JOptionPane.INFORMATION_MESSAGE, null,
arrayOf("OK", "Cancel"),
"Cancel"
)
}
private fun displayError(messageKey: String, cause: Throwable) {
JOptionPane.showOptionDialog(null,
lang.getProperty(messageKey) + "\n" + cause.toString(), null,
JOptionPane.DEFAULT_OPTION,
JOptionPane.ERROR_MESSAGE, null,
arrayOf("OK", "Cancel"),
"Cancel"
)
}
}
class SpriteAssemblerPreview: Game() {
private lateinit var batch: SpriteBatch
private lateinit var renderTexture: Texture
private var image: Pixmap? = null
set(value) {
renderTexture.dispose()
field?.dispose()
field = value
renderTexture = Texture(field)
}
override fun create() {
Gdx.graphics.setTitle("Sprite Assembler Preview")
batch = SpriteBatch()
renderTexture = Texture(1, 1, Pixmap.Format.RGBA8888)
}
private val bgCol = Color(.62f,.79f,1f,1f)
private var doAssemble = false
private lateinit var assembleProp: ADProperties
private var doExport = false
private lateinit var exportPath: String
override fun render() {
if (doAssemble) {
// assembly requires GL context
doAssemble = false
assembleImage(assembleProp)
}
if (doExport && image != null) {
doExport = false
PixmapIO2.writeTGAHappy(Gdx.files.absolute(exportPath), image, false)
}
gdxClearAndSetBlend(.62f,.79f,1f,1f)
batch.inUse {
batch.color = Color.WHITE
batch.draw(renderTexture, 0f, 0f)
}
}
private fun assembleImage(prop: ADProperties) {
image = AssembleSheetPixmap(prop)
}
// TODO rename to requestAssembly
fun requestAssemblyTest(prop: ADProperties) {
doAssemble = true
assembleProp = prop
}
fun requestExport(path: String) {
doExport = true
exportPath = path
}
override fun resize(width: Int, height: Int) {
super.resize(width, height)
}
}
fun main(args: Array<String>) {
val appConfig = LwjglApplicationConfiguration()
appConfig.resizable = true
appConfig.width = 512
appConfig.height = 512
appConfig.foregroundFPS = 5
appConfig.backgroundFPS = 5
val gdxWindow = SpriteAssemblerPreview()
LwjglApplication(gdxWindow, appConfig)
SpriteAssemblerApp(gdxWindow)
}

View File

@@ -0,0 +1,35 @@
# complete file name is: SPRITESHEET + bodypart name + EXTENSION
SPRITESHEET=mods/basegame/sprites/sprite_assembler_test_assets/test_
EXTENSION=.tga
# defines frame size and origin point. Origin point is given as: (originx, size.y - 1)
CONFIG=SIZE 48,56;ORIGINX 29
# note to self: don't implement skeleton hierarchy: there's too many exceptions
# besides, you have "ALL" key.
! a skeleton also defines what body parts (images) be used.
! you can also write multiline text using reverse solidus; this is a feature of .properties
! skeleton joints are ordered: foremost-drawn object comes first, which means lowermost object IN THIS LIST
! are painted first, and any object that comes before it will paint over it. In other words, this list is
! first reversed then being iterated.
! Joints' original point is defined in the document sprite_joints.psd. It also has visual representations.
# TODO right now accessory points are explicitly defined. Should they be injected in run-time?
SKELETON_STAND=HEADGEAR 0,32;HAIR_FORE 0,32;\
ARM_REST_RIGHT -7,23;HAND_REST_RIGHT -6,11;HELD_ITEM -6,11;\
HAIR 0,32;HEAD 0,32;\
UPPER_TORSO 0,23;LOWER_TORSO 0,15;\
FOOT_RIGHT -2,2;LEG_REST_RIGHT -2,7;\
FOOT_LEFT 2,2;LEG_REST_LEFT 2,7;\
ARM_REST_LEFT 5,24;HAND_REST_LEFT 6,12
# skeleton_stand is used for testing purpose
ANIM_RUN=DELAY 0.15;ROW 2;SKELETON SKELETON_STAND
ANIM_RUN_1=LEG_REST_RIGHT 1,1;FOOT_RIGHT 1,1;LEG_REST_LEFT -1,0;FOOT_LEFT -1,0
ANIM_RUN_2=ALL 0,1;LEG_REST_RIGHT 0,-1;FOOT_RIGHT 0,-1;LEG_REST_LEFT 0,1;FOOT_LEFT 0,1
ANIM_RUN_3=LEG_REST_RIGHT -1,0;FOOT_RIGHT -1,0;LEG_REST_LEFT 1,1;FOOT_LEFT 1,1
ANIM_RUN_4=ALL 0,1;LEG_REST_RIGHT 0,1;FOOT_RIGHT 0,1;LEG_REST_LEFT 0,-1;FOOT_LEFT 0,-1
ANIM_IDLE=DELAY 2;ROW 1;SKELETON SKELETON_STAND
ANIM_IDLE_1=
! ANIM_IDLE_1 will not make any transformation
ANIM_IDLE_2=UPPER_TORSO 0,-1;HEAD 0,-1;HAIR 0,-1;HELD_ITEM 0,-1;ARM_REST_LEFT 0,-1;ARM_REST_RIGHT 0,-1;HAND_REST_LEFT 0,-1;HAND_REST_RIGHT 0,-1;HAIR_FORE 0,-1;HEADGEAR 0,-1

View File

@@ -3,6 +3,7 @@ package net.torvald.terrarum;
import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.audio.AudioDevice;
import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;
import com.badlogic.gdx.graphics.*;
@@ -10,13 +11,24 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.graphics.glutils.FrameBuffer;
import com.badlogic.gdx.graphics.glutils.ShaderProgram;
import com.badlogic.gdx.utils.ScreenUtils;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import net.torvald.dataclass.ArrayListMap;
import net.torvald.terrarum.modulebasegame.IngameRenderer;
import net.torvald.terrarum.utils.JsonFetcher;
import net.torvald.terrarum.utils.JsonWriter;
import net.torvald.terrarumsansbitmap.gdx.GameFontBase;
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Random;
import static net.torvald.terrarum.TerrarumKt.gdxClearAndSetBlend;
/**
* The framework's Application Loader
*
@@ -30,19 +42,62 @@ public class AppLoader implements ApplicationListener {
* AA: Major version
* BB: Minor version
* XXXX: Revision (Repository commits, or something arbitrary)
*
* e.g. 0x02010034 can be translated as 2.1.52
* <p>
* e.g. 0x02010034 will be translated as 2.1.52
*/
public static final int VERSION_RAW = 0x00_02_027C;
public static final boolean IS_DEVELOPMENT_BUILD = true;
public static final int VERSION_RAW = 0x00_02_04B1;
public static final String getVERSION_STRING() {
return String.format("%d.%d.%d", VERSION_RAW >>> 24, (VERSION_RAW & 0xff0000) >>> 16, VERSION_RAW & 0xFFFF);
}
/**
* when FALSE, some assertion and print code will not execute
*/
public static boolean IS_DEVELOPMENT_BUILD = false;
/**
* Singleton instance
*/
private static AppLoader INSTANCE = null;
private AppLoader() { }
/**
* Screen injected at init, so that you run THAT screen instead of the main game.
*/
private static Screen injectScreen = null;
/**
* Initialise the application with the alternative Screen you choose
*
* @param appConfig LWJGL(2) Application Configuration
* @param injectScreen GDX Screen you want to run
*/
public AppLoader(LwjglApplicationConfiguration appConfig, Screen injectScreen) {
AppLoader.injectScreen = injectScreen;
AppLoader.appConfig = appConfig;
}
/**
* Initialise the application with default game screen
*
* @param appConfig LWJGL(2) Application Configuration
*/
public AppLoader(LwjglApplicationConfiguration appConfig) {
AppLoader.appConfig = appConfig;
}
/**
* Default null constructor. Don't use it.
*/
private AppLoader() {
}
/**
* Singleton pattern implementation in Java.
*
* @return
*/
public static AppLoader getINSTANCE() {
if (INSTANCE == null) {
INSTANCE = new AppLoader();
@@ -54,6 +109,9 @@ public class AppLoader implements ApplicationListener {
public static final String COPYRIGHT_DATE_NAME = "Copyright 2013-2018 Torvald (minjaesong)";
public static String GAME_LOCALE = System.getProperty("user.language") + System.getProperty("user.country");
/**
* These languages won't distinguish regional differences (e.g. enUS and enUK, frFR and frCA)
*/
private static final String[] localeSimple = {"de", "en", "es", "it"}; // must be sorted!!
public static String getSysLang() {
@@ -81,12 +139,11 @@ public class AppLoader implements ApplicationListener {
}
}
public static final String getVERSION_STRING() {
return String.format("%d.%d.%d", VERSION_RAW >>> 24, (VERSION_RAW & 0xff0000) >>> 16, VERSION_RAW & 0xFFFF);
}
private static boolean splashDisplayed = false;
private static boolean postInitFired = false;
private static boolean screenshotRequested = false;
public static LwjglApplicationConfiguration appConfig;
public static GameFontBase fontGame;
/**
@@ -95,21 +152,28 @@ public class AppLoader implements ApplicationListener {
public static int GLOBAL_RENDER_TIMER = new Random().nextInt(1020) + 1;
public static ArrayListMap debugTimers = new ArrayListMap<String, Long>();
public static void main(String[] args) {
ShaderProgram.pedantic = false;
appConfig = new LwjglApplicationConfiguration();
LwjglApplicationConfiguration appConfig = new LwjglApplicationConfiguration();
//appConfig.useGL30 = true; // used: loads GL 3.2, unused: loads GL 4.6; what the fuck?
appConfig.vSyncEnabled = false;
appConfig.resizable = false;//true;
//appConfig.width = 1072; // IMAX ratio
//appConfig.height = 742; // IMAX ratio
appConfig.width = 1110; // photographic ratio (1.5:1)
appConfig.height = 740; // photographic ratio (1.5:1)
appConfig.backgroundFPS = 9999;
appConfig.foregroundFPS = 9999;
appConfig.title = GAME_NAME;
appConfig.forceExit = false;
new LwjglApplication(new AppLoader(), appConfig);
if (args.length == 1 && args[0].equals("isdev=true")) {
IS_DEVELOPMENT_BUILD = true;
}
new LwjglApplication(new AppLoader(appConfig), appConfig);
}
@@ -121,11 +185,16 @@ public class AppLoader implements ApplicationListener {
private OrthographicCamera camera;
private SpriteBatch logoBatch;
public static TextureRegion logo;
public static AudioDevice audioDevice;
private Color gradWhiteTop = new Color(0xf8f8f8ff);
private Color gradWhiteBottom = new Color(0xd8d8d8ff);
public Screen screen;
public static int screenW = 0;
public static int screenH = 0;
public static Texture textureWhiteSquare;
private void initViewPort(int width, int height) {
// Set Y to point downwards
@@ -138,6 +207,8 @@ public class AppLoader implements ApplicationListener {
Gdx.gl20.glViewport(0, 0, width, height);
}
public static final double UPDATE_RATE = 1.0 / 61.0; // TODO set it like 1/100, because apparent framerate is limited by update rate
private float loadTimer = 0f;
private final float showupTime = 100f / 1000f;
@@ -148,16 +219,14 @@ public class AppLoader implements ApplicationListener {
logoBatch = new SpriteBatch();
camera = new OrthographicCamera(((float) appConfig.width), ((float) appConfig.height));
initViewPort(appConfig.width, appConfig.height);
logo = new TextureRegion(new Texture(Gdx.files.internal("assets/graphics/logo_placeholder.tga")));
logo.flip(false, true);
shaderBayerSkyboxFill = new ShaderProgram(Gdx.files.internal("assets/4096.vert"), Gdx.files.internal("assets/4096_bayer_skyboxfill.frag"));
shaderHicolour = new ShaderProgram(Gdx.files.internal("assets/4096.vert"), Gdx.files.internal("assets/hicolour.frag"));
shaderColLUT = new ShaderProgram(Gdx.files.internal("assets/4096.vert"), Gdx.files.internal("assets/passthru.frag"));
shaderBayerSkyboxFill = loadShader("assets/4096.vert", "assets/4096_bayer_skyboxfill.frag");
shaderHicolour = loadShader("assets/4096.vert", "assets/hicolour.frag");
shaderColLUT = loadShader("assets/4096.vert", "assets/passthru.frag");
fullscreenQuad = new Mesh(
true, 4, 6,
@@ -165,40 +234,107 @@ public class AppLoader implements ApplicationListener {
VertexAttribute.ColorUnpacked(),
VertexAttribute.TexCoords(0)
);
updateFullscreenQuad(appConfig.width, appConfig.height);
}
fullscreenQuad.setVertices(new float[]{
0f, 0f, 0f, 1f, 1f, 1f, 1f, 0f, 1f,
((float) appConfig.width), 0f, 0f, 1f, 1f, 1f, 1f, 1f, 1f,
((float) appConfig.width), ((float) appConfig.height), 0f, 1f, 1f, 1f, 1f, 1f, 0f,
0f, ((float) appConfig.height), 0f, 1f, 1f, 1f, 1f, 0f, 0f
});
fullscreenQuad.setIndices(new short[]{0, 1, 2, 2, 3, 0});
private static double _kalman_xhat_k = UPDATE_RATE;
private static double _kalman_return_value = _kalman_xhat_k;
private static double _kalman_p_k = 1.0;
private static final double _kalman_R = 0.2; // 0.2: empirical value
private final double _KALMAN_UPDATE_THRE = 0.1;
/**
* Because fuck you GDX. (No, really; take a look at LwjglGraphics.java, getDeltaTime() and rawDeltaTime() are exactly the same)
* @return Render delta that is smoothed out.
*/
public static double getSmoothDelta() {
// kalman filter is calculated but not actually being used.
logo = new TextureRegion(new Texture(Gdx.files.internal("assets/graphics/logo_placeholder.tga")));
logo.flip(false, true);
// below is the kalman part
return _kalman_return_value;
}
public static void resetDeltaSmoothingHistory() {
_kalman_xhat_k = UPDATE_RATE;
_kalman_p_k = 1.0;
}
/**
* @link http://bilgin.esme.org/BitsAndBytes/KalmanFilterforDummies
*/
private void updateKalmanRenderDelta() {
// TODO implement nonlinear kalman filter
// kalman filter is calculated but not actually being used.
// the problem with this kalman filter is that it assumes most simplistic situation:
// 1. the actual delta (measured delta - noise) is constant
// 2. everything is linear
// we may need to implement Extended Kalman Filter but wtf is Jacobian, I suck at maths.
// Instead, the kalman filter will reset when new delta is given-value-times greater/lesser
// it's not perfect but it works.
double observation = ((double) Gdx.graphics.getRawDeltaTime());
if (getMul(observation, _kalman_return_value) >= 2.5) {
resetDeltaSmoothingHistory();
}
// measurement value
double _kalman_zed_k = observation;
if (_kalman_zed_k <= _KALMAN_UPDATE_THRE) {
// time update
double _kalman_xhatminus_k = _kalman_xhat_k;
double _kalman_pminus_k = _kalman_p_k;
// measurement update
double _kalman_gain = _kalman_pminus_k / (_kalman_pminus_k + _kalman_R);
double _kalman_xhat_kNew = _kalman_xhatminus_k + _kalman_gain * (_kalman_zed_k - _kalman_xhatminus_k);
double _kalman_p_kNew = (1.0 - _kalman_gain) * _kalman_pminus_k;
_kalman_xhat_k = _kalman_xhat_kNew;
_kalman_p_k = _kalman_p_kNew;
_kalman_return_value = _kalman_xhat_kNew;
}
}
TextureRegionPack.Companion.setGlobalFlipY(true);
fontGame = new GameFontBase("assets/graphics/fonts/terrarum-sans-bitmap", false, true, Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest, false, 128, false);
private final double getMul_epsilon = 0.00001;
// only for a > 0 && b > 0
private double getMul(double a, double b) {
if (a < getMul_epsilon || b < getMul_epsilon) {
return a + b;
}
if (a > b) {
return a / b;
}
else {
return b / a;
}
}
@Override
public void render() {
FrameBufferManager.begin(renderFBO);
Gdx.gl.glClearColor(.094f, .094f, .094f, 0f);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
Gdx.gl.glEnable(GL20.GL_TEXTURE_2D);
Gdx.gl.glEnable(GL20.GL_BLEND);
Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
Gdx.gl.glBlendEquation(GL20.GL_FUNC_ADD);
FrameBufferManager.end();
if (splashDisplayed && !postInitFired) {
postInitFired = true;
postInit();
}
// update smooth delta AFTER postInit
updateKalmanRenderDelta();
FrameBufferManager.begin(renderFBO);
gdxClearAndSetBlend(.094f, .094f, .094f, 0f);
setCameraPosition(0, 0);
// draw splash screen when predefined screen is null
// because in normal operation, the only time screen == null is when the app is cold-launched
// you can't have a text drawn here :v
if (screen == null) {
shaderBayerSkyboxFill.begin();
shaderBayerSkyboxFill.setUniformMatrix("u_projTrans", camera.combined);
@@ -224,13 +360,14 @@ public class AppLoader implements ApplicationListener {
loadTimer += Gdx.graphics.getRawDeltaTime();
if (loadTimer >= showupTime) {
Terrarum.INSTANCE.setScreenW(appConfig.width);
Terrarum.INSTANCE.setScreenH(appConfig.height);
// hand over the scene control to this single class; Terrarum must call
// 'AppLoader.getINSTANCE().screen.render(delta)', this is not redundant at all!
setScreen(Terrarum.INSTANCE);
}
}
// draw the screen
else {
screen.render(Gdx.graphics.getDeltaTime());
screen.render((float) UPDATE_RATE);
}
// nested FBOs are just not a thing in GL!
@@ -239,7 +376,21 @@ public class AppLoader implements ApplicationListener {
PostProcessor.INSTANCE.draw(camera.combined, renderFBO);
// process screenshot request
if (screenshotRequested) {
screenshotRequested = false;
try {
Pixmap p = ScreenUtils.getFrameBufferPixmap(0, 0, appConfig.width, appConfig.height);
PixmapIO2.writeTGA(Gdx.files.absolute(defaultDir + "/Screenshot.tga"), p, true);
p.dispose();
}
catch (Throwable e) {
e.printStackTrace();
}
}
splashDisplayed = true;
GLOBAL_RENDER_TIMER += 1;
}
@@ -247,52 +398,72 @@ public class AppLoader implements ApplicationListener {
public void resize(int width, int height) {
//initViewPort(width, height);
Terrarum.INSTANCE.resize(width, height);
if (screen != null) screen.resize(Terrarum.INSTANCE.getWIDTH(), Terrarum.INSTANCE.getHEIGHT());
screenW = width;
screenH = height;
if (screenW % 2 == 1) screenW -= 1;
if (screenH % 2 == 1) screenH -= 1;
if (screen != null) screen.resize(screenW, screenH);
if (renderFBO == null ||
(renderFBO.getWidth() != Terrarum.INSTANCE.getWIDTH() ||
renderFBO.getHeight() != Terrarum.INSTANCE.getHEIGHT())
) {
(renderFBO.getWidth() != screenW ||
renderFBO.getHeight() != screenH)
) {
renderFBO = new FrameBuffer(
Pixmap.Format.RGBA8888,
Terrarum.INSTANCE.getWIDTH(),
Terrarum.INSTANCE.getHEIGHT(),
screenW,
screenH,
false
);
}
appConfig.width = Terrarum.INSTANCE.getWIDTH();
appConfig.height = Terrarum.INSTANCE.getHEIGHT();
appConfig.width = screenW;
appConfig.height = screenH;
updateFullscreenQuad(screenW, screenH);
printdbg(this, "Resize event");
resetDeltaSmoothingHistory();
}
@Override
public void dispose () {
if (screen != null) screen.hide();
public void dispose() {
System.out.println("Goodbye !");
if (screen != null) {
screen.hide();
screen.dispose();
}
IngameRenderer.INSTANCE.dispose();
// delete temp files
new File("./tmp_wenquanyi.tga").delete();
new File("./tmp_wenquanyi.tga").delete(); // FIXME this is pretty much ad-hoc
}
@Override
public void pause () {
public void pause() {
if (screen != null) screen.pause();
}
@Override
public void resume () {
public void resume() {
if (screen != null) screen.resume();
}
public void setScreen(Screen screen) {
printdbg(this, "Changing screen to " + screen.getClass().getCanonicalName());
if (this.screen != null) this.screen.hide();
// this whole thing is directtly copied from com.badlogic.gdx.Game
if (this.screen != null) {
this.screen.hide();
}
this.screen = screen;
if (this.screen != null) {
this.screen.show();
@@ -300,8 +471,36 @@ public class AppLoader implements ApplicationListener {
}
printdbg(this, "Screen transisiton complete: " + this.screen.getClass().getCanonicalName());
resetDeltaSmoothingHistory();
}
private void postInit() {
// load configs
getDefaultDirectory();
createDirs();
readConfigJson();
textureWhiteSquare = new Texture(Gdx.files.internal("assets/graphics/ortho_line_tex_2px.tga"));
textureWhiteSquare.setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest);
TextureRegionPack.Companion.setGlobalFlipY(true);
fontGame = new GameFontBase("assets/graphics/fonts/terrarum-sans-bitmap", false, true,
Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest, false, 256, false
);
audioDevice = Gdx.audio.newAudioDevice(48000, false);
// if there is a predefined screen, open that screen after my init process
if (injectScreen != null) {
setScreen(injectScreen);
}
printdbg(this, "PostInit done");
}
private void setCameraPosition(float newX, float newY) {
camera.position.set((-newX + appConfig.width / 2), (-newY + appConfig.height / 2), 0f);
camera.update();
@@ -318,15 +517,243 @@ public class AppLoader implements ApplicationListener {
fullscreenQuad.setIndices(new short[]{0, 1, 2, 2, 3, 0});
}
public static void requestScreenshot() {
screenshotRequested = true;
}
public static final void printdbg(Object obj, Object message) {
if (IS_DEVELOPMENT_BUILD) {
System.out.println("["+obj.getClass().getSimpleName()+"] "+message.toString());
// DEFAULT DIRECTORIES //
public static String OSName = System.getProperty("os.name");
public static String OSVersion = System.getProperty("os.version");
public static String operationSystem;
/** %appdata%/Terrarum, without trailing slash */
public static String defaultDir;
/** defaultDir + "/Saves", without trailing slash */
public static String defaultSaveDir;
/** defaultDir + "/config.json" */
public static String configDir;
public static RunningEnvironment environment;
private void getDefaultDirectory() {
String OS = OSName.toUpperCase();
if (OS.contains("WIN")) {
operationSystem = "WINDOWS";
defaultDir = System.getenv("APPDATA") + "/Terrarum";
}
else if (OS.contains("OS X")) {
operationSystem = "OSX";
defaultDir = System.getProperty("user.home") + "/Library/Application Support/Terrarum";
}
else if (OS.contains("NUX") || OS.contains("NIX") || OS.contains("BSD")) {
operationSystem = "LINUX";
defaultDir = System.getProperty("user.home") + "/.Terrarum";
}
else if (OS.contains("SUNOS")) {
operationSystem = "SOLARIS";
defaultDir = System.getProperty("user.home") + "/.Terrarum";
}
else if (System.getProperty("java.runtime.name").toUpperCase().contains("ANDROID")) {
operationSystem = "ANDROID";
defaultDir = System.getProperty("user.home") + "/.Terrarum";
environment = RunningEnvironment.MOBILE;
}
else {
operationSystem = "UNKNOWN";
defaultDir = System.getProperty("user.home") + "/.Terrarum";
}
defaultSaveDir = defaultDir + "/Saves";
configDir = defaultDir + "/config.json";
System.out.println(String.format("os.name = %s (with identifier %s)", OSName, operationSystem));
System.out.println(String.format("os.version = %s", OSVersion));
System.out.println(String.format("default directory: %s", defaultDir));
}
private void createDirs() {
File[] dirs = {new File(defaultSaveDir)};
for (File it : dirs) {
if (!it.exists())
it.mkdirs();
}
//dirs.forEach { if (!it.exists()) it.mkdirs() }
}
// CONFIG //
private static KVHashMap gameConfig = new KVHashMap();
private static void createConfigJson() throws IOException {
File configFile = new File(configDir);
if (!configFile.exists() || configFile.length() == 0L) {
JsonWriter.INSTANCE.writeToFile(DefaultConfig.INSTANCE.fetch(), configDir);
}
}
public static final void printdbgerr(Object obj, Object message) {
if (IS_DEVELOPMENT_BUILD) {
System.err.println("["+obj.getClass().getSimpleName()+"] "+message.toString());
/**
*
* @return true on successful, false on failure.
*/
private static Boolean readConfigJson() {
try {
// read from disk and build config from it
JsonObject jsonObject = JsonFetcher.INSTANCE.invoke(configDir);
// make config
jsonObject.entrySet().forEach((entry) ->
gameConfig.set(entry.getKey(), entry.getValue())
);
return true;
}
catch (java.nio.file.NoSuchFileException e) {
// write default config to game dir. Call this method again to read config from it.
try {
createConfigJson();
}
catch (IOException e1) {
System.out.println("[AppLoader] Unable to write config.json file");
e.printStackTrace();
}
return false;
}
}
/**
* Return config from config set. If the config does not exist, default value will be returned.
* @param key
* *
* @return Config from config set or default config if it does not exist.
* *
* @throws NullPointerException if the specified config simply does not exist.
*/
public static int getConfigInt(String key) {
Object cfg = getConfigMaster(key);
if (cfg instanceof JsonPrimitive)
return ((JsonPrimitive) cfg).getAsInt();
else
return Integer.parseInt(((String) cfg));
}
/**
* Return config from config set. If the config does not exist, default value will be returned.
* @param key
* *
* @return Config from config set or default config if it does not exist.
* *
* @throws NullPointerException if the specified config simply does not exist.
*/
public static String getConfigString(String key) {
Object cfg = getConfigMaster(key);
if (cfg instanceof JsonPrimitive)
return ((JsonPrimitive) cfg).getAsString();
else
return ((String) cfg);
}
/**
* Return config from config set. If the config does not exist, default value will be returned.
* @param key
* *
* @return Config from config set or default config if it does not exist.
* *
* @throws NullPointerException if the specified config simply does not exist.
*/
public static boolean getConfigBoolean(String key) {
Object cfg = getConfigMaster(key);
if (cfg instanceof JsonPrimitive)
return ((JsonPrimitive) cfg).getAsBoolean();
else
return ((boolean) cfg);
}
public static int[] getConfigIntArray(String key) {
Object cfg = getConfigMaster(key);
if (cfg instanceof JsonArray) {
JsonArray jsonArray = ((JsonArray) cfg).getAsJsonArray();
//return IntArray(jsonArray.size(), { i -> jsonArray[i].asInt })
int[] intArray = new int[jsonArray.size()];
for (int i = 0; i < jsonArray.size(); i++) {
intArray[i] = jsonArray.get(i).getAsInt();
}
return intArray;
}
else
return ((int[]) cfg);
}
/**
* Get config from config file. If the entry does not exist, get from defaults; if the entry is not in the default, NullPointerException will be thrown
*/
private static JsonObject getDefaultConfig() {
return DefaultConfig.INSTANCE.fetch();
}
private static Object getConfigMaster(String key1) {
String key = key1.toLowerCase();
Object config;
try {
config = gameConfig.get(key);
}
catch (NullPointerException e) {
config = null;
}
Object defaults;
try {
defaults = getDefaultConfig().get(key);
}
catch (NullPointerException e) {
defaults = null;
}
if (config == null) {
if (defaults == null) {
throw new NullPointerException("key not found: '$key'");
}
else {
return defaults;
}
}
else {
return config;
}
}
}
public static void setConfig(String key, Object value) {
gameConfig.set(key, value);
}
// //
public static void printdbg(Object obj, Object message) {
if (IS_DEVELOPMENT_BUILD || getConfigBoolean("forcedevbuild")) {
System.out.println("[" + obj.getClass().getSimpleName() + "] " + message.toString());
}
}
public static void printdbgerr(Object obj, Object message) {
if (IS_DEVELOPMENT_BUILD || getConfigBoolean("forcedevbuild")) {
System.err.println("[" + obj.getClass().getSimpleName() + "] " + message.toString());
}
}
public static ShaderProgram loadShader(String vert, String frag) {
ShaderProgram s = new ShaderProgram(Gdx.files.internal(vert), Gdx.files.internal(frag));
if (s.getLog().contains("error C")) {
throw new Error(String.format("Shader program loaded with %s, %s failed:\n%s", vert, frag, s.getLog()));
}
return s;
}
}

View File

@@ -15,6 +15,7 @@ object DefaultConfig {
jsonObject.addProperty("displayfps", 0) // 0: no limit, non-zero: limit
jsonObject.addProperty("usevsync", true)
jsonObject.addProperty("forcedevbuild", false)
jsonObject.addProperty("imtooyoungtodie", false) // no perma-death
@@ -66,8 +67,8 @@ object DefaultConfig {
jsonObject.addProperty("keyjump", Input.Keys.SPACE)
val keyquickbars = JsonArray(); for (i in Input.Keys.NUMPAD_1..Input.Keys.NUMPAD_9) keyquickbars.add(i); keyquickbars.add(Input.Keys.NUMPAD_0) // NUM_1 to NUM_0
jsonObject.add("keyquickbars", keyquickbars)
val keyquickslots = JsonArray(); for (i in Input.Keys.NUM_1..Input.Keys.NUM_9) keyquickslots.add(i); keyquickslots.add(Input.Keys.NUM_0) // NUM_1 to NUM_0
jsonObject.add("keyquickslots", keyquickslots)
jsonObject.addProperty("mouseprimary", Input.Buttons.LEFT) // left mouse
jsonObject.addProperty("mousesecondary", Input.Buttons.RIGHT) // right mouse
@@ -75,23 +76,17 @@ object DefaultConfig {
jsonObject.addProperty("pcgamepadenv", "console")
jsonObject.addProperty("safetywarning", true)
//jsonObject.addProperty("safetywarning", true)
jsonObject.addProperty("maxparticles", 768)
jsonObject.addProperty("fullframelightupdate", false)
jsonObject.addProperty("temperatureunit", 1) // -1: american, 0: kelvin, 1: celcius
// "fancy" graphics settings
jsonObject.addProperty("fxdither", true)
jsonObject.addProperty("fx3dlut", false)
jsonObject.addProperty("__debug", false)
//jsonObject.addProperty("fx3dlut", false)
return jsonObject

View File

@@ -3,7 +3,6 @@ package net.torvald.terrarum
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.Screen
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.GL20
import com.badlogic.gdx.graphics.OrthographicCamera
import com.badlogic.gdx.graphics.g2d.SpriteBatch
import net.torvald.terrarum.langpack.Lang
@@ -39,8 +38,7 @@ object ErrorDisp : Screen {
}
override fun render(delta: Float) {
Gdx.gl.glClearColor(.094f, .094f, .094f, 0f)
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)
gdxClearAndSetBlend(.094f, .094f, .094f, 0f)

View File

@@ -65,7 +65,7 @@ class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
* list of Actors that is sorted by Actors' referenceID
*/
//val ACTORCONTAINER_INITIAL_SIZE = 64
val PARTICLES_MAX = Terrarum.getConfigInt("maxparticles")
val PARTICLES_MAX = AppLoader.getConfigInt("maxparticles")
//val actorContainer = ArrayList<Actor>(ACTORCONTAINER_INITIAL_SIZE)
//val actorContainerInactive = ArrayList<Actor>(ACTORCONTAINER_INITIAL_SIZE)
val particlesContainer = CircularArray<ParticleBase>(PARTICLES_MAX)
@@ -362,14 +362,14 @@ class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
width = 900,
height = Terrarum.HEIGHT - 160,
categoryWidth = 210,
toggleKeyLiteral = Terrarum.getConfigInt("keyinventory")
toggleKeyLiteral = AppLoader.getConfigInt("keyinventory")
)*/
/*uiInventoryPlayer.setPosition(
-uiInventoryPlayer.width,
70
)*/
uiInventoryPlayer = UIInventoryFull(player,
toggleKeyLiteral = Terrarum.getConfigInt("keyinventory")
toggleKeyLiteral = AppLoader.getConfigInt("keyinventory")
)
uiInventoryPlayer.setPosition(0, 0)
@@ -464,7 +464,7 @@ class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
override fun run() {
var updateTries = 0
while (ingame.updateDeltaCounter >= ingame.updateRate) {
ingame.updateGame(Terrarum.deltaTime)
ingame.updateGame(AppLoader.getSmoothDelta().toFloat())
ingame.updateDeltaCounter -= ingame.updateRate
updateTries++
@@ -515,7 +515,7 @@ class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
if (false && Terrarum.getConfigBoolean("multithread")) { // NO MULTITHREADING: camera don't like concurrent modification (jittery actor movements)
if (false && AppLoader.getConfigBoolean("multithread")) { // NO MULTITHREADING: camera don't like concurrent modification (jittery actor movements)
if (firstTimeRun || updateThreadWrapper.state == Thread.State.TERMINATED) {
updateThreadWrapper = Thread(ingameUpdateThread, "Terrarum UpdateThread")
updateThreadWrapper.start()
@@ -529,7 +529,7 @@ class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
while (updateDeltaCounter >= updateRate) {
//updateGame(delta)
Terrarum.debugTimers["Ingame.update"] = measureNanoTime { updateGame(delta) }
AppLoader.debugTimers["Ingame.update"] = measureNanoTime { updateGame(delta) }
updateDeltaCounter -= updateRate
updateTries++
@@ -544,7 +544,7 @@ class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
/** RENDER CODE GOES HERE */
//renderGame(batch)
Terrarum.debugTimers["Ingame.render"] = measureNanoTime { renderGame(batch) }
AppLoader.debugTimers["Ingame.render"] = measureNanoTime { renderGame(batch) }
}
protected fun updateGame(delta: Float) {
@@ -1090,7 +1090,7 @@ class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
}
playableActorDelegate = newActor
WorldSimulator(player, Terrarum.deltaTime)
WorldSimulator(player, AppLoader.getSmoothDelta().toFloat())
}
private fun changePossession(refid: Int) {
@@ -1107,7 +1107,7 @@ class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
// accept new delegate
playableActorDelegate = PlayableActorDelegate(getActorByID(refid) as ActorHumanoid)
playableActorDelegate!!.actor.collisionType = ActorWithPhysics.COLLISION_KINEMATIC
WorldSimulator(player, Terrarum.deltaTime)
WorldSimulator(player, AppLoader.getSmoothDelta().toFloat())
}
/** Send message to notifier UI and toggle the UI as opened. */

View File

@@ -55,4 +55,40 @@ class GdxColorMap {
fun getRaw(x: Int, y: Int): RGBA8888 = data[y * width + x]
fun getRaw(x: Int): RGBA8888 = if (is2D) throw OperationNotSupportedException("This is 2D color map") else data[x]
override fun toString(): String {
val sb = StringBuilder()
sb.append("ColorMap ${width}x$height:\n")
var yi = 0
var xi = 0
for (y in ((0 until height).take(2) + (0 until height).toList().takeLast(2)).distinct()) {
if (y - yi > 1) {
sb.append(when (width) {
in 1..4 -> ".......... ".repeat(width) + '\n'
else -> ".......... .......... ... .......... .......... \n"
}
)
}
for (x in ((0 until width).take(2) + (0 until width).toList().takeLast(2)).distinct()) {
if (x - xi > 1) {
sb.append("... ")
}
sb.append("0x")
sb.append(getRaw(x, y).toLong().and(0xFFFFFFFF).toString(16).toUpperCase().padStart(8, '0'))
sb.append(' ')
xi = x
}
sb.append('\n')
yi = y
}
return sb.toString()
}
}

View File

@@ -6,7 +6,7 @@ import net.torvald.terrarum.gameactors.Actor
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
import net.torvald.terrarum.ui.ConsoleWindow
import java.util.ArrayList
import java.util.*
import java.util.concurrent.locks.Lock
import java.util.concurrent.locks.ReentrantLock
import javax.swing.JOptionPane
@@ -23,7 +23,7 @@ open class IngameInstance(val batch: SpriteBatch) : Screen {
open lateinit var consoleHandler: ConsoleWindow
open lateinit var world: GameWorld
open var world: GameWorld = GameWorld.makeNullWorld()
/** how many different planets/stages/etc. are thenre. Whole stages must be manually managed by YOU. */
var gameworldCount = 0
/** The actor the game is currently allowing you to control.
@@ -36,6 +36,11 @@ open class IngameInstance(val batch: SpriteBatch) : Screen {
*/
open var actorNowPlaying: ActorHumanoid? = null
open var gameInitialised = false
internal set
open var gameFullyLoaded = false
internal set
val ACTORCONTAINER_INITIAL_SIZE = 64
val actorContainer = ArrayList<Actor>(ACTORCONTAINER_INITIAL_SIZE)
val actorContainerInactive = ArrayList<Actor>(ACTORCONTAINER_INITIAL_SIZE)
@@ -44,6 +49,8 @@ open class IngameInstance(val batch: SpriteBatch) : Screen {
}
override fun show() {
// the very basic show() implementation
gameInitialised = true
}
override fun render(delta: Float) {
@@ -197,7 +204,7 @@ open class IngameInstance(val batch: SpriteBatch) : Screen {
fun insertionSortLastElem(arr: ArrayList<Actor>) {
lock(ReentrantLock()) {
ReentrantLock().lock {
var j = arr.lastIndex - 1
val x = arr.last()
while (j >= 0 && arr[j] > x) {
@@ -208,13 +215,14 @@ open class IngameInstance(val batch: SpriteBatch) : Screen {
}
}
inline fun lock(lock: Lock, body: () -> Unit) {
lock.lock()
try {
body()
}
finally {
lock.unlock()
}
}
inline fun Lock.lock(body: () -> Unit) {
this.lock()
try {
body()
}
}
finally {
this.unlock()
}
}

View File

@@ -9,7 +9,6 @@ import com.google.gson.JsonPrimitive
import kotlin.collections.HashMap
typealias ItemValue = KVHashMap
typealias GameConfig = KVHashMap
/**
* Created by minjaesong on 2015-12-30.

View File

@@ -2,19 +2,21 @@ package net.torvald.terrarum
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.ScreenAdapter
import com.badlogic.gdx.graphics.*
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.OrthographicCamera
import com.badlogic.gdx.graphics.Pixmap
import com.badlogic.gdx.graphics.Texture
import com.badlogic.gdx.graphics.glutils.FrameBuffer
import com.jme3.math.FastMath
import net.torvald.dataclass.HistoryArray
import net.torvald.terrarum.langpack.Lang
import net.torvald.terrarum.modulebasegame.Ingame
/**
* Created by minjaesong on 2017-07-13.
*/
object LoadScreen : ScreenAdapter() {
var screenToLoad: Ingame? = null
var screenToLoad: IngameInstance? = null
private lateinit var screenLoadingThread: Thread
@@ -123,12 +125,10 @@ object LoadScreen : ScreenAdapter() {
Gdx.gl.glClearColor(.094f, .094f, .094f, 0f)
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)
gdxClearAndSetBlend(.094f, .094f, .094f, 0f)
textFbo.inAction(null, null) {
Gdx.gl.glClearColor(0f, 0f, 0f, 0f)
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)
gdxClearAndSetBlend(0f, 0f, 0f, 0f)
}
// update arrow object
@@ -161,7 +161,7 @@ object LoadScreen : ScreenAdapter() {
Terrarum.batch.inUse {
blendNormal()
blendNormal(Terrarum.batch)
Terrarum.fontGame
it.color = Color.WHITE
@@ -169,7 +169,7 @@ object LoadScreen : ScreenAdapter() {
Terrarum.fontGame.draw(it, textToPrint, ((textFbo.width - textWidth) / 2).toInt().toFloat(), 0f)
blendMul()
blendMul(Terrarum.batch)
// draw colour overlay, flipped
it.draw(textOverlayTex,
(textFbo.width - textWidth) / 2f,
@@ -184,7 +184,7 @@ object LoadScreen : ScreenAdapter() {
Terrarum.batch.inUse {
initViewPort(Terrarum.WIDTH, Terrarum.HEIGHT) // dunno, no render without this
it.projectionMatrix = camera.combined
blendNormal()
blendNormal(Terrarum.batch)
// almost black background
@@ -251,7 +251,7 @@ object LoadScreen : ScreenAdapter() {
initViewPort(Terrarum.WIDTH, Terrarum.HEIGHT) // dunno, no render without this
it.projectionMatrix = camera.combined
blendNormal()
blendNormal(Terrarum.batch)

View File

@@ -229,6 +229,8 @@ object ModMgr {
val className = it["classname"].toString()
val itemID = it["id"].toInt()
printdbg(this, "Reading item #$itemID with className $className")
val loadedClass = Class.forName(className)
val loadedClassConstructor = loadedClass.getConstructor(ItemID::class.java)
val loadedClassInstance = loadedClassConstructor.newInstance(itemID)

View File

@@ -53,3 +53,5 @@ data class Point2d(var x: Double, var y: Double) : Cloneable {
fun distSqr(other: Point2d) = ((this.x - other.x).sqr() + (this.y - other.y).sqr())
}
data class Point2i(val x: Int, val y: Int)

View File

@@ -37,16 +37,12 @@ object PostProcessor {
Terrarum.debugTimers["Renderer.PostProcessor"] = measureNanoTime {
AppLoader.debugTimers["Renderer.PostProcessor"] = measureNanoTime {
Gdx.gl.glClearColor(.094f, .094f, .094f, 0f)
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)
Gdx.gl.glEnable(GL20.GL_TEXTURE_2D)
Gdx.gl.glEnable(GL20.GL_BLEND)
Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA)
gdxClearAndSetBlend(.094f, .094f, .094f, 0f)
val shader: ShaderProgram? =
if (Terrarum.getConfigBoolean("fxdither"))
if (AppLoader.getConfigBoolean("fxdither"))
AppLoader.shaderHicolour
else
null
@@ -54,7 +50,6 @@ object PostProcessor {
fbo.colorBufferTexture.bind(0)
shader?.begin()
shader?.setUniformf("resolution", AppLoader.appConfig.width.toFloat(), AppLoader.appConfig.height.toFloat())
shader?.setUniformMatrix("u_projTrans", projMat)
shader?.setUniformi("u_texture", 0)
AppLoader.fullscreenQuad.render(shader, GL20.GL_TRIANGLES)

View File

@@ -0,0 +1,72 @@
package net.torvald.terrarum
import java.util.*
import kotlin.collections.ArrayList
class QNDTreeNode<T>(var data: T? = null, var parent: QNDTreeNode<T>? = null) {
var children = ArrayList<QNDTreeNode<T>>()
private fun traverse1(node: QNDTreeNode<T>, action: (QNDTreeNode<T>, Int) -> Unit, depth: Int = 0) {
//if (node == null) return
action(node, depth)
node.children.forEach { traverse1(it, action, depth + 1) }
}
private fun traverse2(node: QNDTreeNode<T>, action: (QNDTreeNode<T>, Int) -> Unit, depth: Int = 0) {
//if (node == null) return
node.children.forEach { traverse2(it, action, depth + 1) }
action(node, depth)
}
/**
* (QNDTreeNode, Int) is Node-depth pair, starting from zero.
*/
fun traversePreorder(action: (QNDTreeNode<T>, Int) -> Unit) {
this.traverse1(this, action)
}
/**
* (QNDTreeNode, Int) is Node-depth pair, starting from zero.
*/
fun traversePostorder(action: (QNDTreeNode<T>, Int) -> Unit) {
this.traverse2(this, action)
}
/**
* (QNDTreeNode, Int) is Node-depth pair, starting from zero.
*/
fun traverseLevelorder(action: (QNDTreeNode<T>, Int) -> Unit) {
val q = ArrayList<Pair<QNDTreeNode<T>, Int>>() // node, depth
q.add(this to 0)
while (q.isNotEmpty()) {
val node = q.removeAt(0)
action(node.first, node.second)
node.first.children.forEach {
q.add(it to node.second + 1)
}
}
}
/**
* Retrieves data in the node in a specific depth (level).
* Probably only useful for level = 1
*/
fun getLevelData(level: Int): List<T?> {
val list = ArrayList<T?>()
traversePreorder { node, i ->
if (i == level) {
list.add(node.data)
}
}
return list
}
override fun toString() = data.toString()
fun print() {
TODO()
}
}

View File

@@ -3,26 +3,24 @@ package net.torvald.terrarum
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.Screen
import com.badlogic.gdx.assets.AssetManager
import com.badlogic.gdx.graphics.*
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.GL20
import com.badlogic.gdx.graphics.OrthographicCamera
import com.badlogic.gdx.graphics.Texture
import com.badlogic.gdx.graphics.g2d.SpriteBatch
import com.badlogic.gdx.graphics.glutils.FrameBuffer
import com.badlogic.gdx.graphics.glutils.ShaderProgram
import com.badlogic.gdx.graphics.glutils.ShapeRenderer
import com.badlogic.gdx.utils.GdxRuntimeException
import com.google.gson.JsonArray
import com.google.gson.JsonPrimitive
import com.jme3.math.FastMath
import net.torvald.dataclass.ArrayListMap
import net.torvald.dataclass.CircularArray
import net.torvald.getcpuname.GetCpuName
import net.torvald.random.HQRNG
import net.torvald.terrarum.AppLoader.printdbg
import net.torvald.terrarum.AppLoader.printdbgerr
import net.torvald.terrarum.AppLoader.*
import net.torvald.terrarum.gameactors.Actor
import net.torvald.terrarum.gameactors.ActorID
import net.torvald.terrarum.imagefont.TinyAlphNum
import net.torvald.terrarum.itemproperties.ItemCodex
import net.torvald.terrarum.utils.JsonFetcher
import net.torvald.terrarum.utils.JsonWriter
import net.torvald.terrarum.worlddrawer.FeaturesDrawer
import net.torvald.terrarum.worlddrawer.WorldCamera
import net.torvald.terrarumsansbitmap.gdx.GameFontBase
@@ -30,8 +28,7 @@ import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
import org.lwjgl.BufferUtils
import org.lwjgl.input.Controllers
import java.io.File
import java.io.IOException
import net.torvald.getcpuname.GetCpuName
import kotlin.math.absoluteValue
@@ -50,11 +47,6 @@ object Terrarum : Screen {
*/
const val PLAYER_REF_ID: Int = 0x91A7E2
val debugTimers = ArrayListMap<String, Long>()
var screenW = 0
var screenH = 0
lateinit var batch: SpriteBatch
lateinit var shapeRender: ShapeRenderer // DO NOT USE!! for very limited applications e.g. WeatherMixer
inline fun inShapeRenderer(shapeRendererType: ShapeRenderer.ShapeType = ShapeRenderer.ShapeType.Filled, action: (ShapeRenderer) -> Unit) {
@@ -69,9 +61,9 @@ object Terrarum : Screen {
//////////////////////////////
val WIDTH: Int
get() = if (screenW % 2 == 0) screenW else screenW - 1
get() = AppLoader.screenW
val HEIGHT: Int
get() = if (screenH % 2 == 0) screenH else screenH - 1
get() = AppLoader.screenH
//val WIDTH_MIN = 800
//val HEIGHT_MIN = 600
@@ -82,44 +74,22 @@ object Terrarum : Screen {
get() = HEIGHT.ushr(1)
/**
* To be used with physics simulator
* To be used with physics simulator. This is a magic number.
*/
val TARGET_FPS: Double = 26.0 + (2.0 / 3.0)
val PHYS_TIME_FRAME: Double = 26.0 + (2.0 / 3.0)
// 26.0 + (2.0 / 3.0) // lower value == faster gravity response (IT WON'T HOTSWAP!!)
// protip: using METER, game unit and SI unit will have same number
/**
* To be used with render, to achieve smooth frame drawing
* TARGET_INTERNAL_FPS > TARGET_FPS for smooth frame drawing
*/
val TARGET_INTERNAL_FPS: Double = 60.0
internal val UPDATE_CATCHUP_MAX_TRIES = 10
var previousScreen: Screen? = null // to be used with temporary states like StateMonitorCheck
var ingame: IngameInstance? = null
private val gameConfig = GameConfig()
val OSName = System.getProperty("os.name")
val OSVersion = System.getProperty("os.version")
lateinit var OperationSystem: String // all caps "WINDOWS, "OSX", "LINUX", "SOLARIS", "UNKNOWN"
private set
lateinit var defaultDir: String
private set
lateinit var defaultSaveDir: String
private set
private val javaHeapCircularArray = CircularArray<Int>(128)
private val nativeHeapCircularArray = CircularArray<Int>(128)
private val javaHeapCircularArray = CircularArray<Int>(64)
private val nativeHeapCircularArray = CircularArray<Int>(64)
private val updateRateCircularArray = CircularArray<Double>(16)
val memJavaHeap: Int
get() {
@@ -139,9 +109,14 @@ object Terrarum : Screen {
}
val memXmx: Int
get() = (Runtime.getRuntime().maxMemory() shr 20).toInt()
val updateRateStr: String
get() {
updateRateCircularArray.add(updateRate)
var environment: RunningEnvironment
private set
var acc = 0.0
updateRateCircularArray.forEach { acc = maxOf(acc, it) }
return String.format("%.2f", acc)
}
@@ -190,7 +165,7 @@ object Terrarum : Screen {
val CONTROLLER_DEADZONE = 0.1f
/** Available CPU threads */
val THREADS = Runtime.getRuntime().availableProcessors()
val THREADS = Runtime.getRuntime().availableProcessors() + 1
/**
* If the game is multithreading.
@@ -199,9 +174,7 @@ object Terrarum : Screen {
* THREADS >= 2 and config "multithread" is true
*/
val MULTITHREAD: Boolean
get() = THREADS >= 2 && getConfigBoolean("multithread")
private lateinit var configDir: String
get() = THREADS >= 3 && getConfigBoolean("multithread")
const val NAME = AppLoader.GAME_NAME
@@ -209,6 +182,8 @@ object Terrarum : Screen {
val systemArch = System.getProperty("os.arch")
val processor = GetCpuName.getModelName()
val processorVendor = GetCpuName.getCPUID()
lateinit var renderer: String
lateinit var rendererVendor: String
val is32BitJVM = !System.getProperty("sun.arch.data.model").contains("64")
@@ -220,10 +195,6 @@ object Terrarum : Screen {
lateinit var shaderRGBOnly: ShaderProgram
lateinit var shaderAtoGrey: ShaderProgram
lateinit var textureWhiteSquare: Texture
lateinit var testTexture: Texture
@@ -231,8 +202,6 @@ object Terrarum : Screen {
val fullscreenQuad = AppLoader.fullscreenQuad
val deltaTime: Float; get() = Gdx.graphics.rawDeltaTime
lateinit var assetManager: AssetManager // TODO
@@ -243,16 +212,6 @@ object Terrarum : Screen {
println("LibGDX version ${com.badlogic.gdx.Version.VERSION}")
getDefaultDirectory()
createDirs()
// read config i guess...?
val readFromDisk = readConfigJson()
if (!readFromDisk) readConfigJson() // what's this for?
println("os.arch = $systemArch") // debug info
if (is32BitJVM) {
@@ -278,18 +237,19 @@ object Terrarum : Screen {
}
environment = try {
Controllers.getController(0) // test if controller exists
if (getConfigString("pcgamepadenv") == "console")
RunningEnvironment.CONSOLE
else
// setting environment as MOBILE precedes this code
if (environment != RunningEnvironment.MOBILE) {
environment = try {
Controllers.getController(0) // test if controller exists
if (getConfigString("pcgamepadenv") == "console")
RunningEnvironment.CONSOLE
else
RunningEnvironment.PC
}
catch (e: IndexOutOfBoundsException) {
RunningEnvironment.PC
}
}
catch (e: IndexOutOfBoundsException) {
RunningEnvironment.PC
}
}
@@ -325,9 +285,15 @@ object Terrarum : Screen {
testTexture = Texture(Gdx.files.internal("./assets/test_texture.tga"))
val glInfo = Gdx.graphics.glVersion.debugVersionString
println("GL_VERSION = $GL_VERSION")
println("GL_MAX_TEXTURE_SIZE = $GL_MAX_TEXTURE_SIZE")
println("GL info:\n${Gdx.graphics.glVersion.debugVersionString}") // debug info
println("GL info:\n$glInfo") // debug info
// set up renderer info variables
renderer = Gdx.graphics.glVersion.rendererString
rendererVendor = Gdx.graphics.glVersion.vendorString
if (GL_VERSION < MINIMAL_GL_VERSION || GL_MAX_TEXTURE_SIZE < MINIMAL_GL_MAX_TEXTURE_SIZE) {
@@ -345,27 +311,22 @@ object Terrarum : Screen {
shapeRender = ShapeRenderer()
//fontGame = GameFontBase("assets/graphics/fonts/terrarum-sans-bitmap", flipY = true)
fontSmallNumbers = TinyAlphNum
textureWhiteSquare = Texture(Gdx.files.internal("assets/graphics/ortho_line_tex_2px.tga"))
textureWhiteSquare.setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest)
ShaderProgram.pedantic = false
shaderBlur = ShaderProgram(Gdx.files.internal("assets/blur.vert"), Gdx.files.internal("assets/blur.frag"))
shaderBlur = AppLoader.loadShader("assets/blur.vert", "assets/blur.frag")
if (getConfigBoolean("fxdither")) {
shaderBayer = ShaderProgram(Gdx.files.internal("assets/4096.vert"), Gdx.files.internal("assets/4096_bayer.frag"))
shaderBayer = AppLoader.loadShader("assets/4096.vert", "assets/4096_bayer.frag")
shaderBayer.begin()
shaderBayer.setUniformf("rcount", 64f)
shaderBayer.setUniformf("gcount", 64f)
shaderBayer.setUniformf("bcount", 64f)
shaderBayer.end()
shaderSkyboxFill = ShaderProgram(Gdx.files.internal("assets/4096.vert"), Gdx.files.internal("assets/4096_bayer_skyboxfill.frag"))
shaderSkyboxFill = AppLoader.loadShader("assets/4096.vert", "assets/4096_bayer_skyboxfill.frag")
shaderSkyboxFill.begin()
shaderSkyboxFill.setUniformf("rcount", 64f)
shaderSkyboxFill.setUniformf("gcount", 64f)
@@ -373,15 +334,15 @@ object Terrarum : Screen {
shaderSkyboxFill.end()
}
else {
shaderBayer = ShaderProgram(Gdx.files.internal("assets/4096.vert"), Gdx.files.internal("assets/passthru.frag"))
shaderSkyboxFill = ShaderProgram(Gdx.files.internal("assets/4096.vert"), Gdx.files.internal("assets/skyboxfill.frag"))
shaderBayer = AppLoader.loadShader("assets/4096.vert", "assets/passthru.frag")
shaderSkyboxFill = AppLoader.loadShader("assets/4096.vert", "assets/skyboxfill.frag")
}
shaderBlendGlow = ShaderProgram(Gdx.files.internal("assets/blendGlow.vert"), Gdx.files.internal("assets/blendGlow.frag"))
shaderBlendGlow = AppLoader.loadShader("assets/blendGlow.vert", "assets/blendGlow.frag")
shaderRGBOnly = ShaderProgram(Gdx.files.internal("assets/4096.vert"), Gdx.files.internal("assets/rgbonly.frag"))
shaderAtoGrey = ShaderProgram(Gdx.files.internal("assets/4096.vert"), Gdx.files.internal("assets/aonly.frag"))
shaderRGBOnly = AppLoader.loadShader("assets/4096.vert", "assets/rgbonly.frag")
shaderAtoGrey = AppLoader.loadShader("assets/4096.vert", "assets/aonly.frag")
if (!shaderBlendGlow.isCompiled) {
@@ -419,18 +380,18 @@ object Terrarum : Screen {
// jump right into the ingame
/*ingame = Ingame(batch)
ingame!!.gameLoadInfoPayload = Ingame.NewWorldParameters(2400, 800, HQRNG().nextLong())
ingame!!.gameLoadMode = Ingame.GameLoadMode.CREATE_NEW
LoadScreen.screenToLoad = ingame!!
super.setScreen(LoadScreen)*/
// jump straight into the ingame
/*val ingame = Ingame(batch)
ingame.gameLoadInfoPayload = Ingame.NewWorldParameters(2400, 800, HQRNG().nextLong())
ingame.gameLoadMode = Ingame.GameLoadMode.CREATE_NEW
LoadScreen.screenToLoad = ingame
this.ingame = ingame
setScreen(LoadScreen)*/
// title screen
AppLoader.getINSTANCE().setScreen(TitleScreen(batch))
//appLoader.setScreen(FuckingWorldRenderer(batch))
}
fun setScreen(screen: Screen) {
@@ -438,10 +399,9 @@ object Terrarum : Screen {
}
override fun render(delta: Float) {
Terrarum.debugTimers["GDX.delta"] = delta.times(1000_000_000f).toLong()
AppLoader.getINSTANCE().screen.render(deltaTime)
//GLOBAL_RENDER_TIMER += 1
// moved to AppLoader; global event must be place at the apploader to prevent ACCIDENTAL forgot-to-update type of bug.
AppLoader.debugTimers["GDX.rawDelta"] = Gdx.graphics.rawDeltaTime.times(1000_000_000f).toLong()
AppLoader.debugTimers["GDX.smtDelta"] = AppLoader.getSmoothDelta().times(1000_000_000f).toLong()
AppLoader.getINSTANCE().screen.render(delta)
}
override fun pause() {
@@ -477,206 +437,16 @@ object Terrarum : Screen {
}
override fun resize(width: Int, height: Int) {
//var width = maxOf(width, WIDTH_MIN)
//var height = maxOf(height, HEIGHT_MIN)
var width = width
var height = height
if (width % 2 == 1) width -= 1
if (height % 2 == 1) height -= 1
screenW = width
screenH = height
try {
AppLoader.getINSTANCE().screen.resize(screenW, screenH)
/*try {
AppLoader.getINSTANCE().screen.resize(width, height)
}
catch (e: NullPointerException) { }
// re-calculate fullscreen quad
//updateFullscreenQuad(screenW, screenH)
//appLoader.resize(width, height)
//Gdx.graphics.setWindowedMode(width, height)
catch (e: NullPointerException) { }*/ // I sense circular recursion...
printdbg(this, "newsize: ${Gdx.graphics.width}x${Gdx.graphics.height} | internal: ${width}x$height")
}
private fun getDefaultDirectory() {
val OS = System.getProperty("os.name").toUpperCase()
if (OS.contains("WIN")) {
OperationSystem = "WINDOWS"
defaultDir = System.getenv("APPDATA") + "/Terrarum"
}
else if (OS.contains("OS X")) {
OperationSystem = "OSX"
defaultDir = System.getProperty("user.home") + "/Library/Application Support/Terrarum"
}
else if (OS.contains("NUX") || OS.contains("NIX") || OS.contains("BSD")) {
OperationSystem = "LINUX"
defaultDir = System.getProperty("user.home") + "/.Terrarum"
}
else if (OS.contains("SUNOS")) {
OperationSystem = "SOLARIS"
defaultDir = System.getProperty("user.home") + "/.Terrarum"
}
else if (System.getProperty("java.runtime.name").toUpperCase().contains("ANDROID")) {
OperationSystem = "ANDROID"
defaultDir = System.getProperty("user.home") + "/.Terrarum"
environment = RunningEnvironment.MOBILE
}
else {
OperationSystem = "UNKNOWN"
defaultDir = System.getProperty("user.home") + "/.Terrarum"
}
defaultSaveDir = defaultDir + "/Saves"
configDir = defaultDir + "/config.json"
println("os.name = $OSName (with identifier $OperationSystem)")
println("os.version = $OSVersion")
println("default directory: $defaultDir")
}
private fun createDirs() {
val dirs = arrayOf(File(defaultSaveDir))
dirs.forEach { if (!it.exists()) it.mkdirs() }
}
private fun createConfigJson() {
val configFile = File(configDir)
if (!configFile.exists() || configFile.length() == 0L) {
JsonWriter.writeToFile(DefaultConfig.fetch(), configDir)
}
}
private fun readConfigJson(): Boolean {
try {
// read from disk and build config from it
val jsonObject = JsonFetcher(configDir)
// make config
jsonObject.entrySet().forEach { entry -> gameConfig[entry.key] = entry.value }
return true
}
catch (e: IOException) {
// write default config to game dir. Call this method again to read config from it.
try {
createConfigJson()
}
catch (e1: IOException) {
e.printStackTrace()
}
return false
}
}
/**
* Return config from config set. If the config does not exist, default value will be returned.
* @param key
* *
* @return Config from config set or default config if it does not exist.
* *
* @throws NullPointerException if the specified config simply does not exist.
*/
fun getConfigInt(key: String): Int {
val cfg = getConfigMaster(key)
if (cfg is JsonPrimitive)
return cfg.asInt
else
return cfg as Int
}
/**
* Return config from config set. If the config does not exist, default value will be returned.
* @param key
* *
* @return Config from config set or default config if it does not exist.
* *
* @throws NullPointerException if the specified config simply does not exist.
*/
fun getConfigString(key: String): String {
val cfg = getConfigMaster(key)
if (cfg is JsonPrimitive)
return cfg.asString
else
return cfg as String
}
/**
* Return config from config set. If the config does not exist, default value will be returned.
* @param key
* *
* @return Config from config set or default config if it does not exist.
* *
* @throws NullPointerException if the specified config simply does not exist.
*/
fun getConfigBoolean(key: String): Boolean {
val cfg = getConfigMaster(key)
if (cfg is JsonPrimitive)
return cfg.asBoolean
else
return cfg as Boolean
}
fun getConfigIntArray(key: String): IntArray {
val cfg = getConfigMaster(key)
if (cfg is JsonArray) {
val jsonArray = cfg.asJsonArray
return IntArray(jsonArray.size(), { i -> jsonArray[i].asInt })
}
else
return cfg as IntArray
}
/**
* Get config from config file. If the entry does not exist, get from defaults; if the entry is not in the default, NullPointerException will be thrown
*/
private val defaultConfig = DefaultConfig.fetch()
private fun getConfigMaster(key: String): Any {
val key = key.toLowerCase()
val config = try {
gameConfig[key]
}
catch (e: NullPointerException) {
null
}
val defaults = try {
defaultConfig.get(key)
}
catch (e: NullPointerException) {
null
}
if (config == null) {
if (defaults == null) {
throw NullPointerException("key not found: '$key'")
}
else {
return defaults
}
}
else {
return config
}
}
fun setConfig(key: String, value: Any) {
gameConfig[key] = value
}
val currentSaveDir: File
get() {
val file = File(defaultSaveDir + "/test")
@@ -703,15 +473,9 @@ object Terrarum : Screen {
get() = Gdx.input.x
inline val mouseScreenY: Int
get() = Gdx.input.y
/** Bigger than 1.0 */
/** Delta converted as it it was a FPS */
inline val updateRate: Double
get() = 1.0 / Gdx.graphics.deltaTime
val updateRateStr: String
get() = String.format("%.2f", updateRate)
/** Smaller than 1.0 */
val renderRate = 1.0 / TARGET_INTERNAL_FPS
val renderRateStr = TARGET_INTERNAL_FPS.toString()
get() = 1.0 / AppLoader.getSmoothDelta()
/**
* Usage:
*
@@ -727,6 +491,7 @@ object Terrarum : Screen {
Actor.RenderOrder.MIDDLE -> Actor.RANGE_MIDDLE
Actor.RenderOrder.MIDTOP -> Actor.RANGE_MIDTOP
Actor.RenderOrder.FRONT -> Actor.RANGE_FRONT
Actor.RenderOrder.OVERLAY-> Actor.RANDE_OVERLAY
}
}
catch (gameNotInitialisedException: KotlinNullPointerException) {
@@ -780,9 +545,9 @@ fun Float.round(): Float {
// ShapeRenderer alternative for rects
fun SpriteBatch.fillRect(x: Float, y: Float, w: Float, h: Float) {
this.draw(Terrarum.textureWhiteSquare, x, y, w, h)
this.draw(AppLoader.textureWhiteSquare, x, y, w, h)
}
inline fun SpriteBatch.drawStraightLine(x: Float, y: Float, otherEnd: Float, thickness: Float, isVertical: Boolean) {
fun SpriteBatch.drawStraightLine(x: Float, y: Float, otherEnd: Float, thickness: Float, isVertical: Boolean) {
if (!isVertical)
this.fillRect(x, y, otherEnd - x, thickness)
else
@@ -794,36 +559,70 @@ inline fun SpriteBatch.drawStraightLine(x: Float, y: Float, otherEnd: Float, thi
infix fun Color.mul(other: Color): Color = this.cpy().mul(other)
/*inline fun Color.toRGB10(): RGB10 {
val bits = this.toIntBits() // ABGR
// 0bxxRRRRRRRRRRGGGGGGGGGGBBBBBBBBBB
// 0bAAAAAAAABBBBBBBBGGGGGGGGRRRRRRRR
return bits.and(0x0000FF).shl(20) or bits.and(0x00FF00).shl(2) or bits.and(0xFF0000).ushr(16)
}*/
fun blendMul(batch: SpriteBatch? = null) {
(batch ?: Terrarum.batch).enableBlending()
(batch ?: Terrarum.batch).setBlendFunction(GL20.GL_DST_COLOR, GL20.GL_ONE_MINUS_SRC_ALPHA)
Gdx.gl.glBlendEquation(GL20.GL_FUNC_ADD) // batch.flush does not touch blend equation
fun blendMul(batch: SpriteBatch) {
// will break if the colour image contains semitransparency
batch.enableBlending()
batch.setBlendFunction(GL20.GL_DST_COLOR, GL20.GL_ONE_MINUS_SRC_ALPHA)
}
fun blendNormal(batch: SpriteBatch? = null) {
(batch ?: Terrarum.batch).enableBlending()
(batch ?: Terrarum.batch).setBlendFunction(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA)
Gdx.gl.glBlendEquation(GL20.GL_FUNC_ADD) // batch.flush does not touch blend equation
fun blendScreen(batch: SpriteBatch) {
// will break if the colour image contains semitransparency
batch.enableBlending()
batch.setBlendFunction(GL20.GL_ONE, GL20.GL_ONE_MINUS_SRC_COLOR)
}
fun blendScreen(batch: SpriteBatch? = null) {
(batch ?: Terrarum.batch).enableBlending()
(batch ?: Terrarum.batch).setBlendFunction(GL20.GL_ONE, GL20.GL_ONE_MINUS_SRC_COLOR)
Gdx.gl.glBlendEquation(GL20.GL_FUNC_ADD) // batch.flush does not touch blend equation
fun blendDisable(batch: SpriteBatch) {
batch.disableBlending()
}
fun blendDisable(batch: SpriteBatch? = null) {
(batch ?: Terrarum.batch).disableBlending()
fun blendNormal(batch: SpriteBatch) {
batch.enableBlending()
batch.setBlendFunctionSeparate(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA, GL20.GL_SRC_ALPHA, GL20.GL_ONE)
// ALPHA *MUST BE* PREMULTIPLIED //
// One way to tell:
// 1. Check (RGB) and (A) values.
// 2. If there exist a pixel such that max(R,G,B) > (A), then the image is NOT premultiplied.
// Easy way:
// Base game (mods/basegame/blocks/terrain.tga.gz) has impure window glass. When looking at the RGB channel only:
// premultipied if the glass looks very dark.
// not premultipied if the glass looks VERY GREEN.
// helpful links:
// - https://gamedev.stackexchange.com/questions/82741/normal-blend-mode-with-opengl-trouble
// - https://www.andersriggelsen.dk/glblendfunc.php
}
fun gdxClearAndSetBlend(r: Float, g: Float, b: Float, a: Float) {
Gdx.gl.glClearColor(r,g,b,a)
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)
gdxSetBlend()
}
fun gdxSetBlend() {
Gdx.gl.glEnable(GL20.GL_TEXTURE_2D)
Gdx.gl.glEnable(GL20.GL_BLEND)
}
fun gdxSetBlendNormal() {
gdxSetBlend()
Gdx.gl.glBlendFuncSeparate(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA, GL20.GL_SRC_ALPHA, GL20.GL_ONE)
//Gdx.gl.glBlendEquationSeparate(GL20.GL_FUNC_ADD, GL30.GL_MAX) // batch.flush does not touch blend equation
// ALPHA *MUST BE* PREMULTIPLIED //
// One way to tell:
// 1. Check (RGB) and (A) values.
// 2. If there exist a pixel such that max(R,G,B) > (A), then the image is NOT premultiplied.
// Easy way:
// Base game (mods/basegame/blocks/terrain.tga.gz) has impure window glass. When looking at the RGB channel only:
// premultipied if the glass looks very dark.
// not premultipied if the glass looks VERY GREEN.
// helpful links:
// - https://gamedev.stackexchange.com/questions/82741/normal-blend-mode-with-opengl-trouble
// - https://www.andersriggelsen.dk/glblendfunc.php
}
object BlendMode {
@@ -832,11 +631,11 @@ object BlendMode {
const val NORMAL = "normal"
//const val MAX = "GL_MAX" // not supported by GLES -- use shader
fun resolve(mode: String) {
fun resolve(mode: String, batch: SpriteBatch) {
when (mode) {
SCREEN -> blendScreen()
MULTIPLY -> blendMul()
NORMAL -> blendNormal()
SCREEN -> blendScreen(batch)
MULTIPLY -> blendMul(batch)
NORMAL -> blendNormal(batch)
//MAX -> blendLightenOnly() // not supported by GLES -- use shader
else -> throw Error("Unknown blend mode: $mode")
}
@@ -890,23 +689,23 @@ val ccK = GameFontBase.toColorCode(0x888F)
typealias Second = Float
inline fun Int.sqr(): Int = this * this
inline fun Double.floorInt() = Math.floor(this).toInt()
inline fun Float.floorInt() = FastMath.floor(this)
inline fun Float.floor() = FastMath.floor(this).toFloat()
inline fun Double.ceilInt() = Math.ceil(this).toInt()
inline fun Float.ceil(): Float = FastMath.ceil(this).toFloat()
inline fun Float.ceilInt() = FastMath.ceil(this)
inline fun Double.round() = Math.round(this).toDouble()
inline fun Double.floor() = Math.floor(this)
inline fun Double.ceil() = this.floor() + 1.0
inline fun Double.roundInt(): Int = Math.round(this).toInt()
inline fun Float.roundInt(): Int = Math.round(this)
inline fun Double.abs() = Math.abs(this)
inline fun Double.sqr() = this * this
inline fun Double.sqrt() = Math.sqrt(this)
inline fun Float.sqrt() = FastMath.sqrt(this)
inline fun Int.abs() = if (this < 0) -this else this
fun Int.sqr(): Int = this * this
fun Double.floorInt() = Math.floor(this).toInt()
fun Float.floorInt() = FastMath.floor(this)
fun Float.floor() = FastMath.floor(this).toFloat()
fun Double.ceilInt() = Math.ceil(this).toInt()
fun Float.ceil(): Float = FastMath.ceil(this).toFloat()
fun Float.ceilInt() = FastMath.ceil(this)
fun Double.round() = Math.round(this).toDouble()
fun Double.floor() = Math.floor(this)
fun Double.ceil() = this.floor() + 1.0
fun Double.roundInt(): Int = Math.round(this).toInt()
fun Float.roundInt(): Int = Math.round(this)
fun Double.abs() = Math.abs(this)
fun Double.sqr() = this * this
fun Double.sqrt() = Math.sqrt(this)
fun Float.sqrt() = FastMath.sqrt(this)
fun Int.abs() = this.absoluteValue
fun Double.bipolarClamp(limit: Double) =
this.coerceIn(-limit, limit)
@@ -938,4 +737,19 @@ fun interpolateLinear(scale: Double, startValue: Double, endValue: Double): Doub
return endValue
}
return (1.0 - scale) * startValue + scale * endValue
}
}
fun <T> List<T>.linearSearch(selector: (T) -> Boolean): Int? {
this.forEachIndexed { index, it ->
if (selector.invoke(it)) return index
}
return null
}
fun <T> List<T>.linearSearchBy(selector: (T) -> Boolean): T? {
this.forEach {
if (selector.invoke(it)) return it
}
return null
}

View File

@@ -3,7 +3,10 @@ package net.torvald.terrarum
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.InputAdapter
import com.badlogic.gdx.Screen
import com.badlogic.gdx.graphics.*
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.OrthographicCamera
import com.badlogic.gdx.graphics.Pixmap
import com.badlogic.gdx.graphics.Texture
import com.badlogic.gdx.graphics.g2d.SpriteBatch
import com.badlogic.gdx.graphics.g2d.TextureRegion
import com.badlogic.gdx.graphics.glutils.FrameBuffer
@@ -18,14 +21,16 @@ import net.torvald.terrarum.gameworld.fmod
import net.torvald.terrarum.langpack.Lang
import net.torvald.terrarum.modulebasegame.Ingame
import net.torvald.terrarum.modulebasegame.IngameRenderer
import net.torvald.terrarum.modulebasegame.gameactors.*
import net.torvald.terrarum.modulebasegame.gameactors.HumanoidNPC
import net.torvald.terrarum.modulebasegame.gameworld.GameWorldExtension
import net.torvald.terrarum.modulebasegame.ui.UIRemoCon
import net.torvald.terrarum.serialise.ReadLayerData
import net.torvald.terrarum.ui.UICanvas
import net.torvald.terrarum.modulebasegame.ui.UITitleRemoConYaml
import net.torvald.terrarum.modulebasegame.weather.WeatherMixer
import net.torvald.terrarum.worlddrawer.*
import net.torvald.terrarum.serialise.ReadLayerData
import net.torvald.terrarum.ui.UICanvas
import net.torvald.terrarum.worlddrawer.FeaturesDrawer
import net.torvald.terrarum.worlddrawer.LightmapRenderer
import net.torvald.terrarum.worlddrawer.WorldCamera
import java.io.FileInputStream
/**
@@ -49,7 +54,7 @@ class TitleScreen(val batch: SpriteBatch) : Screen {
}
private var loadDone = false
//private var loadDone = false // not required; draw-while-loading is implemented in the AppLoader
private lateinit var demoWorld: GameWorldExtension
private lateinit var cameraNodes: FloatArray // camera Y-pos
@@ -128,14 +133,14 @@ class TitleScreen(val batch: SpriteBatch) : Screen {
// construct camera nodes
val nodeCount = 100
cameraNodes = kotlin.FloatArray(nodeCount, { it ->
cameraNodes = kotlin.FloatArray(nodeCount) { it ->
val tileXPos = (demoWorld.width.toFloat() * it / nodeCount).floorInt()
var travelDownCounter = 0
while (!BlockCodex[demoWorld.getTileFromTerrain(tileXPos, travelDownCounter)].isSolid) {
travelDownCounter += 4
}
travelDownCounter * FeaturesDrawer.TILE_SIZE.toFloat()
})
}
cameraPlayer = object : HumanoidNPC(cameraAI, born = 0, usePhysics = false, forceAssignRefID = Terrarum.PLAYER_REF_ID) {
@@ -164,7 +169,7 @@ class TitleScreen(val batch: SpriteBatch) : Screen {
uiContainer.add(uiMenu)
loadDone = true
//loadDone = true
}
@@ -172,7 +177,7 @@ class TitleScreen(val batch: SpriteBatch) : Screen {
}
override fun show() {
printdbg(this, "atrniartsientsarinoetsar")
printdbg(this, "show() called")
initViewPort(Terrarum.WIDTH, Terrarum.HEIGHT)
@@ -184,40 +189,26 @@ class TitleScreen(val batch: SpriteBatch) : Screen {
worldFBO = FrameBuffer(Pixmap.Format.RGBA8888, Terrarum.WIDTH, Terrarum.HEIGHT, false)
loadThingsWhileIntroIsVisible()
printdbg(this, "show() exit")
}
private val introUncoverTime: Second = 0.3f
private var introUncoverDeltaCounter = 0f
private var updateDeltaCounter = 0.0
protected val renderRate = Terrarum.renderRate
override fun render(delta: Float) {
if (!loadDone) {
loadThingsWhileIntroIsVisible()
}
else {
// async update
updateDeltaCounter += delta
var updateTries = 0
while (updateDeltaCounter >= renderRate) {
updateScreen(delta)
updateDeltaCounter -= renderRate
updateTries++
// TODO async update
if (updateTries >= Terrarum.UPDATE_CATCHUP_MAX_TRIES) {
break
}
}
// render? just do it anyway
renderScreen()
}
updateScreen(delta)
// render? just do it anyway
renderScreen()
}
fun updateScreen(delta: Float) {
//Gdx.graphics.setTitle(Ingame.getCanonicalTitle())
demoWorld.globalLight = WeatherMixer.globalLightNow
demoWorld.updateWorldTime(delta)
WeatherMixer.update(delta, cameraPlayer, demoWorld)
@@ -236,12 +227,13 @@ class TitleScreen(val batch: SpriteBatch) : Screen {
}
fun renderScreen() {
Gdx.graphics.setTitle(Ingame.getCanonicalTitle())
//camera.setToOrtho(true, Terrarum.WIDTH.toFloat(), Terrarum.HEIGHT.toFloat())
// render world
Gdx.gl.glClearColor(.64f, .754f, .84f, 1f)
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)
gdxClearAndSetBlend(.64f, .754f, .84f, 1f)
IngameRenderer.invoke(world = demoWorld, uisToDraw = uiContainer)
@@ -257,7 +249,7 @@ class TitleScreen(val batch: SpriteBatch) : Screen {
private fun renderOverlayTexts() {
setCameraPosition(0f, 0f)
blendNormal()
blendNormal(batch)
batch.shader = null
batch.color = Color.LIGHT_GRAY
@@ -289,22 +281,24 @@ class TitleScreen(val batch: SpriteBatch) : Screen {
}
override fun resize(width: Int, height: Int) {
printdbg(this, "resize() called")
// Set up viewport when window is resized
initViewPort(Terrarum.WIDTH, Terrarum.HEIGHT)
BlocksDrawer.resize(Terrarum.WIDTH, Terrarum.HEIGHT)
LightmapRenderer.resize(Terrarum.WIDTH, Terrarum.HEIGHT)
if (loadDone) {
// resize UI by re-creating it (!!)
uiMenu.resize(Terrarum.WIDTH, Terrarum.HEIGHT)
//uiMenu.setPosition(0, UITitleRemoConRoot.menubarOffY)
uiMenu.setPosition(0, 0) // shitty hack. Could be:
// 1: Init code and resize code are different
// 2: The UI is coded shit
}
// resize UI by re-creating it (!!)
uiMenu.resize(Terrarum.WIDTH, Terrarum.HEIGHT)
// TODO I forgot what the fuck kind of hack I was talking about
//uiMenu.setPosition(0, UITitleRemoConRoot.menubarOffY)
uiMenu.setPosition(0, 0) // shitty hack. Could be:
// 1: Init code and resize code are different
// 2: The UI is coded shit
IngameRenderer.resize(Terrarum.WIDTH, Terrarum.HEIGHT)
printdbg(this, "resize() exit")
}
override fun dispose() {

View File

@@ -10,7 +10,7 @@ import net.torvald.terrarum.itemproperties.GameItem
import net.torvald.terrarum.modulebasegame.Ingame
import net.torvald.terrarum.modulebasegame.ui.UIInventoryFull
import net.torvald.terrarum.modulebasegame.ui.UIItemInventoryCellBase
import net.torvald.terrarum.ui.*
import net.torvald.terrarum.ui.UIItemTextButton
/***
* Note that the UI will not render if either item or itemImage is null.
@@ -74,12 +74,12 @@ class UIItemInventoryElem(
if (item != null || drawBackOnNull) {
// do not highlight even if drawBackOnNull is true
if (mouseUp && item != null) {
BlendMode.resolve(mouseoverBackBlendMode)
BlendMode.resolve(mouseoverBackBlendMode, batch)
batch.color = mouseoverBackCol
}
// if drawBackOnNull, just draw background
else {
BlendMode.resolve(backBlendMode)
BlendMode.resolve(backBlendMode, batch)
batch.color = backCol
}
batch.fillRect(posX.toFloat(), posY.toFloat(), width.toFloat(), height.toFloat())
@@ -87,7 +87,7 @@ class UIItemInventoryElem(
if (item != null && itemImage != null) {
blendNormal()
blendNormal(batch)
// item image
batch.color = Color.WHITE
@@ -136,14 +136,14 @@ class UIItemInventoryElem(
}
override fun keyDown(keycode: Int): Boolean {
if (item != null && Terrarum.ingame != null && keycode in Input.Keys.NUM_1..Input.Keys.NUM_0) {
if (item != null && Terrarum.ingame != null && keycode in Input.Keys.NUM_0..Input.Keys.NUM_9) {
val player = (Terrarum.ingame!! as Ingame).actorNowPlaying
if (player == null) return false
val inventory = player.inventory
val slot = if (keycode == Input.Keys.NUM_0) 9 else keycode - Input.Keys.NUM_1
val currentSlotItem = inventory?.getQuickBar(slot)
val currentSlotItem = inventory?.getQuickslot(slot)
inventory.setQuickBar(
@@ -157,13 +157,13 @@ class UIItemInventoryElem(
// search for duplicates in the quickbar, except mine
// if there is, unregister the other
(0..9).minus(slot).forEach {
if (inventory.getQuickBar(it)?.item == item) {
if (inventory.getQuickslot(it)?.item == item) {
inventory.setQuickBar(it, null)
}
}
}
return true
return super.keyDown(keycode)
}
override fun touchDown(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
@@ -171,6 +171,10 @@ class UIItemInventoryElem(
// equip da shit
val itemEquipSlot = item!!.equipPosition
if (itemEquipSlot == GameItem.EquipPosition.NULL) {
TODO("Equip position is NULL, does this mean it's single-consume items like a potion?")
}
val player = (Terrarum.ingame!! as Ingame).actorNowPlaying
if (player == null) return false
@@ -185,7 +189,7 @@ class UIItemInventoryElem(
inventoryUI.rebuildList()
return true
return super.touchDown(screenX, screenY, pointer, button)
}

View File

@@ -9,7 +9,7 @@ import net.torvald.terrarum.itemproperties.GameItem
import net.torvald.terrarum.modulebasegame.Ingame
import net.torvald.terrarum.modulebasegame.ui.UIInventoryFull
import net.torvald.terrarum.modulebasegame.ui.UIItemInventoryCellBase
import net.torvald.terrarum.ui.*
import net.torvald.terrarum.ui.UIItemTextButton
/**
* Created by minjaesong on 2017-10-20.
@@ -56,12 +56,12 @@ class UIItemInventoryElemSimple(
if (item != null || drawBackOnNull) {
// do not highlight even if drawBackOnNull is true
if (mouseUp && item != null || equippedSlot != null) { // "equippedSlot != null": also highlight back if equipped
BlendMode.resolve(mouseoverBackBlendMode)
BlendMode.resolve(mouseoverBackBlendMode, batch)
batch.color = mouseoverBackCol
}
// if drawBackOnNull, just draw background
else {
BlendMode.resolve(backBlendMode)
BlendMode.resolve(backBlendMode, batch)
batch.color = backCol
}
batch.fillRect(posX.toFloat(), posY.toFloat(), width.toFloat(), height.toFloat())
@@ -72,7 +72,7 @@ class UIItemInventoryElemSimple(
// and you can clearly see the quickslot UI anyway
if (item != null && itemImage != null) {
blendNormal()
blendNormal(batch)
// item image
batch.color = Color.WHITE
@@ -121,15 +121,14 @@ class UIItemInventoryElemSimple(
}
override fun keyDown(keycode: Int): Boolean {
if (item != null && Terrarum.ingame != null && keycode in Input.Keys.NUM_1..Input.Keys.NUM_0) {
println("keydown elemgrid")
if (item != null && Terrarum.ingame != null && keycode in Input.Keys.NUM_0..Input.Keys.NUM_9) {
val player = (Terrarum.ingame!! as Ingame).actorNowPlaying
if (player == null) return false
val inventory = player.inventory
val slot = if (keycode == Input.Keys.NUM_0) 9 else keycode - Input.Keys.NUM_1
val currentSlotItem = inventory.getQuickBar(slot)
val currentSlotItem = inventory.getQuickslot(slot)
inventory.setQuickBar(
@@ -143,13 +142,13 @@ class UIItemInventoryElemSimple(
// search for duplicates in the quickbar, except mine
// if there is, unregister the other
(0..9).minus(slot).forEach {
if (inventory.getQuickBar(it)?.item == item) {
if (inventory.getQuickslot(it)?.item == item) {
inventory.setQuickBar(it, null)
}
}
}
return true
return super.keyDown(keycode)
}
override fun touchDown(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
@@ -172,7 +171,7 @@ class UIItemInventoryElemSimple(
inventoryUI.rebuildList()
return true
return super.touchDown(screenX, screenY, pointer, button)
}

View File

@@ -0,0 +1,197 @@
package net.torvald.terrarum
import java.util.*
/**
* Simplified version of YAML, only for the representation of a text tree.
*
* Example code:
* ```
* - File
* - New : Ctrl-N
* - Open : Ctrl-O
* - Open Recent
* - yaml_example.yaml
* - Yaml.kt
* - Close : Ctrl-W
* - Settings
* - Line Separators
* - CRLF
* - CR
* - LF
* - Edit
* - Undo : Ctrl-Z
* - Redo : Shift-Ctrl-Z
* - Cut : Ctrl-X
* - Copy : Ctrl-C
* - Paste : Ctrl-V
* - Find
* - Find : Ctrl-F
* - Replace : Shift-Ctrl-F
* - Convert Indents
* - To Spaces
* - Set Project Indentation
* - To Tabs
* - Refactor
* - Refactor This
* - Rename : Shift-Ctrl-R
* - Extract
* - Variable
* - Property
* - Function
* ```
*
* - All lines are indented with one space
* - All entries are preceded by '- ' (dash and a space)
* - All propery are separated by ' : ' (space colon space)
* - A line that does not start with '- ' are simply ignored, so you can freely make empty lines and/or comments.
*
* Any deviation to the above rule will cause a parse failure, because it's simple and dumb as that.
*
* Created by minjaesong on 2018-12-08.
*/
inline class Yaml(val text: String) {
companion object {
val SEPARATOR = Regex(" : ")
}
fun parse(): QNDTreeNode<String> {
var currentIndentLevel = -1
val root = QNDTreeNode<String>()
var currentNode = root
val nodesStack = Stack<QNDTreeNode<String>>()
val validLineStartRe = Regex(""" *\- """)
nodesStack.push(currentNode)
text.split('\n') .forEach {
if (validLineStartRe.containsMatchIn(it)) { // take partial match; do the task if the text's line is valid
val indentLevel = it.countSpaces()
val it = it.trimIndent()
if (it.startsWith("- ")) { // just double check if indent-trimmed line looks valid
val nodeName = it.drop(2)
if (indentLevel == currentIndentLevel) {
val sibling = QNDTreeNode(nodeName, currentNode.parent)
currentNode.parent!!.children.add(sibling)
currentNode = sibling
}
else if (indentLevel > currentIndentLevel) {
val childNode = QNDTreeNode(nodeName, currentNode)
currentNode.children.add(childNode)
nodesStack.push(currentNode)
currentNode = childNode
currentIndentLevel = indentLevel
}
else {
repeat(currentIndentLevel - indentLevel) { currentNode = nodesStack.pop() }
currentIndentLevel = indentLevel
val sibling = QNDTreeNode(nodeName, currentNode.parent)
currentNode.parent!!.children.add(sibling)
currentNode = sibling
}
}
}
}
// test traverse resulting tree
/*root.traversePreorder { node, depth ->
repeat(depth + 1) { print("-") }
println("${node.data} -> ${node.parent}")
}*/
return root
}
fun parseAsYamlInvokable(): QNDTreeNode<Pair<String, YamlInvokable?>> {
var currentIndentLevel = -1
val root = QNDTreeNode<Pair<String, YamlInvokable?>>()
var currentNode = root
val nodesStack = Stack<QNDTreeNode<Pair<String, YamlInvokable?>>>()
val validLineStartRe = Regex(""" *\- """)
nodesStack.push(currentNode)
text.split('\n') .forEach {
if (validLineStartRe.containsMatchIn(it)) { // take partial match; do the task if the text's line is valid
val indentLevel = it.countSpaces()
val it = it.trimIndent()
if (it.startsWith("- ")) { // just double check if indent-trimmed line looks valid
val nodeString = it.drop(2)
val nodeNameAndInvocation = nodeString.split(SEPARATOR)
val nodeName = nodeNameAndInvocation[0]
val nodeInvocation = loadClass(nodeNameAndInvocation[1])
val nameInvokePair = nodeName to nodeInvocation
if (indentLevel == currentIndentLevel) {
val sibling = QNDTreeNode(nameInvokePair, currentNode.parent)
currentNode.parent!!.children.add(sibling)
currentNode = sibling
}
else if (indentLevel > currentIndentLevel) {
val childNode = QNDTreeNode(nameInvokePair, currentNode)
currentNode.children.add(childNode)
nodesStack.push(currentNode)
currentNode = childNode
currentIndentLevel = indentLevel
}
else {
repeat(currentIndentLevel - indentLevel) { currentNode = nodesStack.pop() }
currentIndentLevel = indentLevel
val sibling = QNDTreeNode(nameInvokePair, currentNode.parent)
currentNode.parent!!.children.add(sibling)
currentNode = sibling
}
}
}
}
// test traverse resulting tree
/*root.traversePreorder { node, depth ->
repeat(depth + 1) { print("-") }
println("${node.data} -> ${node.parent}")
}*/
return root
}
private fun String.countSpaces(): Int {
var c = 0
while (c <= this.length) {
if (this[c] == ' ')
c++
else
break
}
return c
}
private fun loadClass(name: String): YamlInvokable {
val newClass = Class.forName(name)
val newClassConstructor = newClass.getConstructor(/* no args defined */)
val newClassInstance = newClassConstructor.newInstance(/* no args defined */)
return newClassInstance as YamlInvokable
}
}
/**
* A simple interface that meant to be attached with Yaml tree, so that the entry can be ```invoke()```d.
*
* Example usage in Yaml:
* ```
* - File
* - Import : net.torvald.terrarum.whatever.package.ImportFile
* ```
*
*/
interface YamlInvokable {
operator fun invoke()
}

View File

@@ -5,149 +5,126 @@ package net.torvald.terrarum.blockproperties
*/
object Block {
val AIR = 0 // hard coded; this is the standard
const val AIR = 0 // hard coded; this is the standard
val STONE = 16
val STONE_QUARRIED = 17
val STONE_TILE_WHITE = 18
val STONE_BRICKS = 19
const val STONE = 16
const val STONE_QUARRIED = 17
const val STONE_TILE_WHITE = 18
const val STONE_BRICKS = 19
val DIRT = 32
val GRASS = 33
val GRASSWALL = 34
const val DIRT = 32
const val GRASS = 33
const val GRASSWALL = 34
val PLANK_NORMAL = 48
val PLANK_EBONY = 49
val PLANK_BIRCH = 50
val PLANK_BLOODROSE = 51
const val PLANK_NORMAL = 48
const val PLANK_EBONY = 49
const val PLANK_BIRCH = 50
const val PLANK_BLOODROSE = 51
val TRUNK_NORMAL = 64
val TRUNK_EBONY = 65
val TRUNK_BIRCH = 66
val TRUNK_BLOODROSE = 67
const val TRUNK_NORMAL = 64
const val TRUNK_EBONY = 65
const val TRUNK_BIRCH = 66
const val TRUNK_BLOODROSE = 67
val SAND = 80
val SAND_WHITE = 81
val SAND_RED = 82
val SAND_DESERT = 83
val SAND_BLACK = 84
val SAND_GREEN = 85
const val SAND = 80
const val SAND_WHITE = 81
const val SAND_RED = 82
const val SAND_DESERT = 83
const val SAND_BLACK = 84
const val SAND_GREEN = 85
val GRAVEL = 96
val GRAVEL_GREY = 97
const val GRAVEL = 96
const val GRAVEL_GREY = 97
val ORE_COPPER = 112
val ORE_IRON = 113
val ORE_GOLD = 114
val ORE_SILVER = 115
val ORE_ILMENITE = 116
val ORE_AURICHALCUM = 117
const val ORE_COPPER = 112
const val ORE_IRON = 113
const val ORE_GOLD = 114
const val ORE_SILVER = 115
const val ORE_ILMENITE = 116
const val ORE_AURICHALCUM = 117
val RAW_RUBY = 128
val RAW_EMERALD = 129
val RAW_SAPPHIRE = 130
val RAW_TOPAZ = 131
val RAW_DIAMOND = 132
val RAW_AMETHYST = 133
const val RAW_RUBY = 128
const val RAW_EMERALD = 129
const val RAW_SAPPHIRE = 130
const val RAW_TOPAZ = 131
const val RAW_DIAMOND = 132
const val RAW_AMETHYST = 133
val SNOW = 144
val ICE_FRAGILE = 145
val ICE_NATURAL = 146
val ICE_MAGICAL = 147
const val SNOW = 144
const val ICE_FRAGILE = 145
const val ICE_NATURAL = 146
const val ICE_MAGICAL = 147
val GLASS_CRUDE = 148
val GLASS_CLEAN = 149
const val GLASS_CRUDE = 148
const val GLASS_CLEAN = 149
val PLATFORM_STONE = 160
val PLATFORM_WOODEN = 161
val PLATFORM_EBONY = 162
val PLATFORM_BIRCH = 163
val PLATFORM_BLOODROSE = 164
const val PLATFORM_STONE = 160
const val PLATFORM_WOODEN = 161
const val PLATFORM_EBONY = 162
const val PLATFORM_BIRCH = 163
const val PLATFORM_BLOODROSE = 164
val TORCH = 176
val TORCH_FROST = 177
const val TORCH = 176
const val TORCH_FROST = 177
val TORCH_OFF = 192
val TORCH_FROST_OFF = 193
const val TORCH_OFF = 192
const val TORCH_FROST_OFF = 193
val ILLUMINATOR_WHITE = 208
val ILLUMINATOR_YELLOW = 209
val ILLUMINATOR_ORANGE = 210
val ILLUMINATOR_RED = 211
val ILLUMINATOR_FUCHSIA = 212
val ILLUMINATOR_PURPLE = 213
val ILLUMINATOR_BLUE = 214
val ILLUMINATOR_CYAN = 215
val ILLUMINATOR_GREEN = 216
val ILLUMINATOR_GREEN_DARK = 217
val ILLUMINATOR_BROWN = 218
val ILLUMINATOR_TAN = 219
val ILLUMINATOR_GREY_LIGHT = 220
val ILLUMINATOR_GREY_MED = 221
val ILLUMINATOR_GREY_DARK = 222
val ILLUMINATOR_BLACK = 223
const val ILLUMINATOR_WHITE = 208
const val ILLUMINATOR_YELLOW = 209
const val ILLUMINATOR_ORANGE = 210
const val ILLUMINATOR_RED = 211
const val ILLUMINATOR_FUCHSIA = 212
const val ILLUMINATOR_PURPLE = 213
const val ILLUMINATOR_BLUE = 214
const val ILLUMINATOR_CYAN = 215
const val ILLUMINATOR_GREEN = 216
const val ILLUMINATOR_GREEN_DARK = 217
const val ILLUMINATOR_BROWN = 218
const val ILLUMINATOR_TAN = 219
const val ILLUMINATOR_GREY_LIGHT = 220
const val ILLUMINATOR_GREY_MED = 221
const val ILLUMINATOR_GREY_DARK = 222
const val ILLUMINATOR_BLACK = 223
val ILLUMINATOR_WHITE_OFF = 224
val ILLUMINATOR_YELLOW_OFF = 225
val ILLUMINATOR_ORANGE_OFF = 226
val ILLUMINATOR_RED_OFF = 227
val ILLUMINATOR_FUCHSIA_OFF = 228
val ILLUMINATOR_PURPLE_OFF = 229
val ILLUMINATOR_BLUE_OFF = 230
val ILLUMINATOR_CYAN_OFF = 231
val ILLUMINATOR_GREEN_OFF = 232
val ILLUMINATOR_GREEN_DARK_OFF = 233
val ILLUMINATOR_BROWN_OFF = 234
val ILLUMINATOR_TAN_OFF = 235
val ILLUMINATOR_GREY_LIGHT_OFF = 236
val ILLUMINATOR_GREY_MED_OFF = 237
val ILLUMINATOR_GREY_DARK_OFF = 238
val ILLUMINATOR_BLACK_OFF = 239
const val ILLUMINATOR_WHITE_OFF = 224
const val ILLUMINATOR_YELLOW_OFF = 225
const val ILLUMINATOR_ORANGE_OFF = 226
const val ILLUMINATOR_RED_OFF = 227
const val ILLUMINATOR_FUCHSIA_OFF = 228
const val ILLUMINATOR_PURPLE_OFF = 229
const val ILLUMINATOR_BLUE_OFF = 230
const val ILLUMINATOR_CYAN_OFF = 231
const val ILLUMINATOR_GREEN_OFF = 232
const val ILLUMINATOR_GREEN_DARK_OFF = 233
const val ILLUMINATOR_BROWN_OFF = 234
const val ILLUMINATOR_TAN_OFF = 235
const val ILLUMINATOR_GREY_LIGHT_OFF = 236
const val ILLUMINATOR_GREY_MED_OFF = 237
const val ILLUMINATOR_GREY_DARK_OFF = 238
const val ILLUMINATOR_BLACK_OFF = 239
val SANDSTONE = 240
val SANDSTONE_WHITE = 241
val SANDSTONE_RED = 242
val SANDSTONE_DESERT = 243
val SANDSTONE_BLACK = 244
val SANDSTONE_GREEN = 245
const val SANDSTONE = 240
const val SANDSTONE_WHITE = 241
const val SANDSTONE_RED = 242
const val SANDSTONE_DESERT = 243
const val SANDSTONE_BLACK = 244
const val SANDSTONE_GREEN = 245
val LANTERN = 256
val SUNSTONE = 257
val DAYLIGHT_CAPACITOR = 258
const val LANTERN = 256
const val SUNSTONE = 257
const val DAYLIGHT_CAPACITOR = 258
val WATER_1 = 4080
val WATER_2 = 4081
val WATER_3 = 4082
val WATER_4 = 4083
val WATER_5 = 4084
val WATER_6 = 4085
val WATER_7 = 4086
val WATER_8 = 4087
val WATER_9 = 4088
val WATER_10 = 4089
val WATER_11 = 4090
val WATER_12 = 4091
val WATER_13 = 4092
val WATER_14 = 4093
val WATER_15 = 4094
val WATER = 4095
val LAVA_1 = 4064
val LAVA_2 = 4065
val LAVA_3 = 4066
val LAVA_4 = 4067
val LAVA_5 = 4068
val LAVA_6 = 4069
val LAVA_7 = 4070
val LAVA_8 = 4071
val LAVA_9 = 4072
val LAVA_10 = 4073
val LAVA_11 = 4074
val LAVA_12 = 4075
val LAVA_13 = 4076
val LAVA_14 = 4077
val LAVA_15 = 4078
val LAVA = 4079
const val ACTORBLOCK_NO_COLLISION = 4191
const val ACTORBLOCK_FULL_COLLISION = 4092
const val ACTORBLOCK_ALLOW_MOVE_DOWN = 4093
const val ACTORBLOCK_NO_PASS_RIGHT = 4094
const val ACTORBLOCK_NO_PASS_LEFT = 4095
val NULL = -1
const val LAVA = 4094
const val WATER = 4095
const val NULL = -1
}

View File

@@ -1,12 +1,11 @@
package net.torvald.terrarum.blockproperties
import net.torvald.terrarum.AppLoader
import net.torvald.terrarum.utils.CSVFetcher
import net.torvald.terrarum.gameworld.MapLayer
import net.torvald.terrarum.gameworld.PairedMapLayer
import net.torvald.terrarum.utils.CSVFetcher
import net.torvald.terrarum.worlddrawer.LightmapRenderer
import org.apache.commons.csv.CSVRecord
import java.io.IOException
/**
@@ -97,7 +96,7 @@ object BlockCodex {
prop.shadeColB = floatVal(record, "shdb") / LightmapRenderer.MUL_FLOAT
prop.shadeColA = floatVal(record, "shduv") / LightmapRenderer.MUL_FLOAT
prop.strength = intVal(record, "strength")
prop.strength = intVal(record, "str")
prop.density = intVal(record, "dsty")
prop.lumColR = floatVal(record, "lumr") / LightmapRenderer.MUL_FLOAT
@@ -105,12 +104,13 @@ object BlockCodex {
prop.lumColB = floatVal(record, "lumb") / LightmapRenderer.MUL_FLOAT
prop.lumColA = floatVal(record, "lumuv") / LightmapRenderer.MUL_FLOAT
prop.friction = intVal(record, "friction")
prop.friction = intVal(record, "fr")
prop.viscosity = intVal(record, "vscs")
prop.isFluid = boolVal(record, "fluid")
//prop.isFluid = boolVal(record, "fluid")
prop.isSolid = boolVal(record, "solid")
prop.isClear = boolVal(record, "clear")
//prop.isClear = boolVal(record, "clear")
prop.isPlatform = boolVal(record, "plat")
prop.isWallable = boolVal(record, "wall")
prop.isFallable = boolVal(record, "fall")
prop.isVertFriction = boolVal(record, "fv")

View File

@@ -27,9 +27,9 @@ class BlockProp {
var density: Int = 0
var viscosity: Int = 0
var isFluid: Boolean = false
var isSolid: Boolean = false
var isClear: Boolean = false
//var isClear: Boolean = false
var isPlatform: Boolean = false
var isWallable: Boolean = false
var isVertFriction: Boolean = false

View File

@@ -4,11 +4,12 @@ import com.badlogic.gdx.Gdx
import com.badlogic.gdx.graphics.Color
import com.jme3.math.FastMath
import net.torvald.random.HQRNG
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.AppLoader
import net.torvald.terrarum.Second
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.modulebasegame.gameworld.WorldTime
import net.torvald.terrarum.worlddrawer.LightmapRenderer
import net.torvald.terrarum.modulebasegame.weather.WeatherMixer
import net.torvald.terrarum.worlddrawer.LightmapRenderer
/**
* Created by minjaesong on 2016-06-16.
@@ -63,9 +64,9 @@ object BlockPropUtil {
internal fun dynamicLumFuncTickClock() {
// FPS-time compensation
if (Gdx.graphics.framesPerSecond > 0) {
flickerFuncX += Terrarum.deltaTime * 1000f
breathFuncX += Terrarum.deltaTime * 1000f
pulsateFuncX += Terrarum.deltaTime * 1000f
flickerFuncX += AppLoader.getSmoothDelta().toFloat() * 1000f
breathFuncX += AppLoader.getSmoothDelta().toFloat() * 1000f
pulsateFuncX += AppLoader.getSmoothDelta().toFloat() * 1000f
}
// flicker-related vars

View File

@@ -0,0 +1,20 @@
package net.torvald.terrarum.blockproperties
import net.torvald.terrarum.gameworld.FluidType
/**
* Created by minjaesong on 2016-08-06.
*/
object Fluid {
val NULL = FluidType(0)
val WATER = FluidType(1)
val STATIC_WATER = FluidType(-1)
val LAVA = FluidType(2)
val STATIC_LAVA = FluidType(-2)
val fluidRange = 1..2 // TODO MANUAL UPDATE
}

View File

@@ -2,13 +2,17 @@ package net.torvald.terrarum.concurrent
import net.torvald.terrarum.Terrarum
typealias RunnableFun = () -> Unit
/** Int: index of the processing core */
typealias ThreadableFun = (Int) -> Unit
/**
* Created by minjaesong on 2016-05-25.
*/
object ThreadParallel {
val threads = Terrarum.THREADS // modify this to your taste
val threadCount = Terrarum.THREADS // modify this to your taste
private val pool: Array<Thread?> = Array(threads, { null })
private val pool: Array<Thread?> = Array(threadCount, { null })
/**
* Map Runnable object to certain index of the thread pool.
@@ -23,7 +27,7 @@ object ThreadParallel {
/**
* @param runFunc A function that takes an int input (the index), and returns nothing
*/
fun map(index: Int, prefix: String, runFunc: (Int) -> Unit) {
fun map(index: Int, prefix: String, runFunc: ThreadableFun) {
val runnable = object : Runnable {
override fun run() {
runFunc(index)
@@ -52,15 +56,80 @@ object ThreadParallel {
* Primitive locking
*/
fun allFinished(): Boolean {
pool.forEach { if (it?.state != Thread.State.TERMINATED) return false }
pool.forEach { if (it != null && it.state != Thread.State.TERMINATED) return false }
return true
}
}
/**
* A thread pool that will hold the execution until all the tasks are completed.
*
* Tasks are not guaranteed to be done orderly; but the first task in the list will be executed first.
*/
@Deprecated("Experimental.", ReplaceWith("ThreadParallel", "net.torvald.terrarum.concurrent.ThreadParallel"))
object BlockingThreadPool {
val threadCount = Terrarum.THREADS // modify this to your taste
private val pool: Array<Thread?> = Array(threadCount, { null })
private var tasks: List<RunnableFun> = ArrayList<RunnableFun>()
@Volatile private var dispatchedTasks = 0
private var threadPrefix = ""
/** @return false on failure (likely the previous jobs not finished), true on success */
fun map(prefix: String, tasks: List<RunnableFun>) = setTasks(tasks, prefix)
/** @return false on failure (likely the previous jobs not finished), true on success */
fun setTasks(tasks: List<RunnableFun>, prefix: String): Boolean {
if (!allFinished())
return false
this.tasks = tasks
dispatchedTasks = 0
threadPrefix = prefix
return true
}
private fun dequeueTask(): RunnableFun {
dispatchedTasks += 1
return tasks[dispatchedTasks - 1]
}
fun startAllWaitForDie() {
while (dispatchedTasks <= tasks.lastIndex) {
// marble rolling down the slanted channel-track of threads, if a channel is empty (a task assigned
// to the thread is dead) the marble will roll into the channel, and the marble is a task #MarbleMachineX
for (i in 0 until threadCount) {
// but unlike the marble machine, marble don't actually roll down, we can just pick up any number
// of marbles and put it into an empty channel whenever we encounter one
// SO WHAT WE DO is first fill any empty channels:
if (dispatchedTasks <= tasks.lastIndex && // because cache invalidation damnit
(pool[i] == null || pool[i]!!.state == Thread.State.TERMINATED)) {
pool[i] = Thread(dequeueTask().makeRunnable(), "$threadPrefix-$dispatchedTasks") // thread name index is one-based
pool[i]!!.start()
}
// then, sleep this very thread, wake if any of the thread in the pool is terminated,
// and GOTO loop_start; if we don't sleep, this function will be busy-waiting
}
}
}
fun allFinished(): Boolean {
pool.forEach { if (it != null && it.state != Thread.State.TERMINATED) return false }
return true
}
private fun RunnableFun.makeRunnable() = Runnable {
this.invoke()
}
}
object ParallelUtils {
fun <T, R> Iterable<T>.parallelMap(transform: (T) -> R): List<R> {
val tasks = this.sliceEvenly(ThreadParallel.threads)
val destination = Array(ThreadParallel.threads) { ArrayList<R>() }
val tasks = this.sliceEvenly(ThreadParallel.threadCount)
val destination = Array(ThreadParallel.threadCount) { ArrayList<R>() }
tasks.forEachIndexed { index, list ->
ThreadParallel.map(index, "ParallelUtils.parallelMap@${this.javaClass.canonicalName}") {
for (item in list)
@@ -100,9 +169,9 @@ object ParallelUtils {
return al
}
fun Iterable<*>.sliceEvenly(slices: Int): List<List<*>> = this.toList().sliceEvenly(slices)
fun <T> Iterable<T>.sliceEvenly(slices: Int): List<List<T>> = this.toList().sliceEvenly(slices)
fun List<*>.sliceEvenly(slices: Int): List<List<*>> {
fun <T> List<T>.sliceEvenly(slices: Int): List<List<T>> {
return (0 until slices).map {
this.subList(
this.size.toFloat().div(slices).times(it).roundInt(),
@@ -111,7 +180,7 @@ object ParallelUtils {
}
}
fun Array<*>.sliceEvenly(slices: Int): List<Array<*>> {
fun <T> Array<T>.sliceEvenly(slices: Int): List<Array<T>> {
return (0 until slices).map {
this.sliceArray(
this.size.toFloat().div(slices).times(it).roundInt() until

View File

@@ -1,7 +1,7 @@
package net.torvald.terrarum.console
import net.torvald.terrarum.modulebasegame.console.*
import java.util.HashMap
import java.util.*
/**
* Created by minjaesong on 2016-01-15.
@@ -43,6 +43,7 @@ object CommandDict {
"setscale" to SetScale,
"kill" to KillActor,
"money" to MoneyDisp,
"screenshot" to TakeScreenshot,
// Test codes
"bulletintest" to SetBulletin,
@@ -59,7 +60,8 @@ object CommandDict {
/* !! */"exportlayer" to ExportLayerData,
/* !! */"importlayer" to ImportLayerData
/* !! */"importlayer" to ImportLayerData,
/* !! */"exportfborgb" to ExportRendererFboRGB
)
operator fun get(commandName: String): ConsoleCommand {

View File

@@ -1,10 +1,11 @@
package net.torvald.terrarum.console
import net.torvald.terrarum.*
import net.torvald.terrarum.ccG
import net.torvald.terrarum.ccW
import net.torvald.terrarum.ccY
import net.torvald.terrarum.langpack.Lang
import java.time.ZonedDateTime
import java.util.ArrayList
import java.util.Formatter
import java.util.*
import java.util.regex.Pattern
/**
@@ -20,7 +21,8 @@ internal object CommandInterpreter {
"getlocale",
"help",
"version",
"tips"
"tips",
"screenshot"
)
internal fun execute(command: String) {

View File

@@ -0,0 +1,14 @@
package net.torvald.terrarum.console
import net.torvald.terrarum.modulebasegame.IngameRenderer
object ExportRendererFboRGB: ConsoleCommand {
override fun execute(args: Array<String>) {
IngameRenderer.fboRGBexportRequested = true
}
override fun printUsage() {
}
}

View File

@@ -0,0 +1,13 @@
package net.torvald.terrarum.console
import net.torvald.terrarum.AppLoader
object TakeScreenshot: ConsoleCommand {
override fun execute(args: Array<String>) {
AppLoader.requestScreenshot()
}
override fun printUsage() {
Echo("Takes screenshot and save it to the default directory as 'screenshot.tga'")
}
}

View File

@@ -0,0 +1,539 @@
package net.torvald.terrarum.debuggerapp;
import net.torvald.terrarum.utils.CSVFetcher;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVRecord;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.StringReader;
import java.nio.file.Files;
import java.util.List;
import java.util.Properties;
/**
* Should be made into its own artifact to build.
*
* Only recognisable columns are read and saved, thus this app should be update when new properties are added.
*
* Created by minjaesong on 2019-01-01.
*/
public class CSVEditor extends JFrame {
/** Default columns. When you open existing csv, it should overwrite this. */
private String[] columns = new String[]{"id", "drop", "name", "shdr", "shdg", "shdb", "shduv", "str", "dsty", "mate", "solid", "plat", "wall", "fall", "dlfn", "fv", "fr", "lumr", "lumg", "lumb", "lumuv"};
private final int FOUR_DIGIT = 42;
private final int SIX_DIGIT = 50;
private final int TWO_DIGIT = 30;
private final int ARBITRARY = 240;
private int[] colWidth = new int[]{FOUR_DIGIT, FOUR_DIGIT, ARBITRARY, SIX_DIGIT, SIX_DIGIT, SIX_DIGIT, SIX_DIGIT, TWO_DIGIT, FOUR_DIGIT, FOUR_DIGIT, TWO_DIGIT, TWO_DIGIT, TWO_DIGIT, TWO_DIGIT, TWO_DIGIT, TWO_DIGIT, TWO_DIGIT, SIX_DIGIT, SIX_DIGIT, SIX_DIGIT, SIX_DIGIT};
private final int UNDO_BUFFER_SIZE = 10;
private CSVFormat csvFormat = CSVFetcher.INSTANCE.getTerrarumCSVFormat();
private final int INITIAL_ROWS = 2;
private JPanel panelSpreadSheet = new JPanel();
private JPanel panelComment = new JPanel();
private JSplitPane panelWorking = new JSplitPane(JSplitPane.VERTICAL_SPLIT, panelSpreadSheet, panelComment);
private JMenuBar menuBar = new JMenuBar();
private JTable spreadsheet = new JTable(new DefaultTableModel(columns, INITIAL_ROWS)); // it MUST be DefaultTableModel because that's what I'm using
private JTextPane caption = new JTextPane();
private JTextPane comment = new JTextPane();
private JLabel statBar = new JLabel("null.");
private JMenu undoMenu = new JMenu("Undo");
private JMenu redoMenu = new JMenu("Redo");
private Properties props = new Properties();
private Properties lang = new Properties();
private TraversingCircularArray<Object[][]> undoBuffer = new TraversingCircularArray(UNDO_BUFFER_SIZE);
public CSVEditor() {
// setup application properties //
try {
props.load(new StringReader(captionProperties));
lang.load(new StringReader(translations));
}
catch (Throwable e) {
}
// setup layout //
this.setLayout(new BorderLayout());
panelSpreadSheet.setLayout(new BorderLayout());
panelComment.setLayout(new BorderLayout());
spreadsheet.setVisible(true);
caption.setVisible(true);
caption.setEditable(false);
caption.setContentType("text/html");
caption.setText("<span style=\"font:sans-serif; color:#888888; font-style:italic;\">Description of the selected column will be displayed here.</span>");
comment.setVisible(true);
comment.setPreferredSize(new Dimension(100, 220));
comment.setText("# This is a comment section.\n# All the comment must begin with this '#' mark.\n# null value on the CSV is represented as 'N/A'.");
panelSpreadSheet.add(menuBar, BorderLayout.NORTH);
panelSpreadSheet.add(new JScrollPane(spreadsheet, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS
), BorderLayout.CENTER);
panelComment.add(caption, BorderLayout.NORTH);
panelComment.add(new JScrollPane(comment, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS
), BorderLayout.CENTER);
this.add(statBar, BorderLayout.SOUTH);
this.add(panelWorking, BorderLayout.CENTER);
this.add(menuBar, BorderLayout.NORTH);
this.setTitle("Terrarum CSV Editor");
this.setVisible(true);
this.setSize(1154, 768);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
// setup menubar //
menuBar.add(new JMenu("File") {
{
add("Open...").addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
// let's show generic warning first
if (discardAgreed()) {
// actually read file
JFileChooser fileChooser = new JFileChooser() {
{
setFileSelectionMode(JFileChooser.FILES_ONLY);
setMultiSelectionEnabled(false);
}
};
fileChooser.showOpenDialog(null);
if (fileChooser.getSelectedFile() != null) {
if (fileChooser.getSelectedFile().exists()) {
List<CSVRecord> records = CSVFetcher.INSTANCE.readFromFile(
fileChooser.getSelectedFile().getAbsolutePath());
// turn list of records into a spreadsheet
// first dispose of any existing data
((DefaultTableModel) spreadsheet.getModel()).setRowCount(0);
// then work on the file
for (CSVRecord record : records) {
String[] newRow = new String[columns.length];
// construct newRow
for (String column : columns) {
String value = record.get(column);
if (value == null) {
value = csvFormat.getNullString();
}
newRow[spreadsheet.getColumnModel().getColumnIndex(column)] = value;
}
((DefaultTableModel) spreadsheet.getModel()).addRow(newRow);
}
// then add the comments
// since the Commons CSV simply ignores the comments, we have to read them on our own.
try {
StringBuilder sb = new StringBuilder();
List<String> allTheLines = Files.readAllLines(
fileChooser.getSelectedFile().toPath());
allTheLines.forEach(line -> {
if (line.startsWith("" + csvFormat.getCommentMarker().toString())) {
sb.append(line);
sb.append('\n');
}
});
comment.setText(sb.toString());
statBar.setText(lang.getProperty("STAT_LOAD_SUCCESSFUL"));
}
catch (Throwable fuck) {
displayError("ERROR_INTERNAL", fuck);
}
}
// if file not found
else {
displayMessage("NO_SUCH_FILE");
}
} // if opening cancelled, do nothing
} // if discard cancelled, do nothing
}
});
add("Save...").addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
JFileChooser fileChooser = new JFileChooser() {
{
setFileSelectionMode(JFileChooser.FILES_ONLY);
setMultiSelectionEnabled(false);
}
};
fileChooser.showSaveDialog(null);
if (fileChooser.getSelectedFile() != null) {
try {
FileOutputStream fos = new FileOutputStream(fileChooser.getSelectedFile());
fos.write(toCSV().getBytes());
fos.flush();
fos.close();
statBar.setText(lang.getProperty("STAT_SAVE_SUCCESSFUL"));
}
catch (IOException iofuck) {
displayError("WRITE_FAIL", iofuck);
}
} // if saving cancelled, do nothing
}
});
add("New").addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
if (discardAgreed()) {
// ask new rows
Integer rows = askInteger("NEW_ROWS");
if (rows != null) {
// first, delete everything
((DefaultTableModel) spreadsheet.getModel()).setRowCount(0);
// then add some columns
((DefaultTableModel) spreadsheet.getModel()).setRowCount(rows);
// notify the user as well
statBar.setText(lang.getProperty("STAT_NEW_FILE"));
}
}
}
});
}
});
undoMenu.setEnabled(false);
redoMenu.setEnabled(false);
menuBar.add(new JMenu("Edit") {
{
add("New rows...").addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
Integer rows = askInteger("ADD_ROWS");
if (rows != null) {
DefaultTableModel tableModel = (DefaultTableModel) spreadsheet.getModel();
tableModel.setRowCount(tableModel.getRowCount() + rows);
}
}
});
add("New column...");
add("Delete current row");
add("Delete current column");
addSeparator();
add(undoMenu);
add(redoMenu);
addSeparator();
add("Sort by ID").addMouseListener(new MouseAdapter() {
private String[] getRow(int row, DefaultTableModel table) {
String[] v = new String[table.getColumnCount()];
for (int k = 0; k < v.length; k++) {
v[k] = (String) table.getValueAt(row, k);
}
return v;
}
private void setRow(int row, String[] data, DefaultTableModel table) {
for (int k = 0; k < data.length; k++) {
table.setValueAt(data[k], row, k);
}
}
private int toInt(String s) {
int i;
try {
i = Integer.parseInt(s);
if (i == -1) i = 2147483646;
}
catch (NumberFormatException e) {
i = 2147483647;
}
return i;
}
@Override
public void mousePressed(MouseEvent e) {
DefaultTableModel table = (DefaultTableModel) spreadsheet.getModel();
int tableLen = table.getRowCount();
// perkele, had to get dirty
// using insertion sort (should work good enough)
int i = 1;
while (i < tableLen) {
String[] xData = getRow(i, table);
int xComparator = toInt(xData[0]); // x <- A[i]
int j = i - 1;
String[] jData = getRow(j, table);
while (j >= 0 && toInt(jData[0]) > xComparator) {
// manually set a row
setRow(j + 1, jData, table);
j -= 1;
if (j < 0) break;
jData = getRow(j, table);
}
setRow(j + 1, xData, table);
i += 1;
}
}
});
}
});
menuBar.revalidate();
// setup spreadsheet //
// no resize
spreadsheet.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
// set column width
for (int i = 0; i < columns.length; i++) {
spreadsheet.getColumnModel().getColumn(i).setPreferredWidth(colWidth[i]);
}
// make tables do things
spreadsheet.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
}
});
// make tables do things
spreadsheet.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
// make caption line working
JTable table = ((JTable) e.getSource());
int col = table.getSelectedColumn();
String colName = table.getColumnName(col);
String captionText = props.getProperty(colName);
caption.setText("<span style=\"font:sans-serif;\"><b>" + colName + "</b><span style=\"color:#404040;\">" +
((captionText == null) ? "" : ": " + captionText) +
"</span></span>"
);
}
});
statBar.setText(lang.getProperty("STAT_INIT"));
this.revalidate();
this.repaint();
}
public static void main(String[] args) {
new CSVEditor();
}
private String toCSV() {
StringBuilder sb = new StringBuilder();
int cols = spreadsheet.getColumnModel().getColumnCount();
int rows = spreadsheet.getRowCount(); // actual rows, not counting the titles row
// add all the column titles
for (int i = 0; i < cols; i++) {
sb.append('"');
sb.append(spreadsheet.getColumnName(i));
sb.append('"');
if (i + 1 < cols) sb.append(';');
} sb.append('\n');
// loop for all the rows
forEachRow:
for (int row = 0; row < rows; row++) {
for (int col = 0; col < cols; col++) {
Object rawValue = spreadsheet.getModel().getValueAt(row, col);
String cell;
if (rawValue == null)
cell = "";
else
cell = ((String) rawValue).toUpperCase();
// skip if ID cell is empty
if (col == 0 && cell.isEmpty()) {
continue forEachRow;
}
sb.append('"');
sb.append(cell);
sb.append('"');
if (col + 1 < cols) sb.append(';');
}
sb.append("\n");
} sb.append("\n\n");
// add comments
sb.append(comment.getText());
return sb.toString();
}
private boolean discardAgreed() {
return 0 == JOptionPane.showOptionDialog(null,
lang.getProperty("WARNING_YOUR_DATA_WILL_GONE") + " " + lang.getProperty("WARNING_CONTINUE"),
null,
JOptionPane.DEFAULT_OPTION,
JOptionPane.WARNING_MESSAGE,
null,
new String[]{"OK", "Cancel"},
"Cancel"
);
}
private boolean confirmedContinue(String messageKey) {
return 0 == JOptionPane.showOptionDialog(null,
lang.getProperty(messageKey) + " " + lang.getProperty("WARNING_CONTINUE"),
null,
JOptionPane.DEFAULT_OPTION,
JOptionPane.WARNING_MESSAGE,
null,
new String[]{"OK", "Cancel"},
"Cancel"
);
}
private void displayMessage(String messageKey) {
JOptionPane.showOptionDialog(null,
lang.getProperty(messageKey),
null,
JOptionPane.DEFAULT_OPTION,
JOptionPane.INFORMATION_MESSAGE,
null,
new String[]{"OK", "Cancel"},
"Cancel"
);
}
private void displayError(String messageKey, Throwable cause) {
JOptionPane.showOptionDialog(null,
lang.getProperty(messageKey) + "\n" + cause.toString(),
null,
JOptionPane.DEFAULT_OPTION,
JOptionPane.ERROR_MESSAGE,
null,
new String[]{"OK", "Cancel"},
"Cancel"
);
}
/**
*
* @param messageKey
* @return null if the operation cancelled, nonzero int if the choice was made
*/
private Integer askInteger(String messageKey) {
OptionSize optionWindow = new OptionSize(lang.getProperty(messageKey));
int confirmedStatus = optionWindow.showDialog();
if (confirmedStatus == JOptionPane.CANCEL_OPTION) {
return null;
}
else {
return ((Integer) optionWindow.capacity.getValue());
}
}
private String captionProperties =
"" + // dummy string to make IDE happy with the auto indent
"id=ID of this block\n" +
"drop=ID of the block this very block should drop when mined\n" +
"name=String identifier of the block\n" +
"shdr=Shade Red (light absorption). Valid range 0.0-4.0\n" +
"shdg=Shade Green (light absorption). Valid range 0.0-4.0\n" +
"shdb=Shade Blue (light absorption). Valid range 0.0-4.0\n" +
"shduv=Shade UV (light absorbtion). Valid range 0.0-4.0\n" +
"lumr=Luminosity Red (light intensity). Valid range 0.0-4.0\n" +
"lumg=Luminosity Green (light intensity). Valid range 0.0-4.0\n" +
"lumb=Luminosity Blue (light intensity). Valid range 0.0-4.0\n" +
"lumuv=Luminosity UV (light intensity). Valid range 0.0-4.0\n" +
"str=Strength of the block\n" +
"dsty=Density of the block. Water have 1000 in the in-game scale\n" +
"mate=Material of the block\n" +
"solid=Whether the file has full collision\n" +
"plat=Whether the block should behave like a platform\n" +
"wall=Whether the block can be used as a wall\n" +
"fall=Whether the block should fall through the empty space\n" +
"dlfn=Dynamic Light Function. 0=Static. Please see <strong>notes</strong>\n" +
"fv=Vertical friction when player slide on the cliff. 0 means not slide-able\n" +
"fr=Horizontal friction. &lt;16:slippery 16:regular &gt;16:sticky\n";
/**
* ¤ is used as a \n marker
*/
private String translations =
"" +
"WARNING_CONTINUE=Continue?\n" +
"WARNING_YOUR_DATA_WILL_GONE=Existing edits will be lost.\n" +
"OPERATION_CANCELLED=Operation cancelled.\n" +
"NO_SUCH_FILE=No such file exists, operation cancelled.\n" +
"NEW_ROWS=Enter the number of rows to initialise the new CSV.¤Remember, you can always add or delete rows later.\n" +
"ADD_ROWS=Enter the number of rows to add:\n" +
"WRITE_FAIL=Writing to file has failed:\n" +
"STAT_INIT=Creating a new CSV. You can still open existing file.\n" +
"STAT_SAVE_SUCCESSFUL=File saved successfully.\n" +
"STAT_NEW_FILE=New CSV created.\n" +
"STAT_LOAD_SUCCESSFUL=File loaded successfully.\n" +
"ERROR_INTERNAL=Something went wrong.\n";
}
class OptionSize {
JSpinner capacity = new JSpinner(new SpinnerNumberModel(
10,
1,
4096,
1
));
private JPanel settingPanel = new JPanel();
OptionSize(String message) {
settingPanel.add(new JLabel("<html>" + message.replace("¤", "<br />") + "</html>"));
settingPanel.add(capacity);
}
/**
* returns either JOptionPane.OK_OPTION or JOptionPane.CANCEL_OPTION
*/
int showDialog() {
return JOptionPane.showConfirmDialog(null, settingPanel,
null, JOptionPane.OK_CANCEL_OPTION);
}
}

View File

@@ -0,0 +1,60 @@
package net.torvald.terrarum.debuggerapp;
/**
* To be used as undo/redo buffer. Which means, current position can go backward and rewrite objects ahead.
*
* The most recent item will be same as the current edit.
*
* Created by minjaesong on 2019-01-09.
*/
public class TraversingCircularArray<T> {
private T[] buf;
private int size;
public TraversingCircularArray(int size) {
buf = (T[]) new Object[size]; // create array of nulls
this.size = size;
}
public int getSize() {
return size;
}
private int tail = 0;
private int head = -1;
private int unreliableAddCount = 0;
/**
* Adds new item.
* @param item
*/
public void undoNew(T item) {
if (unreliableAddCount <= size) unreliableAddCount += 1;
head = (head + 1) % size;
if (unreliableAddCount > size) {
tail = (tail + 1) % size;
}
buf[head] = item; // overwrites oldest item when eligible
}
/**
* Pops existing item. This function is analogous to rewinding the tape. Existing data will be untouched.
* @return
*/
public T redo() {
tail -= 1;
return buf[tail];
}
/**
* Undo the redo. This function is analogous to fast-forwarding the tape, without touching already recorded data.
* If head of the tape reached, will do nothing.
*/
public T undoAgain() {
return null;
}
}

View File

@@ -1,8 +1,5 @@
package net.torvald.terrarum.gameactors
import net.torvald.random.HQRNG
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.itemproperties.ItemCodex
import net.torvald.terrarum.itemproperties.ItemCodex.ACTORID_MIN
@@ -19,14 +16,16 @@ abstract class Actor(val renderOrder: RenderOrder) : Comparable<Actor>, Runnable
BEHIND, // tapestries, some particles (obstructed by terrain)
MIDDLE, // actors
MIDTOP, // bullets, thrown items
FRONT // fake tiles
FRONT, // fake tiles
OVERLAY // screen overlay, not affected by lightmap
}
companion object {
val RANGE_BEHIND = ACTORID_MIN..0x1FFF_FFFF
val RANGE_MIDDLE = 0x2000_0000..0x5FFF_FFFF
val RANGE_MIDTOP = 0x6000_0000..0x6FFF_FFFF
val RANGE_FRONT = 0x7000_0000..0x7FFF_FFFF
val RANGE_BEHIND = ACTORID_MIN..0x1FFF_FFFF // 1
val RANGE_MIDDLE = 0x2000_0000..0x4FFF_FFFF // 3
val RANGE_MIDTOP = 0x5000_0000..0x5FFF_FFFF // 1
val RANGE_FRONT = 0x6000_0000..0x6FFF_FFFF // 1
val RANDE_OVERLAY= 0x7000_0000..0x7FFF_FFFF // 1
}
abstract fun update(delta: Float)
@@ -62,6 +61,8 @@ abstract class Actor(val renderOrder: RenderOrder) : Comparable<Actor>, Runnable
*/
abstract @Event fun onActorValueChange(key: String, value: Any?)
abstract fun dispose()
}
annotation class Event

View File

@@ -12,6 +12,10 @@ class ActorValue(val actor: Actor) : KVHashMap() {
}
override fun set(key: String, value: Any) {
/*if (key == AVKey.__PLAYER_QUICKSLOTSEL) {
Thread.currentThread().stackTrace.forEach { println(it) }
}*/
super.set(key, value)
actor.onActorValueChange(key, value) // fire the event handler
}

View File

@@ -3,19 +3,19 @@ package net.torvald.terrarum.gameactors
import com.badlogic.gdx.Input
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.g2d.SpriteBatch
import net.torvald.terrarum.Point2d
import net.torvald.terrarum.*
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.worlddrawer.FeaturesDrawer
import net.torvald.terrarum.blockproperties.BlockCodex
import net.torvald.spriteanimation.SpriteAnimation
import net.torvald.terrarum.*
import net.torvald.terrarum.AppLoader.printdbg
import net.torvald.terrarum.worlddrawer.WorldCamera
import net.torvald.terrarum.blockproperties.Block
import net.torvald.terrarum.blockproperties.BlockCodex
import net.torvald.terrarum.blockproperties.BlockProp
import net.torvald.terrarum.gamecontroller.KeyToggler
import net.torvald.terrarum.gameworld.BlockAddress
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
import net.torvald.terrarum.realestate.LandUtil
import net.torvald.terrarum.worlddrawer.FeaturesDrawer
import net.torvald.terrarum.worlddrawer.WorldCamera
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
import org.dyn4j.geometry.Vector2
import java.util.*
@@ -45,16 +45,16 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
private val world: GameWorld?
get() = Terrarum.ingame?.world
@Transient internal var sprite: SpriteAnimation? = null
@Transient internal var spriteGlow: SpriteAnimation? = null
var drawMode = BlendMode.NORMAL
var hitboxTranslateX: Int = 0// relative to spritePosX
protected set
protected set
var hitboxTranslateY: Int = 0// relative to spritePosY
protected set
protected set
var baseHitboxW: Int = 0
protected set
var baseHitboxH: Int = 0
@@ -66,39 +66,64 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
*/
override val hitbox = Hitbox(0.0, 0.0, 0.0, 0.0) // Hitbox is implemented using Double;
/** half integer tilewise hitbox */ // got the idea from gl_FragCoord
/** half integer tilewise hitbox.
* May hold width/height of zero; the end point should be inclusive!
*
* e.g. USE `for (x in hitbox.startX..hitbox.endX)`, NOT `for (x in hitbox.startX until hitbox.endX)`
*/ // got the idea from gl_FragCoord
val hIntTilewiseHitbox: Hitbox
get() = Hitbox.fromTwoPoints(
hitbox.startX.plus(0.0001f).div(TILE_SIZE).floor() + 0.5f,
hitbox.startY.plus(0.0001f).div(TILE_SIZE).floor() + 0.5f,
hitbox.endX.plus(0.0001f).div(TILE_SIZE).floor() + 0.5f,
hitbox.endY.plus(0.0001f).div(TILE_SIZE).floor() + 0.5f
hitbox.startX.plus(0.00001f).div(TILE_SIZE).floor() + 0.5f,
hitbox.startY.plus(0.00001f).div(TILE_SIZE).floor() + 0.5f,
hitbox.endX.plus(0.00001f).div(TILE_SIZE).floor() + 0.5f,
hitbox.endY.plus(0.00001f).div(TILE_SIZE).floor() + 0.5f,
true
)
/** May hold width/height of zero; the end point should be inclusive!
*
* e.g. USE `for (x in hitbox.startX..hitbox.endX)`, NOT `for (x in hitbox.startX until hitbox.endX)`
*/
val intTilewiseHitbox: Hitbox
get() = Hitbox.fromTwoPoints(
hitbox.startX.plus(0.0001f).div(TILE_SIZE).floor(),
hitbox.startY.plus(0.0001f).div(TILE_SIZE).floor(),
hitbox.endX.plus(0.0001f).div(TILE_SIZE).floor(),
hitbox.endY.plus(0.0001f).div(TILE_SIZE).floor()
hitbox.startX.plus(0.00001f).div(TILE_SIZE).floor(),
hitbox.startY.plus(0.00001f).div(TILE_SIZE).floor(),
hitbox.endX.plus(0.00001f).div(TILE_SIZE).floor(),
hitbox.endY.plus(0.00001f).div(TILE_SIZE).floor(),
true
)
/**
* Unit: Pixels per 1/60 (or AppLoader.UPDATE_RATE) seconds.
*
* When the engine resolves this value, the framerate must be accounted for. E.g.:
* 3.0 is resolved as 3.0 if FPS is 60, but the same value should be resolved as 6.0 if FPS is 30.
* v_resolved = v * (60/FPS) or, v * (60 * delta_t)
* (Use this code verbatim: '(Terrarum.PHYS_REF_FPS * delta)')
*
*
* Elevators/Movingwalks/etc.: edit hitbox manually!
*
* Velocity vector for newtonian sim.
* Acceleration: used in code like:
* veloY += 3.0
* +3.0 is acceleration. You __accumulate__ acceleration to the velocity.
*
* V for Velocity!
*/
internal val externalForce = Vector2(0.0, 0.0)
internal val externalV = Vector2(0.0, 0.0)
@Transient private val VELO_HARD_LIMIT = 100.0
/**
* Unit: Pixels per 1/60 (or AppLoader.UPDATE_RATE) seconds.
*
* for "Controllable" actors
*
* V for Velocity!
*/
var controllerMoveDelta: Vector2? = if (this is Controllable) Vector2() else null
var controllerV: Vector2? = if (this is Controllable) Vector2() else null
// not sure we need this...
//var jumpable = true // this is kind of like "semaphore"
@@ -120,16 +145,16 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
/** Apparent mass. Use "avBaseMass" for base mass */
val mass: Double
get() = actorValue.getAsDouble(AVKey.BASEMASS) ?: MASS_DEFAULT * Math.pow(scale, 3.0)
/*set(value) { // use "var avBaseMass: Double"
if (value <= 0)
throw IllegalArgumentException("mass cannot be less than or equal to zero.")
else if (value < MASS_LOWEST) {
printdbg(this, "input too small; using $MASS_LOWEST instead.")
actorValue[AVKey.BASEMASS] = MASS_LOWEST
}
/*set(value) { // use "var avBaseMass: Double"
if (value <= 0)
throw IllegalArgumentException("mass cannot be less than or equal to zero.")
else if (value < MASS_LOWEST) {
printdbg(this, "input too small; using $MASS_LOWEST instead.")
actorValue[AVKey.BASEMASS] = MASS_LOWEST
}
actorValue[AVKey.BASEMASS] = value / Math.pow(scale, 3.0)
}*/
actorValue[AVKey.BASEMASS] = value / Math.pow(scale, 3.0)
}*/
@Transient val MASS_DEFAULT: Double = 60.0
/** Valid range: [0, 1] */
var elasticity: Double = 0.0
@@ -172,8 +197,8 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
private inline val grounded: Boolean
get() = if (world == null) true else {
isNoClip ||
(world!!.gravitation.y > 0 && isWalled(hitbox, COLLIDING_BOTTOM) ||
isNoClip ||
(world!!.gravitation.y > 0 && isWalled(hitbox, COLLIDING_BOTTOM) ||
world!!.gravitation.y < 0 && isWalled(hitbox, COLLIDING_TOP))
}
/** Default to 'true' */
@@ -199,7 +224,7 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
* meter to pixel : 24/FPS
*/
private val gravitation: Vector2
get() = world?.gravitation ?: Vector2(0.0, 9.8)
get() = world?.gravitation ?: Vector2(0.0, 9.8)
@Transient val DRAG_COEFF_DEFAULT = 1.2
/** Drag coefficient. Parachutes have much higher value than bare body (1.2) */
var dragCoefficient: Double
@@ -253,10 +278,6 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
internal var walledTop = false // UNUSED; only for BasicDebugInfoWindow
internal var walledBottom = false // UNUSED; only for BasicDebugInfoWindow
internal var colliding = false
protected inline val updateDelta: Float
get() = Terrarum.deltaTime
var isWalkingH = false
var isWalkingV = false
@@ -323,7 +344,7 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
inline val feetPosTile: IntArray
get() = intArrayOf(hIntTilewiseHitbox.centeredX.floorInt(), hIntTilewiseHitbox.endY.floorInt())
override fun run() = update(updateDelta)
override fun run() = update(AppLoader.getSmoothDelta().toFloat())
/**
* Add vector value to the velocity, in the time unit of single frame.
@@ -333,14 +354,13 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
* @param acc : Acceleration in Vector2
*/
fun applyForce(acc: Vector2) {
externalForce += acc * speedMultByTile
externalV += acc * speedMultByTile
}
private val bounceDampenVelThreshold = 0.5
override fun update(delta: Float) {
if (isUpdate && !flagDespawn) {
if (!assertPrinted) assertInit()
if (sprite != null) sprite!!.update(delta)
@@ -361,7 +381,7 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
////////////////////////////////////////////////////////////////
// Codes that modifies velocity (moveDelta and externalForce) //
// Codes that modifies velocity (moveDelta and externalV) //
////////////////////////////////////////////////////////////////
// --> Apply more forces <-- //
@@ -369,15 +389,15 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
// Actors are subject to the gravity and the buoyancy if they are not levitating
if (!isNoSubjectToGrav) {
applyGravitation()
applyGravitation(delta)
}
//applyBuoyancy()
}
// hard limit velocity
externalForce.x = externalForce.x.bipolarClamp(VELO_HARD_LIMIT) // displaceHitbox SHOULD use moveDelta
externalForce.y = externalForce.y.bipolarClamp(VELO_HARD_LIMIT)
externalV.x = externalV.x.bipolarClamp(VELO_HARD_LIMIT) // displaceHitbox SHOULD use moveDelta
externalV.y = externalV.y.bipolarClamp(VELO_HARD_LIMIT)
if (!isChronostasis) {
///////////////////////////////////////////////////
@@ -390,36 +410,11 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
* This body is NON-STATIC and the other body is STATIC
*/
if (!isNoCollideWorld) {
// // HOW IT SHOULD WORK // //
// ////////////////////////
// combineVeloToMoveDelta now
// displace hitbox (!! force--moveDelta--still exist, do not touch the force !!)
// make sure "touching" is perfectly useable
// 16-step ccd applies here
// ((nextHitbox <- hitbox))
// resolve forces (use up the force && deform the vector):
// // "touching" should work at this point if displaceHitbox is successful
// [Collision]:
// if touching (test for both axes):
// re-direct force vector by mul w/ elasticity
// if not touching:
// do nothing
// [Friction]:
// deform vector "externalForce"
// if isControllable:
// also alter walkX/Y
// translate ((nextHitbox)) hitbox by moveDelta (forces), this consumes force
// DO NOT set whatever delta to zero
// ((hitbox <- nextHitbox))
//
// ((comments)) [Label]
displaceHitbox()
displaceHitbox(delta.toDouble())
}
else {
hitbox.translate(externalForce)
hitbox.translate(controllerMoveDelta)
val vecSum = externalV + (controllerV ?: Vector2(0.0, 0.0))
hitbox.translate(vecSum)
}
//////////////////////////////////////////////////////////////
@@ -433,9 +428,9 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
// TODO less friction for non-animating objects (make items glide far more on ice)
// FIXME asymmetry on friction
setHorizontalFriction() // friction SHOULD use and alter externalForce
setHorizontalFriction(delta) // friction SHOULD use and alter externalV
//if (isNoClip) { // TODO also hanging on the rope, etc.
setVerticalFriction()
setVerticalFriction(delta)
//}
@@ -475,38 +470,38 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
if (!(isWalled(hitbox, COLLIDING_LEFT) && walkX < 0)
|| !(isWalled(hitbox, COLLIDING_RIGHT) && walkX > 0)
) {
moveDelta.x = externalForce.x + walkX
moveDelta.x = externalV.x + walkX
}
// decide whether to ignore walkY
if (!(isWalled(hitbox, COLLIDING_TOP) && walkY < 0)
|| !(isWalled(hitbox, COLLIDING_BOTTOM) && walkY > 0)
) {
moveDelta.y = externalForce.y + walkY
moveDelta.y = externalV.y + walkY
}
}
else {
if (!isWalled(hitbox, COLLIDING_LEFT)
|| !isWalled(hitbox, COLLIDING_RIGHT)
) {
moveDelta.x = externalForce.x
moveDelta.x = externalV.x
}
// decide whether to ignore walkY
if (!isWalled(hitbox, COLLIDING_TOP)
|| !isWalled(hitbox, COLLIDING_BOTTOM)
) {
moveDelta.y = externalForce.y
moveDelta.y = externalV.y
}
}
}*/
fun getDrag(externalForce: Vector2): Vector2 {
fun getDrag(delta: Float, externalForce: Vector2): Vector2 {
/**
* weight; gravitational force in action
* W = mass * G (9.8 [m/s^2])
*/
val W: Vector2 = gravitation * Terrarum.TARGET_FPS.toDouble()
val W: Vector2 = gravitation * Terrarum.PHYS_TIME_FRAME.toDouble()
/**
* Area
*/
@@ -517,9 +512,12 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
*/
val D: Vector2 = Vector2(externalForce.x.magnSqr(), externalForce.y.magnSqr()) * dragCoefficient * 0.5 * A// * tileDensityFluid.toDouble()
val V: Vector2 = (W - D) / Terrarum.TARGET_FPS * SI_TO_GAME_ACC
val V: Vector2 = (W - D) / Terrarum.PHYS_TIME_FRAME * SI_TO_GAME_ACC
return V
// FIXME v * const, where const = 1.0 for FPS=60, sqrt(2.0) for FPS=30, etc.
// this is "close enough" solution and not perfect.
}
/**
@@ -537,11 +535,11 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
*
* Apply only if not grounded; normal force is precessed separately.
*/
private fun applyGravitation() {
private fun applyGravitation(delta: Float) {
if (!isNoSubjectToGrav && !(gravitation.y > 0 && walledBottom || gravitation.y < 0 && walledTop)) {
//if (!isWalled(hitbox, COLLIDING_BOTTOM)) {
applyForce(getDrag(externalForce))
applyForce(getDrag(delta, externalV))
//}
}
}
@@ -573,35 +571,73 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
}
}*/
private fun displaceHitbox() {
private fun displaceHitbox(delta: Double) {
// // HOW IT SHOULD WORK // //
// ////////////////////////
// combineVeloToMoveDelta now
// displace hitbox (!! force--moveDelta--still exist, do not touch the force !!)
// make sure "touching" is perfectly useable
// 16-step ccd applies here
// ((nextHitbox <- hitbox))
// resolve forces (use up the force && deform the vector):
// // "touching" should work at this point if displaceHitbox is successful
// [Collision]:
// if touching (test for both axes):
// re-direct force vector by mul w/ elasticity
// if not touching:
// do nothing
// [Friction]:
// deform vector "externalV"
// if isControllable:
// also alter walkX/Y
// translate ((nextHitbox)) hitbox by moveDelta (forces), this consumes force
// DO NOT set whatever delta to zero
// ((hitbox <- nextHitbox))
//
// ((comments)) [Label]
if (world != null) {
fun debug1(wut: Any?) {
// vvvvv set it true to make debug print work
if (true) println(wut)
if (true) printdbg(this, wut)
}
fun debug2(wut: Any?) {
// vvvvv set it true to make debug print work
if (false) println(wut)
if (false) printdbg(this, wut)
}
fun debug3(wut: Any?) {
// vvvvv set it true to make debug print work
if (false) println(wut)
if (false) printdbg(this, wut)
}
fun debug4(wut: Any?) {
// vvvvv set it true to make debug print work
if (false) println(wut)
if (false) printdbg(this, wut)
}
fun BlockAddress.isFeetTile(hitbox: Hitbox): Boolean {
val (x, y) = LandUtil.resolveBlockAddr(world!!, this)
val newTilewiseHitbox = Hitbox.fromTwoPoints(
hitbox.startX.div(TILE_SIZE).floor(),
hitbox.startY.div(TILE_SIZE).floor(),
hitbox.endX.minus(0.00001).div(TILE_SIZE).floor(),
hitbox.endY.minus(0.00001).div(TILE_SIZE).floor(),
true
)
// offset 1 pixel to the down so that friction would work
return (y == hitbox.endY.plus(1.0).div(TILE_SIZE).floorInt()) && // copied from forEachFeetTileNum
(x in newTilewiseHitbox.startX.toInt()..newTilewiseHitbox.endX.toInt()) // copied from forEachOccupyingTilePos
}
fun Double.modTile() = this.toInt().div(TILE_SIZE).times(TILE_SIZE)
fun Double.modTileDelta() = this - this.modTile()
val vectorSum = externalForce + controllerMoveDelta
val vectorSum = (externalV + controllerV)
val ccdSteps = minOf(16, (vectorSum.magnitudeSquared / TILE_SIZE.sqr()).floorInt() + 1) // adaptive
@@ -616,10 +652,10 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
// 20 sixteenStep may be optional, I think, but it'd be good to have
// ignore MOST of the codes below (it might be possible to recycle the structure??)
// and the idea above has not yet implemented, and may never will. --Torvald, 2018-12-30
val sixteenStep = (0..ccdSteps).map { hitbox.clone().translate(vectorSum * (it / ccdSteps.toDouble())) } // zeroth step is for special condition
val affectingTiles = ArrayList<BlockAddress>()
var collidingStep: Int? = null
for (step in 1..ccdSteps) {
@@ -628,17 +664,14 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
forEachOccupyingTilePos(stepBox) {
val tileCoord = LandUtil.resolveBlockAddr(world!!, it)
val tileProp = BlockCodex.getOrNull(world!!.getTileFromTerrain(tileCoord.first, tileCoord.second))
val tile = world!!.getTileFromTerrain(tileCoord.first, tileCoord.second) ?: Block.STONE
if (tileProp == null || tileProp.isSolid) {
affectingTiles.add(it)
if (shouldICollideWithThis(tile) || (it.isFeetTile(stepBox) && shouldICollideWithThisFeet(tile))) {
collidingStep = step
}
}
if (affectingTiles.isNotEmpty()) {
collidingStep = step
break // collision found on this step, break and proceed to next step
}
if (collidingStep != null) break
}
@@ -661,7 +694,7 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
debug1("== Collision step: $collidingStep / $ccdSteps")
val newHitbox = hitbox.reassign(sixteenStep[collidingStep])
val newHitbox = hitbox.reassign(sixteenStep[collidingStep!!])
var selfCollisionStatus = 0
if (isWalled(newHitbox, COLLIDING_LEFT)) selfCollisionStatus += COLL_LEFTSIDE // 1
@@ -671,12 +704,6 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
// fixme UP and RIGHT && LEFT and DOWN bug
debug1("Collision type: $selfCollisionStatus")
affectingTiles.forEach {
val tileCoord = LandUtil.resolveBlockAddr(world!!, it)
debug2("affectign tile: ${tileCoord.first}, ${tileCoord.second}")
}
when (selfCollisionStatus) {
0 -> {
debug1("[ActorWBMovable] Contradiction -- collision detected by CCD, but isWalled() says otherwise")
@@ -690,7 +717,7 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
15 -> {
newHitbox.reassign(sixteenStep[0]); zeroX = true; zeroY = true
}
// one-side collision
// one-side collision
1, 11 -> {
newHitbox.translatePosX(TILE_SIZE - newHitbox.startX.modTileDelta()); bounceX = true
}
@@ -709,7 +736,7 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
// fire Collision Event with one/two/three-side collision
// for the ease of writing, this jumptable is separated from above.
when (selfCollisionStatus) {
// TODO compose CollisionInfo and fire collided()
// TODO compose CollisionInfo and fire collided()
}
@@ -811,20 +838,20 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
// bounce X/Y
if (bounceX) {
externalForce.x *= elasticity
controllerMoveDelta?.let { controllerMoveDelta!!.x *= elasticity }
externalV.x *= elasticity
controllerV?.let { controllerV!!.x *= elasticity }
}
if (bounceY) {
externalForce.y *= elasticity
controllerMoveDelta?.let { controllerMoveDelta!!.y *= elasticity }
externalV.y *= elasticity
controllerV?.let { controllerV!!.y *= elasticity }
}
if (zeroX) {
externalForce.x = 0.0
controllerMoveDelta?.let { controllerMoveDelta!!.x = 0.0 }
externalV.x = 0.0
controllerV?.let { controllerV!!.x = 0.0 }
}
if (zeroY) {
externalForce.y = 0.0
controllerMoveDelta?.let { controllerMoveDelta!!.y = 0.0 }
externalV.y = 0.0
controllerV?.let { controllerV!!.y = 0.0 }
}
@@ -833,7 +860,7 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
// slam-into-whatever damage (such dirty; much hack; wow)
// vvvv hack (supposed to be 1.0) vvv 50% hack
val collisionDamage = mass * (vectorSum.magnitude / (10.0 / Terrarum.TARGET_FPS).sqr()) / fallDamageDampening.sqr() * GAME_TO_SI_ACC
val collisionDamage = mass * (vectorSum.magnitude / (10.0 / Terrarum.PHYS_TIME_FRAME).sqr()) / fallDamageDampening.sqr() * GAME_TO_SI_ACC
// kg * m / s^2 (mass * acceleration), acceleration -> (vectorMagn / (0.01)^2).gameToSI()
if (collisionDamage != 0.0) debug1("Collision damage: $collisionDamage N")
// FIXME instead of 0.5mv^2, we can model after "change of velocity (aka accel)", just as in real-life; big change of accel on given unit time is what kills
@@ -939,23 +966,61 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
val tyStart = y1.plus(0.5f).div(TILE_SIZE).floorInt()
val tyEnd = y2.plus(0.5f).div(TILE_SIZE).floorInt()
return isCollidingInternal(txStart, tyStart, txEnd, tyEnd)
return isCollidingInternal(txStart, tyStart, txEnd, tyEnd, option == COLLIDING_BOTTOM)
}
private fun isCollidingInternal(txStart: Int, tyStart: Int, txEnd: Int, tyEnd: Int): Boolean {
private fun isCollidingInternal(txStart: Int, tyStart: Int, txEnd: Int, tyEnd: Int, feet: Boolean = false): Boolean {
if (world == null) return false
for (y in tyStart..tyEnd) {
for (x in txStart..txEnd) {
val tile = world!!.getTileFromTerrain(x, y)
if (BlockCodex[tile].isSolid)
return true
val tile = world!!.getTileFromTerrain(x, y) ?: Block.STONE
if (feet) {
if (shouldICollideWithThisFeet(tile))
return true
}
else {
if (shouldICollideWithThis(tile))
return true
}
// this weird statement means that if's the condition is TRUE, return TRUE;
// if the condition is FALSE, do nothing and let succeeding code handle it.
}
}
return false
}
/**
* If this tile should be treated as "collidable"
*
* Very straightforward for the actual solid tiles, not so much for the platforms
*/
private fun shouldICollideWithThis(tile: Int) =
// regular solid block
(BlockCodex[tile].isSolid)
/**
* If this tile should be treated as "collidable"
*
* Just like "shouldICollideWithThis" but it's intended to work with feet tiles
*/
private fun shouldICollideWithThisFeet(tile: Int) =
// regular solid block
(BlockCodex[tile].isSolid) ||
// platforms, moving downward AND not "going down"
(this is ActorHumanoid && BlockCodex[tile].isPlatform &&
externalV.y + (controllerV?.y ?: 0.0) >= 0.0 &&
!this.isDownDown && this.axisY <= 0f) ||
// platforms, moving downward
(this !is ActorHumanoid && BlockCodex[tile].isPlatform &&
externalV.y + (controllerV?.y ?: 0.0) >= 0.0)
// TODO: as for the platform, only apply it when it's a feet tile
private fun getContactingAreaFluid(side: Int, translateX: Int = 0, translateY: Int = 0): Int {
if (world == null) return 0
@@ -966,30 +1031,30 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
val tileY: Int
if (side == COLLIDING_LEFT) {
tileX = div16TruncateToMapWidth(hitbox.hitboxStart.x.roundInt()
+ i + translateX)
+ i + translateX)
tileY = div16TruncateToMapHeight(hitbox.hitboxEnd.y.roundInt() + translateY)
}
else if (side == COLLIDING_TOP) {
tileX = div16TruncateToMapWidth(hitbox.hitboxStart.x.roundInt()
+ i + translateX)
+ i + translateX)
tileY = div16TruncateToMapHeight(hitbox.hitboxStart.y.roundInt() + translateY)
}
else if (side == COLLIDING_RIGHT) {
tileX = div16TruncateToMapWidth(hitbox.hitboxEnd.x.roundInt() + translateX)
tileY = div16TruncateToMapHeight(hitbox.hitboxStart.y.roundInt()
+ i + translateY)
+ i + translateY)
}
else if (side == COLLIDING_LEFT) {
tileX = div16TruncateToMapWidth(hitbox.hitboxStart.x.roundInt() + translateX)
tileY = div16TruncateToMapHeight(hitbox.hitboxStart.y.roundInt()
+ i + translateY)
+ i + translateY)
}
else {
throw IllegalArgumentException(side.toString() + ": Wrong side input")
}
// evaluate
if (BlockCodex[world!!.getTileFromTerrain(tileX, tileY)].isFluid) {
if (world!!.getFluid(tileX, tileY).isFluid()) {
contactAreaCounter += 1
}
}
@@ -1006,7 +1071,7 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
/** about stopping
* for about get moving, see updateMovementControl */
private fun setHorizontalFriction() {
private fun setHorizontalFriction(delta: Float) {
val friction = if (isNoClip)
BASE_FRICTION * BlockCodex[Block.STONE].friction.frictionToMult()
else {
@@ -1014,50 +1079,50 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
BASE_FRICTION * if (grounded) feetFriction else bodyFriction
}
if (externalForce.x < 0) {
externalForce.x += friction
if (externalForce.x > 0) externalForce.x = 0.0 // compensate overshoot
if (externalV.x < 0) {
externalV.x += friction
if (externalV.x > 0) externalV.x = 0.0 // compensate overshoot
}
else if (externalForce.x > 0) {
externalForce.x -= friction
if (externalForce.x < 0) externalForce.x = 0.0 // compensate overshoot
else if (externalV.x > 0) {
externalV.x -= friction
if (externalV.x < 0) externalV.x = 0.0 // compensate overshoot
}
if (this is Controllable) {
if (controllerMoveDelta!!.x < 0) {
controllerMoveDelta!!.x += friction
if (controllerMoveDelta!!.x > 0) controllerMoveDelta!!.x = 0.0
if (controllerV!!.x < 0) {
controllerV!!.x += friction
if (controllerV!!.x > 0) controllerV!!.x = 0.0
}
else if (controllerMoveDelta!!.x > 0) {
controllerMoveDelta!!.x -= friction
if (controllerMoveDelta!!.x < 0) controllerMoveDelta!!.x = 0.0
else if (controllerV!!.x > 0) {
controllerV!!.x -= friction
if (controllerV!!.x < 0) controllerV!!.x = 0.0
}
}
}
private fun setVerticalFriction() {
private fun setVerticalFriction(delta: Float) {
val friction = if (isNoClip)
BASE_FRICTION * BlockCodex[Block.STONE].friction.frictionToMult()
else
BASE_FRICTION * bodyFriction
if (externalForce.y < 0) {
externalForce.y += friction
if (externalForce.y > 0) externalForce.y = 0.0 // compensate overshoot
if (externalV.y < 0) {
externalV.y += friction
if (externalV.y > 0) externalV.y = 0.0 // compensate overshoot
}
else if (externalForce.y > 0) {
externalForce.y -= friction
if (externalForce.y < 0) externalForce.y = 0.0 // compensate overshoot
else if (externalV.y > 0) {
externalV.y -= friction
if (externalV.y < 0) externalV.y = 0.0 // compensate overshoot
}
if (this is Controllable) {
if (controllerMoveDelta!!.y < 0) {
controllerMoveDelta!!.y += friction
if (controllerMoveDelta!!.y > 0) controllerMoveDelta!!.y = 0.0
if (controllerV!!.y < 0) {
controllerV!!.y += friction
if (controllerV!!.y > 0) controllerV!!.y = 0.0
}
else if (controllerMoveDelta!!.y > 0) {
controllerMoveDelta!!.y -= friction
if (controllerMoveDelta!!.y < 0) controllerMoveDelta!!.y = 0.0
else if (controllerV!!.y > 0) {
controllerV!!.y -= friction
if (controllerV!!.y < 0) controllerV!!.y = 0.0
}
}
}
@@ -1094,17 +1159,23 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
).toDouble()
// body friction is always as same as the air. Fluid doesn't matter, they use viscosity
// (or viscosity was the wrong way and the friction DO matter? hmm... -- Torvald, 2018-12-31)
// (or perhaps... they work in tandem, viscocity slows things down, friction makes go and stop fast -- Torvald, 2019-01-01; not the proudest thing to do in the ney year)
// going down the platform won't show abnormal slowing (it's because of the friction prop!)
internal inline val bodyFriction: Double
get() {
var friction = 0.0
/*var friction = 0.0
forEachOccupyingTileNum {
// get max friction
if (getTileFriction(it ?: Block.AIR) > friction)
friction = getTileFriction(it ?: Block.AIR)
}
return friction
return friction*/
return getTileFriction(Block.AIR)
}
// after all, feet friction is what it matters
internal inline val feetFriction: Double
get() {
var friction = 0.0
@@ -1178,10 +1249,10 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
private inline val tileDensityFluid: Int
get() {
var density = 0
forEachOccupyingTile {
forEachOccupyingFluid {
// get max density for each tile
if (it?.isFluid ?: false && it?.density ?: 0 > density) {
density = it?.density ?: 0
if (it?.isFluid() ?: false && it?.getProp()?.density ?: 0 > density) {
density = it?.getProp()?.density ?: 0
}
}
@@ -1265,7 +1336,7 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
override fun drawGlow(batch: SpriteBatch) {
if (isVisible && spriteGlow != null) {
blendNormal()
blendNormal(batch)
drawSpriteInGoodPosition(spriteGlow!!, batch)
}
}
@@ -1273,7 +1344,7 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
override fun drawBody(batch: SpriteBatch) {
if (isVisible && sprite != null) {
if (!KeyToggler.isOn(Input.Keys.F12)) {
BlendMode.resolve(drawMode)
BlendMode.resolve(drawMode, batch)
drawSpriteInGoodPosition(sprite!!, batch)
}
else {
@@ -1372,8 +1443,8 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
field = value
if (value) {
externalForce.zero()
controllerMoveDelta?.zero()
externalV.zero()
controllerV?.zero()
}
}
@@ -1401,8 +1472,8 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
private fun forEachOccupyingTileNum(consumer: (Int?) -> Unit) {
if (world == null) return
val tiles = ArrayList<Int?>()
for (y in hIntTilewiseHitbox.startY.toInt()..hIntTilewiseHitbox.endY.toInt()) {
for (x in hIntTilewiseHitbox.startX.toInt()..hIntTilewiseHitbox.endX.toInt()) {
@@ -1416,7 +1487,7 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
private fun forEachOccupyingTile(consumer: (BlockProp?) -> Unit) {
if (world == null) return
val tileProps = ArrayList<BlockProp?>()
for (y in hIntTilewiseHitbox.startY.toInt()..hIntTilewiseHitbox.endY.toInt()) {
for (x in hIntTilewiseHitbox.startX.toInt()..hIntTilewiseHitbox.endX.toInt()) {
@@ -1427,16 +1498,32 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
return tileProps.forEach(consumer)
}
private fun forEachOccupyingFluid(consumer: (GameWorld.FluidInfo?) -> Unit) {
if (world == null) return
val fluids = ArrayList<GameWorld.FluidInfo?>()
for (y in hIntTilewiseHitbox.startY.toInt()..hIntTilewiseHitbox.endY.toInt()) {
for (x in hIntTilewiseHitbox.startX.toInt()..hIntTilewiseHitbox.endX.toInt()) {
fluids.add(world!!.getFluid(x, y))
}
}
return fluids.forEach(consumer)
}
private fun forEachOccupyingTilePos(hitbox: Hitbox, consumer: (BlockAddress) -> Unit) {
if (world == null) return
val newTilewiseHitbox = Hitbox.fromTwoPoints(
hitbox.startX.div(TILE_SIZE).floor(),
hitbox.startY.div(TILE_SIZE).floor(),
hitbox.endX.minus(0.00001).div(TILE_SIZE).floor(),
hitbox.endY.minus(0.00001).div(TILE_SIZE).floor()
)
hitbox.endY.minus(0.00001).div(TILE_SIZE).floor(),
true
) // NOT the same as intTilewiseHitbox !!
val tilePosList = ArrayList<BlockAddress>()
for (y in newTilewiseHitbox.startY.toInt()..newTilewiseHitbox.endY.toInt()) {
@@ -1451,7 +1538,7 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
private fun forEachFeetTileNum(consumer: (Int?) -> Unit) {
if (world == null) return
val tiles = ArrayList<Int?>()
// offset 1 pixel to the down so that friction would work
@@ -1467,7 +1554,7 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
private fun forEachFeetTile(consumer: (BlockProp?) -> Unit) {
if (world == null) return
val tileProps = ArrayList<BlockProp?>()
// offset 1 pixel to the down so that friction would work
@@ -1492,16 +1579,16 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
/**
* [m / s^2] * SI_TO_GAME_ACC -> [px / InternalFrame^2]
*/
@Transient val SI_TO_GAME_ACC = METER / (Terrarum.TARGET_FPS * Terrarum.TARGET_FPS)
@Transient val SI_TO_GAME_ACC = METER / (Terrarum.PHYS_TIME_FRAME * Terrarum.PHYS_TIME_FRAME)
/**
* [m / s] * SI_TO_GAME_VEL -> [px / InternalFrame]
*/
@Transient val SI_TO_GAME_VEL = METER / Terrarum.TARGET_FPS
@Transient val SI_TO_GAME_VEL = METER / Terrarum.PHYS_TIME_FRAME
/**
* [px / InternalFrame^2] * GAME_TO_SI_ACC -> [m / s^2]
*/
@Transient val GAME_TO_SI_ACC = (Terrarum.TARGET_FPS * Terrarum.TARGET_FPS) / METER
@Transient val GAME_TO_SI_ACC = (Terrarum.PHYS_TIME_FRAME * Terrarum.PHYS_TIME_FRAME) / METER
/**
@@ -1571,9 +1658,9 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
internal val avAcceleration: Double
get() { if (accelMultMovement.isNaN()) println("accelMultMovement: $accelMultMovement")
return actorValue.getAsDouble(AVKey.ACCEL)!! *
(actorValue.getAsDouble(AVKey.ACCELBUFF) ?: 1.0) *
accelMultMovement *
scale.sqrt()
(actorValue.getAsDouble(AVKey.ACCELBUFF) ?: 1.0) *
accelMultMovement *
scale.sqrt()
}
internal val avSpeedCap: Double
get() = actorValue.getAsDouble(AVKey.SPEED)!! *

View File

@@ -12,6 +12,4 @@ abstract class ActorWithBody(renderOrder: RenderOrder) : Actor(renderOrder) {
abstract fun drawBody(batch: SpriteBatch)
abstract fun drawGlow(batch: SpriteBatch)
open var tooltipText: String? = null // null: display nothing
abstract fun dispose()
}

View File

@@ -10,7 +10,7 @@ import org.dyn4j.geometry.Vector2
*
* Created by minjaesong on 2016-01-15.
*/
class Hitbox(x1: Double, y1: Double, width: Double, height: Double) {
class Hitbox(x1: Double, y1: Double, width: Double, height: Double, var suppressWarning: Boolean = false) {
@Volatile var hitboxStart: Point2d
private set
@@ -25,6 +25,11 @@ class Hitbox(x1: Double, y1: Double, width: Double, height: Double) {
hitboxStart = Point2d(x1, y1)
this.width = width
this.height = height
if (!suppressWarning && (width == 0.0 || height == 0.0)) {
println("[Hitbox] width or height is zero ($this), perhaps you want to check it out?")
Thread.currentThread().stackTrace.forEach { println(it) }
}
}
override fun toString(): String {
@@ -59,6 +64,12 @@ class Hitbox(x1: Double, y1: Double, width: Double, height: Double) {
hitboxStart = Point2d(x1, y1)
this.width = width
this.height = height
if (!suppressWarning && (width == 0.0 || height == 0.0)) {
println("[Hitbox] width or height is zero ($this), perhaps you want to check it out?")
Thread.currentThread().stackTrace.forEach { println(it) }
}
return this
}
fun setFromTwoPoints(x1: Double, y1: Double, x2: Double, y2: Double): Hitbox {
@@ -72,8 +83,8 @@ class Hitbox(x1: Double, y1: Double, width: Double, height: Double) {
fun setPosition(x1: Double, y1: Double): Hitbox {
hitboxStart = Point2d(x1, y1)
if (width == 0.0 || height == 0.0) {
println("[Hitbox] width or height is zero, perhaps you want to check it out?")
if (!suppressWarning && (width == 0.0 || height == 0.0)) {
println("[Hitbox] width or height is zero ($this), perhaps you want to check it out?")
Thread.currentThread().stackTrace.forEach { println(it) }
}
@@ -125,7 +136,7 @@ class Hitbox(x1: Double, y1: Double, width: Double, height: Double) {
val centeredY: Double
get() = (hitboxStart.y + hitboxEnd.y) * 0.5
fun intersects(position: Point2d) =
infix fun intersects(position: Point2d) =
(position.x >= startX && position.x <= startX + width) &&
(position.y >= startY && position.y <= startY + height)
@@ -134,8 +145,8 @@ class Hitbox(x1: Double, y1: Double, width: Double, height: Double) {
fun clone(): Hitbox = Hitbox(startX, startY, width, height)
companion object {
fun fromTwoPoints(x1: Double, y1: Double, x2: Double, y2: Double) =
Hitbox(x1, y1, x2 - x1, y2 - y1)
fun fromTwoPoints(x1: Double, y1: Double, x2: Double, y2: Double, nowarn: Boolean = false) =
Hitbox(x1, y1, x2 - x1, y2 - y1, nowarn)
}
operator fun minus(other: Hitbox): Vector2 {

View File

@@ -46,7 +46,7 @@ import org.luaj.vm2.*
*/
fun composeActorObject(actor: ActorWBMovable): LuaTable {
val t: LuaTable = LuaTable()
val moveDelta = actor.externalForce + actor.controllerMoveDelta
val moveDelta = actor.externalV + actor.controllerV
t["name"] = actor.actorValue.getAsString(AVKey.NAME).toLua()
t["startX"] = actor.hitbox.centeredX.toLua()

View File

@@ -3,11 +3,14 @@ package net.torvald.terrarum.gamecontroller
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.Input
import com.badlogic.gdx.InputAdapter
import net.torvald.terrarum.AppLoader
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.floorInt
import net.torvald.terrarum.gameactors.AVKey
import net.torvald.terrarum.gameworld.fmod
import net.torvald.terrarum.itemproperties.GameItem
import net.torvald.terrarum.modulebasegame.Ingame
import net.torvald.terrarum.worlddrawer.FeaturesDrawer
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.itemproperties.GameItem
import net.torvald.terrarum.floorInt
import net.torvald.terrarum.worlddrawer.WorldCamera
/**
@@ -40,17 +43,19 @@ class IngameController(val ingame: Ingame) : InputAdapter() {
// Use item: assuming the player has only one effective grip (EquipPosition.HAND_GRIP)
if (ingame.canPlayerControl) {
if (Gdx.input.isButtonPressed(Terrarum.getConfigInt("mouseprimary")) || Gdx.input.isButtonPressed(Terrarum.getConfigInt("mousesecondary"))) {
if (Gdx.input.isButtonPressed(AppLoader.getConfigInt("mouseprimary")) ||
Gdx.input.isButtonPressed(AppLoader.getConfigInt("mousesecondary"))) {
val player = (Terrarum.ingame!! as Ingame).actorNowPlaying
if (player == null) return
val itemOnGrip = player.inventory.itemEquipped[GameItem.EquipPosition.HAND_GRIP]
itemOnGrip?.let {
if (Gdx.input.isButtonPressed(Terrarum.getConfigInt("mouseprimary"))) {
if (Gdx.input.isButtonPressed(AppLoader.getConfigInt("mouseprimary"))) {
player.consumePrimary(it)
}
if (Gdx.input.isButtonPressed(Terrarum.getConfigInt("mousesecondary"))) {
if (Gdx.input.isButtonPressed(AppLoader.getConfigInt("mousesecondary"))) {
player.consumeSecondary(it)
}
}
@@ -67,12 +72,19 @@ class IngameController(val ingame: Ingame) : InputAdapter() {
if (ingame.canPlayerControl) {
ingame.actorNowPlaying?.keyDown(keycode)
}
if (Terrarum.getConfigIntArray("keyquickselalt").contains(keycode)
|| keycode == Terrarum.getConfigInt("keyquicksel")) {
ingame.uiPieMenu.setAsOpen()
ingame.uiQuickBar.setAsClose()
// quickslot by number keys
val quickslotKeys = AppLoader.getConfigIntArray("keyquickslots")
if (keycode in quickslotKeys) {
ingame.actorNowPlaying?.actorValue?.set(AVKey.__PLAYER_QUICKSLOTSEL, quickslotKeys.indexOf(keycode))
}
// pie menu
if (AppLoader.getConfigIntArray("keyquickselalt").contains(keycode)
|| keycode == AppLoader.getConfigInt("keyquicksel")) {
ingame.uiPieMenu.setAsOpen()
ingame.uiQuickBar.setAsClose()
}
}
ingame.uiContainer.forEach { it.keyDown(keycode) } // for KeyboardControlled UIcanvases
@@ -90,8 +102,8 @@ class IngameController(val ingame: Ingame) : InputAdapter() {
}
override fun keyUp(keycode: Int): Boolean {
if (Terrarum.getConfigIntArray("keyquickselalt").contains(keycode)
|| keycode == Terrarum.getConfigInt("keyquicksel")) {
if (AppLoader.getConfigIntArray("keyquickselalt").contains(keycode)
|| keycode == AppLoader.getConfigInt("keyquicksel")) {
ingame.uiPieMenu.setAsClose()
ingame.uiQuickBar.setAsOpen()
}
@@ -118,11 +130,11 @@ class IngameController(val ingame: Ingame) : InputAdapter() {
// fire world click events; the event is defined as Ingame's (or any others') WorldClick event
if (ingame.uiContainer.map { if ((it.isOpening || it.isOpened) && it.mouseUp) 1 else 0 }.sum() == 0) { // no UI on the mouse, right?
if (button == Terrarum.getConfigInt("mouseprimary")) {
ingame.worldPrimaryClickEnd(Terrarum.deltaTime)
if (button == AppLoader.getConfigInt("mouseprimary")) {
ingame.worldPrimaryClickEnd(AppLoader.getSmoothDelta().toFloat())
}
if (button == Terrarum.getConfigInt("mousesecondary")) {
ingame.worldSecondaryClickEnd(Terrarum.deltaTime)
if (button == AppLoader.getConfigInt("mousesecondary")) {
ingame.worldSecondaryClickEnd(AppLoader.getSmoothDelta().toFloat())
}
}
}
@@ -134,6 +146,16 @@ class IngameController(val ingame: Ingame) : InputAdapter() {
}
override fun scrolled(amount: Int): Boolean {
if (ingame.canPlayerControl) {
// quickslot by wheel
if (ingame.actorNowPlaying != null) {
ingame.actorNowPlaying!!.actorValue.set(
AVKey.__PLAYER_QUICKSLOTSEL,
(ingame.actorNowPlaying!!.actorValue.getAsInt(AVKey.__PLAYER_QUICKSLOTSEL)!! - amount) fmod ingame.actorNowPlaying!!.inventory.quickSlot.size
)
}
}
ingame.uiContainer.forEach { it.scrolled(amount) }
return true
}
@@ -149,11 +171,11 @@ class IngameController(val ingame: Ingame) : InputAdapter() {
// fire world click events; the event is defined as Ingame's (or any others') WorldClick event
if (ingame.uiContainer.map { if ((it.isOpening || it.isOpened) && it.mouseUp) 1 else 0 }.sum() == 0) { // no UI on the mouse, right?
if (button == Terrarum.getConfigInt("mouseprimary")) {
ingame.worldPrimaryClickStart(Terrarum.deltaTime)
if (button == AppLoader.getConfigInt("mouseprimary")) {
ingame.worldPrimaryClickStart(AppLoader.getSmoothDelta().toFloat())
}
if (button == Terrarum.getConfigInt("mousesecondary")) {
ingame.worldSecondaryClickStart(Terrarum.deltaTime)
if (button == AppLoader.getConfigInt("mousesecondary")) {
ingame.worldSecondaryClickStart(AppLoader.getSmoothDelta().toFloat())
}
}
}

View File

@@ -20,6 +20,9 @@ object KeyToggler {
return currentState[key]
}
/**
* Put this into the each scene's update/render method.
*/
fun update(gameMode: Boolean = true) {
for (it in 0..255) {
if (gameMode && it in gameKeys &&

View File

@@ -1,9 +1,29 @@
package net.torvald.terrarum.gameworld
import net.torvald.terrarum.blockproperties.Fluid
/**
* Created by minjaesong on 2016-08-06.
*/
object FluidCodex {
const val FLUID_LAVA = 0xFE.toByte()
const val FLUID_WATER = 0xFF.toByte()
}
operator fun get(type: FluidType): FluidProp {
return if (type sameAs Fluid.NULL)
nullProp
else
waterProp
}
// TODO temporary, should read from CSV
val nullProp = FluidProp.getNullProp()
val waterProp = FluidProp()
init {
waterProp.shadeColR = 0.1016f
waterProp.shadeColG = 0.0744f
waterProp.shadeColB = 0.0508f
waterProp.shadeColA = 0.0508f
waterProp.density = 1000
}
}

View File

@@ -0,0 +1,48 @@
package net.torvald.terrarum.gameworld
import com.badlogic.gdx.graphics.Color
import net.torvald.terrarum.blockproperties.Block
import net.torvald.terrarum.blockproperties.BlockCodex
import net.torvald.terrarum.blockproperties.BlockPropUtil
/**
* Created by minjaesong on 2018-12-29.
*/
class FluidProp {
var density: Int = 0
var dynamicLuminosityFunction: Int = 0
/** 1.0f for 1023, 0.25f for 255 */
var shadeColR = 0f
var shadeColG = 0f
var shadeColB = 0f
var shadeColA = 0f
/** 1.0f for 1023, 0.25f for 255 */
var lumColR = 0f
var lumColG = 0f
var lumColB = 0f
var lumColA = 0f
inline val opacity: Color
get() = Color(shadeColR, shadeColG, shadeColB, shadeColA)
inline val luminosity: Color
get() = BlockPropUtil.getDynamicLumFunc(Color(lumColR, lumColG, lumColB, lumColA), dynamicLuminosityFunction)
companion object {
fun getNullProp(): FluidProp {
val p = FluidProp()
p.shadeColR = BlockCodex[Block.AIR].shadeColR
p.shadeColG = BlockCodex[Block.AIR].shadeColG
p.shadeColB = BlockCodex[Block.AIR].shadeColB
p.shadeColA = BlockCodex[Block.AIR].shadeColA
return p
}
}
}

View File

@@ -2,13 +2,16 @@
package net.torvald.terrarum.gameworld
import com.badlogic.gdx.graphics.Color
import net.torvald.terrarum.realestate.LandUtil
import net.torvald.terrarum.blockproperties.Block
import net.torvald.terrarum.blockproperties.BlockCodex
import net.torvald.terrarum.blockproperties.Fluid
import net.torvald.terrarum.modulebasegame.gameworld.WorldSimulator
import net.torvald.terrarum.realestate.LandUtil
import net.torvald.terrarum.serialise.ReadLayerDataLzma
import org.dyn4j.geometry.Vector2
import kotlin.math.absoluteValue
typealias BlockAddress = Long
typealias BlockDamage = Float
open class GameWorld {
@@ -35,15 +38,17 @@ open class GameWorld {
val layerTerrainLowBits: PairedMapLayer
//val layerThermal: MapLayerHalfFloat // in Kelvins
//val layerAirPressure: MapLayerHalfFloat // (milibar - 1000)
//val layerFluidPressure: MapLayerHalfFloat // (milibar - 1000)
/** Tilewise spawn point */
var spawnX: Int
/** Tilewise spawn point */
var spawnY: Int
val wallDamages: HashMap<BlockAddress, BlockDamage>
val terrainDamages: HashMap<BlockAddress, BlockDamage>
val wallDamages: HashMap<BlockAddress, Float>
val terrainDamages: HashMap<BlockAddress, Float>
val fluidTypes: HashMap<BlockAddress, FluidType>
val fluidFills: HashMap<BlockAddress, Float>
//public World physWorld = new World( new Vec2(0, -Terrarum.game.gravitationalAccel) );
//physics
@@ -59,6 +64,8 @@ open class GameWorld {
constructor(worldIndex: Int, width: Int, height: Int, creationTIME_T: Long, lastPlayTIME_T: Long, totalPlayTime: Int) {
if (width <= 0 || height <= 0) throw IllegalArgumentException("Non-positive width/height: ($width, $height)")
this.worldIndex = worldIndex
this.width = width
this.height = height
@@ -72,14 +79,16 @@ open class GameWorld {
layerTerrainLowBits = PairedMapLayer(width, height)
layerWallLowBits = PairedMapLayer(width, height)
wallDamages = HashMap<BlockAddress, BlockDamage>()
terrainDamages = HashMap<BlockAddress, BlockDamage>()
wallDamages = HashMap<BlockAddress, Float>()
terrainDamages = HashMap<BlockAddress, Float>()
fluidTypes = HashMap<BlockAddress, FluidType>()
fluidFills = HashMap<BlockAddress, Float>()
// temperature layer: 2x2 is one cell
//layerThermal = MapLayerHalfFloat(width / 2, height / 2, averageTemperature)
//layerThermal = MapLayerHalfFloat(width, height, averageTemperature)
// air pressure layer: 4 * 8 is one cell
//layerAirPressure = MapLayerHalfFloat(width / 4, height / 8, 13f) // 1013 mBar
// fluid pressure layer: 4 * 8 is one cell
//layerFluidPressure = MapLayerHalfFloat(width, height, 13f) // 1013 mBar
creationTime = creationTIME_T
@@ -98,6 +107,8 @@ open class GameWorld {
wallDamages = layerData.wallDamages
terrainDamages = layerData.terrainDamages
fluidTypes = layerData.fluidTypes
fluidFills = layerData.fluidFills
spawnX = layerData.spawnX
spawnY = layerData.spawnY
@@ -144,9 +155,12 @@ open class GameWorld {
val damageDataArray: ByteArray
get() = layerTerrainLowBits.data
private fun coerceXY(x: Int, y: Int) = (x fmod width) to (y.coerceWorld())
fun getTileFromWall(x: Int, y: Int): Int? {
val wall: Int? = layerWall.getTile(x fmod width, y)
val wallDamage: Int? = getWallLowBits(x fmod width, y)
val (x, y) = coerceXY(x, y)
val wall: Int? = layerWall.getTile(x, y)
val wallDamage: Int? = getWallLowBits(x, y)
return if (wall == null || wallDamage == null)
null
else
@@ -154,8 +168,9 @@ open class GameWorld {
}
fun getTileFromTerrain(x: Int, y: Int): Int? {
val terrain: Int? = layerTerrain.getTile(x fmod width, y)
val terrainDamage: Int? = getTerrainLowBits(x fmod width, y)
val (x, y) = coerceXY(x, y)
val terrain: Int? = layerTerrain.getTile(x, y)
val terrainDamage: Int? = getTerrainLowBits(x, y)
return if (terrain == null || terrainDamage == null)
null
else
@@ -163,15 +178,18 @@ open class GameWorld {
}
fun getTileFromWire(x: Int, y: Int): Int? {
return layerWire.getTile(x fmod width, y)
val (x, y) = coerceXY(x, y)
return layerWire.getTile(x, y)
}
fun getWallLowBits(x: Int, y: Int): Int? {
return layerWallLowBits.getData(x fmod width, y)
val (x, y) = coerceXY(x, y)
return layerWallLowBits.getData(x, y)
}
fun getTerrainLowBits(x: Int, y: Int): Int? {
return layerTerrainLowBits.getData(x fmod width, y)
val (x, y) = coerceXY(x, y)
return layerTerrainLowBits.getData(x, y)
}
/**
@@ -183,7 +201,8 @@ open class GameWorld {
* @param combinedTilenum (tilenum * 16) + damage
*/
fun setTileWall(x: Int, y: Int, combinedTilenum: Int) {
setTileWall(x fmod width, y, (combinedTilenum / PairedMapLayer.RANGE).toByte(), combinedTilenum % PairedMapLayer.RANGE)
val (x, y) = coerceXY(x, y)
setTileWall(x, y, (combinedTilenum / PairedMapLayer.RANGE).toByte(), combinedTilenum % PairedMapLayer.RANGE)
}
/**
@@ -195,23 +214,37 @@ open class GameWorld {
* @param combinedTilenum (tilenum * 16) + damage
*/
fun setTileTerrain(x: Int, y: Int, combinedTilenum: Int) {
setTileTerrain(x fmod width, y, (combinedTilenum / PairedMapLayer.RANGE).toByte(), combinedTilenum % PairedMapLayer.RANGE)
val (x, y) = coerceXY(x, y)
setTileTerrain(x, y, (combinedTilenum / PairedMapLayer.RANGE).toByte(), combinedTilenum % PairedMapLayer.RANGE)
}
fun setTileWall(x: Int, y: Int, tile: Byte, damage: Int) {
layerWall.setTile(x fmod width, y, tile)
layerWallLowBits.setData(x fmod width, y, damage)
val (x, y) = coerceXY(x, y)
layerWall.setTile(x, y, tile)
layerWallLowBits.setData(x, y, damage)
wallDamages.remove(LandUtil.getBlockAddr(this, x, y))
}
/**
* Warning: this function alters fluid lists: be wary of call order!
*/
fun setTileTerrain(x: Int, y: Int, tile: Byte, damage: Int) {
layerTerrain.setTile(x fmod width, y, tile)
layerTerrainLowBits.setData(x fmod width, y, damage)
terrainDamages.remove(LandUtil.getBlockAddr(this, x, y))
val (x, y) = coerceXY(x, y)
layerTerrain.setTile(x, y, tile)
layerTerrainLowBits.setData(x, y, damage)
val blockAddr = LandUtil.getBlockAddr(this, x, y)
terrainDamages.remove(blockAddr)
if (BlockCodex[tile * PairedMapLayer.RANGE + damage].isSolid) {
fluidFills.remove(blockAddr)
fluidTypes.remove(blockAddr)
}
// fluid tiles-item should be modified so that they will also place fluid onto their respective map
}
fun setTileWire(x: Int, y: Int, tile: Byte) {
layerWire.setTile(x fmod width, y, tile)
val (x, y) = coerceXY(x, y)
layerWire.setTile(x, y, tile)
}
fun getTileFrom(mode: Int, x: Int, y: Int): Int? {
@@ -293,6 +326,7 @@ open class GameWorld {
// remove tile from the world
if (terrainDamages[addr] ?: 0f >= BlockCodex[getTileFromTerrain(x, y)].strength) {
setTileTerrain(x, y, 0)
terrainDamages.remove(addr)
return true
}
@@ -321,6 +355,7 @@ open class GameWorld {
// remove tile from the world
if (wallDamages[addr]!! >= BlockCodex[getTileFromWall(x, y)].strength) {
setTileWall(x, y, 0)
wallDamages.remove(addr)
return true
}
@@ -329,30 +364,88 @@ open class GameWorld {
fun getWallDamage(x: Int, y: Int): Float =
wallDamages[LandUtil.getBlockAddr(this, x, y)] ?: 0f
fun setFluid(x: Int, y: Int, fluidType: FluidType, fill: Float) {
/*if (x == 60 && y == 256) {
printdbg(this, "Setting fluid $fill at ($x,$y)")
}*/
if (fluidType == Fluid.NULL && fill != 0f) {
throw Error("Illegal fluid at ($x,$y): ${FluidInfo(fluidType, fill)}")
}
val addr = LandUtil.getBlockAddr(this, x, y)
if (fill > WorldSimulator.FLUID_MIN_MASS) {
//setTileTerrain(x, y, fluidTypeToBlock(fluidType))
fluidFills[addr] = fill
fluidTypes[addr] = fluidType
}
else {
fluidFills.remove(addr)
fluidTypes.remove(addr)
}
/*if (x == 60 && y == 256) {
printdbg(this, "TileTerrain: ${getTileFromTerrain(x, y)}")
printdbg(this, "fluidTypes[$addr] = ${fluidTypes[addr]} (should be ${fluidType.value})")
printdbg(this, "fluidFills[$addr] = ${fluidFills[addr]} (should be $fill)")
}*/
}
fun getFluid(x: Int, y: Int): FluidInfo {
val addr = LandUtil.getBlockAddr(this, x, y)
val fill = fluidFills[addr]
val type = fluidTypes[addr]
return if (type == null) FluidInfo(Fluid.NULL, 0f) else FluidInfo(type, fill!!)
}
private fun fluidTypeToBlock(type: FluidType) = when (type.abs()) {
Fluid.NULL.value -> Block.AIR
in Fluid.fluidRange -> GameWorld.TILES_SUPPORTED - type.abs()
else -> throw IllegalArgumentException("Unsupported fluid type: $type")
}
data class FluidInfo(val type: FluidType, val amount: Float) {
/** test if this fluid should be considered as one */
fun isFluid() = type != Fluid.NULL && amount >= WorldSimulator.FLUID_MIN_MASS
fun getProp() = FluidCodex[type]
override fun toString() = "Fluid type: ${type.value}, amount: $amount"
}
fun getTemperature(worldTileX: Int, worldTileY: Int): Float? {
return null
//return layerThermal.getValue((worldTileX fmod width) / 2, worldTileY / 2)
}
fun getAirPressure(worldTileX: Int, worldTileY: Int): Float? {
return null
//return layerAirPressure.getValue((worldTileX fmod width) / 4, worldTileY / 8)
}
private fun Int.coerceWorld() = this.coerceIn(0, height - 1)
companion object {
@Transient val WALL = 0
@Transient val TERRAIN = 1
@Transient val WIRE = 2
/** 4096 */
@Transient val TILES_SUPPORTED = MapLayer.RANGE * PairedMapLayer.RANGE
@Transient val SIZEOF: Byte = MapLayer.SIZEOF
@Transient val LAYERS: Byte = 4 // terrain, wall (layerTerrainLowBits + layerWallLowBits), wire
fun makeNullWorld() = GameWorld(-1, 1, 1, 0, 0, 0)
}
}
infix fun Int.fmod(other: Int) = Math.floorMod(this, other)
infix fun Float.fmod(other: Float) = if (this >= 0f) this % other else (this % other) + other
inline class FluidType(val value: Int) {
infix fun sameAs(other: FluidType) = this.value.absoluteValue == other.value.absoluteValue
fun abs() = this.value.absoluteValue
}

View File

@@ -11,13 +11,13 @@ import net.torvald.dataclass.Float16Bits
open class MapLayerHalfFloat(val width: Int, val height: Int) : Iterable<Float16Bits> {
constructor(width: Int, height: Int, init: Float) : this(width, height) {
data = Array(height) { Array(width, { Float16.fromFloat(init) }) }
data = Array(height) { Array(width) { Float16.fromFloat(init) } }
}
internal @Volatile var data: Array<Array<Float16Bits>> // in parallel programming: do not trust your register; always read freshly from RAM!
init {
data = Array(height) { Array(width, { 0.toShort() }) }
data = Array(height) { Array(width) { 0.toShort() } }
}
/**

View File

@@ -27,11 +27,13 @@ object TinyAlphNum : BitmapFont() {
return W * str.length
}
lateinit var colourHolder: Color
lateinit var colMain: Color
lateinit var colShadow: Color
override fun draw(batch: Batch, text: CharSequence, x: Float, y: Float): GlyphLayout? {
val originalColour = batch.color
colourHolder = batch.color
val originalColour = batch.color.cpy()
colMain = batch.color.cpy()
colShadow = colMain.cpy().mul(0.5f, 0.5f, 0.5f, 1f)
val x = x.round()
val y = y.round()
@@ -43,16 +45,17 @@ object TinyAlphNum : BitmapFont() {
val cclow = text[index + 1]
val colour = getColour(cchigh, cclow)
colourHolder = colour
colMain = colour
colShadow = colMain.cpy().mul(0.5f, 0.5f, 0.5f, 1f)
}
else if (c in 0.toChar()..255.toChar()) {
batch.color = colourHolder.cpy().mul(0.5f, 0.5f, 0.5f, 1f)
batch.color = colShadow
batch.draw(fontSheet.get(c.toInt() % 16, c.toInt() / 16), x + charsPrinted * W + 1, y)
batch.draw(fontSheet.get(c.toInt() % 16, c.toInt() / 16), x + charsPrinted * W, y + 1)
batch.draw(fontSheet.get(c.toInt() % 16, c.toInt() / 16), x + charsPrinted * W + 1, y + 1)
batch.color = colourHolder.cpy()
batch.color = colMain
batch.draw(fontSheet.get(c.toInt() % 16, c.toInt() / 16), x + charsPrinted * W, y)
charsPrinted += 1

View File

@@ -47,9 +47,10 @@ abstract class GameItem : Comparable<GameItem>, Cloneable {
var nameColour = Color.WHITE
/** In kg */
abstract var baseMass: Double
/** In kg */
abstract var baseToolSize: Double?
abstract var inventoryCategory: String // "weapon", "tool", "armor", etc. (all smallcaps)

View File

@@ -3,12 +3,12 @@ package net.torvald.terrarum.itemproperties
import com.badlogic.gdx.graphics.Texture
import com.badlogic.gdx.graphics.g2d.TextureRegion
import net.torvald.terrarum.KVHashMap
import net.torvald.terrarum.modulebasegame.gameactors.CanBeAnItem
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.blockproperties.Fluid
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.worlddrawer.BlocksDrawer
import net.torvald.terrarum.modulebasegame.Ingame
import net.torvald.terrarum.worlddrawer.FeaturesDrawer.TILE_SIZE
import net.torvald.terrarum.modulebasegame.gameactors.CanBeAnItem
import net.torvald.terrarum.worlddrawer.BlocksDrawer
import java.util.*
/**
@@ -26,18 +26,20 @@ object ItemCodex {
val ITEM_TILES = 0..GameWorld.TILES_SUPPORTED - 1
val ITEM_WALLS = GameWorld.TILES_SUPPORTED..GameWorld.TILES_SUPPORTED * 2 - 1
val ITEM_WIRES = GameWorld.TILES_SUPPORTED * 2..GameWorld.TILES_SUPPORTED * 2 + 255
val ITEM_STATIC = ITEM_WIRES.endInclusive + 1..32767
val ITEM_DYNAMIC = 32768..0x0FFF_FFFF
val ITEM_STATIC = ITEM_WIRES.endInclusive + 1..0x0F_FFFF
val ITEM_DYNAMIC = 0x10_0000..0x0FFF_FFFF
val ACTORID_MIN = ITEM_DYNAMIC.endInclusive + 1
private val itemImagePlaceholder = TextureRegion(Texture("./assets/item_kari_24.tga"))
//private val ingame = Terrarum.ingame!! as Ingame
//private val ingame = Terrarum.ingame!! as Ingame // WARNING you can't put this here, ExceptionInInitializerError
// TODO: when generalised, there's no guarantee that blocks will be used as an item. Write customised item prop loader and init it on the Ingame
init {
//val ingame = Terrarum.ingame!! as Ingame // WARNING you can't put this here, ExceptionInInitializerError
/*println("[ItemCodex] recording item ID ")
@@ -169,6 +171,34 @@ object ItemCodex {
}*/
// test water bucket
itemCodex[9000] = object : GameItem() {
override var dynamicID: ItemID = 9000
override val originalID: ItemID = 9000
override val isUnique: Boolean = true
override val originalName: String = "Infinite Water Bucket"
override var baseMass: Double = 1000.0
override var baseToolSize: Double? = null
override var inventoryCategory: String = "tool"
override var stackable: Boolean = false
override val isDynamic: Boolean = false
override val material: Material = Material(1,1,1,1,1,1,1,1,1,1.0)
override val equipPosition: Int = EquipPosition.HAND_GRIP
override fun startSecondaryUse(delta: Float): Boolean {
val ingame = Terrarum.ingame!! as Ingame // must be in here
ingame.world.setFluid(Terrarum.mouseTileX, Terrarum.mouseTileY, Fluid.WATER, 1f)
return true
}
}
// read from save (if applicable) and fill dynamicItemDescription
@@ -200,7 +230,9 @@ object ItemCodex {
itemCodex[code] = item
}
fun getItemImage(item: GameItem): TextureRegion {
fun getItemImage(item: GameItem?): TextureRegion? {
if (item == null) return null
// terrain
if (item.originalID in ITEM_TILES) {
return BlocksDrawer.tilesTerrain.get(
@@ -211,8 +243,8 @@ object ItemCodex {
// wall
else if (item.originalID in ITEM_WALLS) {
return BlocksDrawer.tileItemWall.get(
(item.originalID.minus(ITEM_WALLS.first) % 16) * TILE_SIZE,
(item.originalID.minus(ITEM_WALLS.first) / 16) * TILE_SIZE
(item.originalID.minus(ITEM_WALLS.first) % 16) * 16,
(item.originalID.minus(ITEM_WALLS.first) / 16)
)
}
// wire

View File

@@ -1,18 +1,22 @@
package net.torvald.terrarum.modulebasegame
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.InputAdapter
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.g2d.SpriteBatch
import net.torvald.terrarum.AppLoader
import net.torvald.terrarum.IngameInstance
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.Yaml
import net.torvald.terrarum.blockproperties.Block
import net.torvald.terrarum.gameactors.*
import net.torvald.terrarum.gamecontroller.KeyToggler
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
import net.torvald.terrarum.modulebasegame.gameworld.GameWorldExtension
import net.torvald.terrarum.modulebasegame.gameworld.WorldTime
import net.torvald.terrarum.modulebasegame.ui.Notification
import net.torvald.terrarum.modulebasegame.ui.UIBuildingMakerToolbox
import net.torvald.terrarum.ui.UICanvas
import net.torvald.terrarum.ui.UINSMenu
import net.torvald.terrarum.worlddrawer.LightmapRenderer
import net.torvald.terrarum.worlddrawer.WorldCamera
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
@@ -23,6 +27,32 @@ import kotlin.system.measureNanoTime
*/
class BuildingMaker(batch: SpriteBatch) : IngameInstance(batch) {
private val menuYaml = Yaml("""
- File
- New
- Export…
- Export sel…
- Import…
- Save world…
- Load world…
- Tool
- Pencil
- Eyedropper
- Select mrq.
- Move
- Undo
- Redo
- Time
- Morning
- Noon
- Dusk
- Night
- Set…
- Weather
- Sunny
- Raining
""".trimIndent())
private val timeNow = System.currentTimeMillis() / 1000
val gameWorld = GameWorldExtension(1, 1024, 256, timeNow, timeNow, 0)
@@ -49,23 +79,29 @@ class BuildingMaker(batch: SpriteBatch) : IngameInstance(batch) {
override var actorNowPlaying: ActorHumanoid? = MovableWorldCamera()
val uiToolbox = UIBuildingMakerToolbox()
val uiToolbox = UINSMenu("Menu", 100, menuYaml)
val notifier = Notification()
val uiContainer = ArrayList<UICanvas>()
val blockPointingCursor = object : ActorWithBody(Actor.RenderOrder.FRONT) {
val blockPointingCursor = object : ActorWithBody(Actor.RenderOrder.OVERLAY) {
override var referenceID: ActorID? = Terrarum.generateUniqueReferenceID(renderOrder)
val body = TextureRegionPack(Gdx.files.internal("assets/graphics/blocks/block_markings_common.tga"), 16, 16)
override val hitbox = Hitbox(0.0, 0.0, 16.0, 16.0)
init {
this.actorValue[AVKey.LUMR] = 1.0
this.actorValue[AVKey.LUMG] = 1.0
}
override fun drawBody(batch: SpriteBatch) {
batch.color = Color.YELLOW
batch.draw(body.get(0, 0), hitbox.startX.toFloat(), hitbox.startY.toFloat())
}
override fun drawGlow(batch: SpriteBatch) { }
override fun dispose() {
body.dispose()
}
@@ -84,20 +120,21 @@ class BuildingMaker(batch: SpriteBatch) : IngameInstance(batch) {
}
}
protected var updateDeltaCounter = 0.0
protected val updateRate = 1.0 / Terrarum.TARGET_INTERNAL_FPS
private val actorsRenderTop = ArrayList<ActorWithBody>()
private val actorsRenderOverlay = ArrayList<ActorWithBody>()
init {
actorsRenderTop.add(blockPointingCursor)
gameWorld.time.setTimeOfToday(WorldTime.HOUR_SEC * 10)
gameWorld.globalLight = Color(.8f,.8f,.8f,.8f)
actorsRenderOverlay.add(blockPointingCursor)
uiContainer.add(uiToolbox)
uiContainer.add(notifier)
uiToolbox.setPosition(Terrarum.WIDTH - 20, 4)
uiToolbox.setPosition(0, 0)
uiToolbox.isVisible = true
notifier.setPosition(
(Terrarum.WIDTH - notifier.width) / 2, Terrarum.HEIGHT - notifier.height)
@@ -109,6 +146,11 @@ class BuildingMaker(batch: SpriteBatch) : IngameInstance(batch) {
LightmapRenderer.fireRecalculateEvent()
}
override fun show() {
Gdx.input.inputProcessor = BuildingMakerController(this)
super.show()
}
override fun render(delta: Float) {
Gdx.graphics.setTitle(Ingame.getCanonicalTitle())
@@ -116,38 +158,16 @@ class BuildingMaker(batch: SpriteBatch) : IngameInstance(batch) {
// ASYNCHRONOUS UPDATE AND RENDER //
/** UPDATE CODE GOES HERE */
updateDeltaCounter += delta
// TODO async update
updateGame(delta)
if (false && Terrarum.getConfigBoolean("multithread")) { // NO MULTITHREADING: camera don't like concurrent modification (jittery actor movements)
// else, NOP;
}
else {
var updateTries = 0
while (updateDeltaCounter >= updateRate) {
//updateGame(delta)
Terrarum.debugTimers["Ingame.update"] = measureNanoTime { updateGame(delta) }
updateDeltaCounter -= updateRate
updateTries++
if (updateTries >= Terrarum.UPDATE_CATCHUP_MAX_TRIES) {
break
}
}
}
/** RENDER CODE GOES HERE */
//renderGame(batch)
Terrarum.debugTimers["Ingame.render"] = measureNanoTime { renderGame() }
// render? just do it anyway
renderGame()
}
private fun updateGame(delta: Float) {
KeyToggler.update(false)
blockPointingCursor.update(delta)
actorNowPlaying?.update(delta)
uiContainer.forEach { it.update(delta) }
@@ -156,18 +176,63 @@ class BuildingMaker(batch: SpriteBatch) : IngameInstance(batch) {
}
private fun renderGame() {
IngameRenderer(world as GameWorldExtension, actorsRenderFront = actorsRenderTop, uisToDraw = uiContainer)
IngameRenderer(world as GameWorldExtension, actorsRenderOverlay = actorsRenderOverlay, uisToDraw = uiContainer)
}
override fun resize(width: Int, height: Int) {
IngameRenderer.resize(Terrarum.WIDTH, Terrarum.HEIGHT)
uiToolbox.setPosition(Terrarum.WIDTH - 20, 4)
uiToolbox.setPosition(0, 0)
notifier.setPosition(
(Terrarum.WIDTH - notifier.width) / 2, Terrarum.HEIGHT - notifier.height)
println("[BuildingMaker] Resize event")
}
override fun dispose() {
IngameRenderer.dispose()
}
}
class BuildingMakerController(val screen: BuildingMaker) : InputAdapter() {
override fun touchUp(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
screen.uiContainer.forEach { it.touchUp(screenX, screenY, pointer, button) }
return true
}
override fun mouseMoved(screenX: Int, screenY: Int): Boolean {
screen.uiContainer.forEach { it.mouseMoved(screenX, screenY) }
return true
}
override fun keyTyped(character: Char): Boolean {
screen.uiContainer.forEach { it.keyTyped(character) }
return true
}
override fun scrolled(amount: Int): Boolean {
screen.uiContainer.forEach { it.scrolled(amount) }
return true
}
override fun keyUp(keycode: Int): Boolean {
screen.uiContainer.forEach { it.keyUp(keycode) }
return true
}
override fun touchDragged(screenX: Int, screenY: Int, pointer: Int): Boolean {
screen.uiContainer.forEach { it.touchDragged(screenX, screenY, pointer) }
return true
}
override fun keyDown(keycode: Int): Boolean {
screen.uiContainer.forEach { it.keyDown(keycode) }
return true
}
override fun touchDown(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
screen.uiContainer.forEach { it.touchDown(screenX, screenY, pointer, button) }
return true
}
}
class MovableWorldCamera : ActorHumanoid(0, usePhysics = false) {

View File

@@ -1,41 +1,41 @@
package net.torvald.terrarum.modulebasegame
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.graphics.*
import com.badlogic.gdx.graphics.Camera
import com.badlogic.gdx.graphics.g2d.SpriteBatch
import net.torvald.dataclass.CircularArray
import net.torvald.terrarum.*
import net.torvald.terrarum.AppLoader.printdbg
import net.torvald.terrarum.blockproperties.BlockPropUtil
import net.torvald.terrarum.blockstats.BlockStats
import net.torvald.terrarum.concurrent.ThreadParallel
import net.torvald.terrarum.gameactors.*
import net.torvald.terrarum.modulebasegame.gameactors.physicssolver.CollisionSolver
import net.torvald.terrarum.console.Authenticator
import net.torvald.terrarum.gameactors.Actor
import net.torvald.terrarum.gameactors.ActorWithBody
import net.torvald.terrarum.gamecontroller.IngameController
import net.torvald.terrarum.gamecontroller.KeyToggler
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.modulebasegame.gameworld.WorldSimulator
import net.torvald.terrarum.modulebasegame.weather.WeatherMixer
import net.torvald.terrarum.worlddrawer.FeaturesDrawer
import net.torvald.terrarum.worlddrawer.LightmapRenderer
import net.torvald.terrarum.worlddrawer.WorldCamera
import java.util.ArrayList
import java.util.concurrent.locks.ReentrantLock
import net.torvald.terrarum.*
import net.torvald.terrarum.AppLoader.printdbg
import net.torvald.terrarum.itemproperties.GameItem
import net.torvald.terrarum.modulebasegame.console.AVTracker
import net.torvald.terrarum.modulebasegame.console.ActorsList
import net.torvald.terrarum.console.Authenticator
import net.torvald.terrarum.itemproperties.GameItem
import net.torvald.terrarum.modulebasegame.gameactors.*
import net.torvald.terrarum.modulebasegame.gameactors.physicssolver.CollisionSolver
import net.torvald.terrarum.modulebasegame.gameworld.GameWorldExtension
import net.torvald.terrarum.modulebasegame.gameworld.WorldSimulator
import net.torvald.terrarum.modulebasegame.imagefont.Watch7SegMain
import net.torvald.terrarum.modulebasegame.imagefont.WatchDotAlph
import net.torvald.terrarum.modulebasegame.ui.*
import net.torvald.terrarum.ui.*
import net.torvald.terrarum.modulebasegame.weather.WeatherMixer
import net.torvald.terrarum.modulebasegame.worldgenerator.RoguelikeRandomiser
import net.torvald.terrarum.modulebasegame.worldgenerator.WorldGenerator
import net.torvald.terrarum.ui.BasicDebugInfoWindow
import net.torvald.terrarum.ui.ConsoleWindow
import net.torvald.terrarum.ui.UICanvas
import net.torvald.terrarum.worlddrawer.FeaturesDrawer
import net.torvald.terrarum.worlddrawer.LightmapRenderer
import net.torvald.terrarum.worlddrawer.WorldCamera
import java.util.*
import java.util.concurrent.locks.ReentrantLock
import kotlin.system.measureNanoTime
@@ -47,14 +47,14 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
private val ACTOR_UPDATE_RANGE = 4096
lateinit var historicalFigureIDBucket: ArrayList<Int>
var historicalFigureIDBucket: ArrayList<Int> = ArrayList<Int>()
/**
* list of Actors that is sorted by Actors' referenceID
*/
//val ACTORCONTAINER_INITIAL_SIZE = 64
val PARTICLES_MAX = Terrarum.getConfigInt("maxparticles")
val PARTICLES_MAX = AppLoader.getConfigInt("maxparticles")
//val actorContainer = ArrayList<Actor>(ACTORCONTAINER_INITIAL_SIZE)
//val actorContainerInactive = ArrayList<Actor>(ACTORCONTAINER_INITIAL_SIZE)
val particlesContainer = CircularArray<ParticleBase>(PARTICLES_MAX)
@@ -64,7 +64,13 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
private val actorsRenderMiddle = ArrayList<ActorWithBody>(ACTORCONTAINER_INITIAL_SIZE)
private val actorsRenderMidTop = ArrayList<ActorWithBody>(ACTORCONTAINER_INITIAL_SIZE)
private val actorsRenderFront = ArrayList<ActorWithBody>(ACTORCONTAINER_INITIAL_SIZE)
private val actorsRenderOverlay= ArrayList<ActorWithBody>(ACTORCONTAINER_INITIAL_SIZE)
private var visibleActorsRenderBehind: List<ActorWithBody> = ArrayList(1)
private var visibleActorsRenderMiddle: List<ActorWithBody> = ArrayList(1)
private var visibleActorsRenderMidTop: List<ActorWithBody> = ArrayList(1)
private var visibleActorsRenderFront: List<ActorWithBody> = ArrayList(1)
private var visibleActorsRenderOverlay: List<ActorWithBody> = ArrayList(1)
//var screenZoom = 1.0f // definition moved to IngameInstance
//val ZOOM_MAXIMUM = 4.0f // definition moved to IngameInstance
@@ -79,8 +85,12 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
}
fun getCanonicalTitle() = AppLoader.GAME_NAME +
" — F: ${Gdx.graphics.framesPerSecond} (Δt${Terrarum.updateRateStr} / RT${Terrarum.renderRateStr})" +
" — M: J${Terrarum.memJavaHeap}M / N${Terrarum.memNativeHeap}M / X${Terrarum.memXmx}M"
" — F: ${Gdx.graphics.framesPerSecond}" +
if (AppLoader.IS_DEVELOPMENT_BUILD)
" (ΔF${Terrarum.updateRateStr})" +
" — M: J${Terrarum.memJavaHeap}M / N${Terrarum.memNativeHeap}M / X${Terrarum.memXmx}M"
else
""
}
@@ -111,11 +121,11 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
// UI aliases
lateinit var uiAliases: ArrayList<UICanvas>
private set
lateinit var uiAlasesPausing: ArrayList<UICanvas>
lateinit var uiAliasesPausing: ArrayList<UICanvas>
private set
inline val paused: Boolean
get() = uiAlasesPausing.map { if (it.isOpened) return true else 0 }.isEmpty() // isEmply is always false, which we want
get() = uiAliasesPausing.map { if (it.isOpened) return true else 0 }.isEmpty() // isEmpty is always false, which we want
/**
* Set to false if UI is opened; set to true if UI is closed.
*/
@@ -132,10 +142,10 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
//private val ingameDrawThread: ThreadIngameDraw // draw must be on the main thread
var gameInitialised = false
private set
var gameFullyLoaded = false
private set
override var gameInitialised = false
internal set
override var gameFullyLoaded = false
internal set
private val TILE_SIZEF = FeaturesDrawer.TILE_SIZE.toFloat()
@@ -168,7 +178,8 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
//BlocksDrawer.world = this.world
FeaturesDrawer.world = this.world
gameInitialised = true
super.show() // gameInitialised = true
}
data class GameSaveData(
@@ -245,22 +256,6 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
historicalFigureIDBucket = ArrayList<Int>()
// add new player and put it to actorContainer
//playableActorDelegate = PlayableActorDelegate(PlayerBuilderSigrid())
//playableActorDelegate = PlayableActorDelegate(PlayerBuilderTestSubject1())
//addNewActor(player)
// test actor
//addNewActor(PlayerBuilderCynthia())
// it won't work:
//setTheRealGamerFirstTime(PlayerBuilderSigrid())
// because NO GL CONTEXT IN THIS THREAD, might want 'postInit()'?
}
}
@@ -268,7 +263,8 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
/** Load rest of the game with GL context */
fun postInit() {
setTheRealGamerFirstTime(PlayerBuilderSigrid())
//setTheRealGamerFirstTime(PlayerBuilderSigrid())
setTheRealGamerFirstTime(PlayerBuilderTestSubject1())
@@ -303,25 +299,25 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
width = 900,
height = Terrarum.HEIGHT - 160,
categoryWidth = 210,
toggleKeyLiteral = Terrarum.getConfigInt("keyinventory")
toggleKeyLiteral = AppLoader.getConfigInt("keyinventory")
)*/
/*uiInventoryPlayer.setPosition(
-uiInventoryPlayer.width,
70
)*/
uiInventoryPlayer = UIInventoryFull(actorNowPlaying,
toggleKeyLiteral = Terrarum.getConfigInt("keyinventory")
toggleKeyLiteral = AppLoader.getConfigInt("keyinventory")
)
uiInventoryPlayer.setPosition(0, 0)
// >- lesser UIs -<
// quick bar
uiQuickBar = UIQuickBar()
uiQuickBar = UIQuickslotBar()
uiQuickBar.isVisible = true
uiQuickBar.setPosition((Terrarum.WIDTH - uiQuickBar.width) / 2 + 12, -10)
uiQuickBar.setPosition((Terrarum.WIDTH - uiQuickBar.width) / 2, 8)
// pie menu
uiPieMenu = UIPieMenu()
uiPieMenu = uiQuickslotPie()
uiPieMenu.setPosition(Terrarum.HALFW, Terrarum.HALFH)
// vital metre
@@ -364,13 +360,13 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
uiTooltip
// drawn last
)
uiAlasesPausing = arrayListOf(
uiAliasesPausing = arrayListOf(
uiInventoryPlayer,
//uiInventoryContainer,
consoleHandler,
uiCheatMotherfuckerNootNoot
)
uiAlasesPausing.forEach { addUI(it) } // put them all to the UIContainer
uiAliasesPausing.forEach { addUI(it) } // put them all to the UIContainer
uiAliases.forEach { addUI(it) } // put them all to the UIContainer
@@ -388,6 +384,7 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
LightmapRenderer.fireRecalculateEvent()
AppLoader.debugTimers["Ingame.updateCounter"] = 0
@@ -417,9 +414,6 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
itemOnGrip?.endSecondaryUse(delta)
}
protected var updateDeltaCounter = 0.0
protected val renderRate = Terrarum.renderRate
private var firstTimeRun = true
///////////////
@@ -427,19 +421,13 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
///////////////
private class ThreadIngameUpdate(val ingame: Ingame): Runnable {
override fun run() {
var updateTries = 0
while (ingame.updateDeltaCounter >= ingame.renderRate) {
ingame.updateGame(Terrarum.deltaTime)
ingame.updateDeltaCounter -= ingame.renderRate
updateTries++
if (updateTries >= Terrarum.UPDATE_CATCHUP_MAX_TRIES) {
break
}
}
TODO()
}
}
private var countdownToDeltaReset = 15 // number of frames
private var updateAkku = 0.0
override fun render(delta: Float) {
// Q&D solution for LoadScreen and Ingame, where while LoadScreen is working, Ingame now no longer has GL Context
// there's still things to load which needs GL context to be present
@@ -460,49 +448,34 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
}
if (countdownToDeltaReset >= 0) {
if (countdownToDeltaReset == 0) {
AppLoader.resetDeltaSmoothingHistory()
}
countdownToDeltaReset -= 1
}
//Gdx.graphics.setTitle(getCanonicalTitle())
// ASYNCHRONOUS UPDATE AND RENDER //
/** UPDATE CODE GOES HERE */
updateDeltaCounter += delta
val dt = AppLoader.getSmoothDelta()
updateAkku += dt
if (false && Terrarum.getConfigBoolean("multithread")) { // NO MULTITHREADING: camera don't like concurrent modification (jittery actor movements)
if (firstTimeRun || updateThreadWrapper.state == Thread.State.TERMINATED) {
updateThreadWrapper = Thread(ingameUpdateThread, "Terrarum UpdateThread")
updateThreadWrapper.start()
if (firstTimeRun) firstTimeRun = false
}
// else, NOP;
}
else {
var updateTries = 0
while (updateDeltaCounter >= renderRate) {
//updateGame(delta)
Terrarum.debugTimers["Ingame.update"] = measureNanoTime { updateGame(delta) }
updateDeltaCounter -= renderRate
updateTries++
if (updateTries >= Terrarum.UPDATE_CATCHUP_MAX_TRIES) {
break
}
}
var i = 0L
while (updateAkku >= delta) {
AppLoader.debugTimers["Ingame.update"] = measureNanoTime { updateGame(delta) }
updateAkku -= delta
i += 1
}
AppLoader.debugTimers["Ingame.updateCounter"] = i
/** RENDER CODE GOES HERE */
//renderGame(batch)
Terrarum.debugTimers["Ingame.render"] = measureNanoTime { renderGame() }
AppLoader.debugTimers["Ingame.render"] = measureNanoTime { renderGame() }
AppLoader.debugTimers["Ingame.render-Light"] =
(AppLoader.debugTimers["Ingame.render"] as Long) - ((AppLoader.debugTimers["Renderer.LightTotal"] as? Long) ?: 0)
}
protected fun updateGame(delta: Float) {
@@ -522,7 +495,7 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
///////////////////////////
BlockPropUtil.dynamicLumFuncTickClock()
world.updateWorldTime(delta)
//WorldSimulator(player, delta)
WorldSimulator.invoke(actorNowPlaying, delta)
WeatherMixer.update(delta, actorNowPlaying, world)
BlockStats.update()
@@ -549,6 +522,13 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
particlesContainer.forEach { if (!it.flagDespawn) particlesActive++; it.update(delta) }
// TODO thread pool(?)
CollisionSolver.process()
visibleActorsRenderBehind = actorsRenderBehind.filter { it.inScreen() }
visibleActorsRenderMiddle = actorsRenderMiddle.filter { it.inScreen() }
visibleActorsRenderMidTop = actorsRenderMidTop.filter { it.inScreen() }
visibleActorsRenderFront = actorsRenderFront.filter { it.inScreen() }
visibleActorsRenderOverlay=actorsRenderOverlay.filter { it.inScreen() }
}
@@ -568,12 +548,15 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
private fun renderGame() {
Gdx.graphics.setTitle(getCanonicalTitle())
IngameRenderer.invoke(
world as GameWorldExtension,
actorsRenderBehind,
actorsRenderMiddle,
actorsRenderMidTop,
actorsRenderFront,
visibleActorsRenderBehind,
visibleActorsRenderMiddle,
visibleActorsRenderMidTop,
visibleActorsRenderFront,
visibleActorsRenderOverlay,
particlesContainer,
actorNowPlaying,
uiContainer
@@ -598,7 +581,7 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
}
actorNowPlaying = newActor
WorldSimulator(actorNowPlaying, Terrarum.deltaTime)
//WorldSimulator(actorNowPlaying, AppLoader.getSmoothDelta().toFloat())
}
private fun changePossession(refid: Int) {
@@ -782,6 +765,10 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
val i = actorsRenderFront.binarySearch(actor.referenceID!!)
actorsRenderFront.removeAt(i)
}
Actor.RenderOrder.OVERLAY-> {
val i = actorsRenderOverlay.binarySearch(actor.referenceID!!)
actorsRenderFront.removeAt(i)
}
}
}
}
@@ -817,6 +804,9 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
Actor.RenderOrder.FRONT -> {
actorsRenderFront.add(actor); insertionSortLastElemAV(actorsRenderFront)
}
Actor.RenderOrder.OVERLAY-> {
actorsRenderOverlay.add(actor); insertionSortLastElemAV(actorsRenderOverlay)
}
}
}
}
@@ -848,6 +838,9 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
Actor.RenderOrder.FRONT -> {
actorsRenderFront.add(actor); insertionSortLastElemAV(actorsRenderFront)
}
Actor.RenderOrder.OVERLAY-> {
actorsRenderOverlay.add(actor); insertionSortLastElemAV(actorsRenderOverlay)
}
}
}
}
@@ -869,7 +862,7 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
}
private fun insertionSortLastElemAV(arr: ArrayList<ActorWithBody>) { // out-projection doesn't work, duh
lock(ReentrantLock()) {
ReentrantLock().lock {
var j = arr.lastIndex - 1
val x = arr.last()
while (j >= 0 && arr[j] > x) {
@@ -954,16 +947,17 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
actorsRenderMiddle.forEach { it.dispose() }
actorsRenderMidTop.forEach { it.dispose() }
actorsRenderFront.forEach { it.dispose() }
actorsRenderOverlay.forEach { it.dispose() }
uiAliases.forEach { it.dispose() }
uiAlasesPausing.forEach { it.dispose() }
uiAliasesPausing.forEach { it.dispose() }
WatchDotAlph.dispose()
Watch7SegMain.dispose()
WatchDotAlph.dispose()
ItemSlotImageBuilder.dispose()
ItemSlotImageFactory.dispose()
MessageWindow.SEGMENT_BLACK.dispose()
MessageWindow.SEGMENT_WHITE.dispose()
@@ -975,4 +969,5 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
printdbg(this, "-> $it")
}
}
}

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