mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-06 08:38:30 +09:00
Compare commits
97 Commits
v0.3.2-tes
...
v0.3.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c701519cb9 | ||
|
|
75e6669d49 | ||
|
|
18631064d4 | ||
|
|
9fe6618cc9 | ||
|
|
7b8d6d6913 | ||
|
|
385a882937 | ||
|
|
c73461a407 | ||
|
|
f7e4987785 | ||
|
|
78bd88858b | ||
|
|
d2b1346252 | ||
|
|
fb28fd8a76 | ||
|
|
36d25c6479 | ||
|
|
2ade76147c | ||
|
|
59d9adbbd1 | ||
|
|
821c7c77d8 | ||
|
|
3308f09e08 | ||
|
|
37d45e22ad | ||
|
|
1ac861fa82 | ||
|
|
451808cd1c | ||
|
|
0c00b3b7cc | ||
|
|
1669f7fdd0 | ||
|
|
f4bfe84009 | ||
|
|
91cf08e93a | ||
|
|
33a8112454 | ||
|
|
439cde09fc | ||
|
|
2a62435712 | ||
|
|
5495552db5 | ||
|
|
e04d0284bb | ||
|
|
ad601ffd7e | ||
|
|
987ec1fd98 | ||
|
|
4fb30821f1 | ||
|
|
a73c536941 | ||
|
|
4c1f16fe91 | ||
|
|
6df78b59a9 | ||
|
|
28c4d8f11b | ||
|
|
cdfc86398c | ||
|
|
91d94d2dab | ||
|
|
0af2e57368 | ||
|
|
fbce707cac | ||
|
|
9d7bd37394 | ||
|
|
df8bcf79af | ||
|
|
e328457259 | ||
|
|
9baec6c7a1 | ||
|
|
d05364f43f | ||
|
|
e7ed3d8eae | ||
|
|
da6da79186 | ||
|
|
0767521441 | ||
|
|
30aca57cbc | ||
|
|
e512c6c7ad | ||
|
|
6ebf79a8e3 | ||
|
|
e5d5feeb38 | ||
|
|
8e9d2371c8 | ||
|
|
1f5d032ad8 | ||
|
|
7993ccd2e5 | ||
|
|
c77f1ffd23 | ||
|
|
4eb7a8a77e | ||
|
|
10f92a11a9 | ||
|
|
c5659e2833 | ||
|
|
173f99f87d | ||
|
|
64e05a4f17 | ||
|
|
c033260ec5 | ||
|
|
22191bd377 | ||
|
|
79f19120f2 | ||
|
|
d96b7d1b84 | ||
|
|
2b62b4f413 | ||
|
|
f0fa5830bd | ||
|
|
ec24dc9870 | ||
|
|
6bc3d0e6ad | ||
|
|
64c610e77e | ||
|
|
b25ea9654c | ||
|
|
b6b98562a2 | ||
|
|
c93b70f537 | ||
|
|
fb67b0ef5a | ||
|
|
7c7b3de68d | ||
|
|
71df31b93d | ||
|
|
9b24014191 | ||
|
|
02308a7918 | ||
|
|
03c6061a12 | ||
|
|
325e67f999 | ||
|
|
211f936bd3 | ||
|
|
1f6fa49d19 | ||
|
|
13810fc09b | ||
|
|
f95bc36c98 | ||
|
|
d507d84950 | ||
|
|
b31da6ffec | ||
|
|
3593894c0f | ||
|
|
c28b286553 | ||
|
|
c0a3da1b66 | ||
|
|
02cf5fdce5 | ||
|
|
1e6f51e16c | ||
|
|
c61c169048 | ||
|
|
5c58c3006b | ||
|
|
742cabb81f | ||
|
|
07d5e571d6 | ||
|
|
305242045f | ||
|
|
67388999f0 | ||
|
|
b0cc1180bb |
BIN
assets/clut/skybox.png
LFS
Normal file
BIN
assets/clut/skybox.png
LFS
Normal file
Binary file not shown.
BIN
assets/graphics/astrum.png
LFS
Normal file
BIN
assets/graphics/astrum.png
LFS
Normal file
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.
@@ -379,11 +379,11 @@ let isDiacritics = (s) => s !== undefined && inRange(s.charCodeAt(0), 0x0300, 0x
|
|||||||
return Object.freeze({"n":"\uDBBF\uDFC1Бъл. Многоезична\uDBBF\uDFC0","v":"none","c":"CuriousTo\uA75Bvald","m":"rewrite",
|
return Object.freeze({"n":"\uDBBF\uDFC1Бъл. Многоезична\uDBBF\uDFC0","v":"none","c":"CuriousTo\uA75Bvald","m":"rewrite",
|
||||||
"t":dislplayKeyLayouts,
|
"t":dislplayKeyLayouts,
|
||||||
"l":"bgBG",
|
"l":"bgBG",
|
||||||
// return: [displayed output, composed output]
|
// return: [delete count, composed output]
|
||||||
"accept":(headkey,shiftin,altgrin)=>{
|
"accept":(headkey,shiftin,altgrin)=>{
|
||||||
let layer = 1*shiftin + 2*altgrin
|
let layer = 1*shiftin + 2*altgrin
|
||||||
|
|
||||||
let s = states.keylayouts[headkey][layer]
|
let s = (states.keylayouts[headkey][layer] || states.keylayouts[headkey][1*shiftin]) || states.keylayouts[headkey][0]
|
||||||
|
|
||||||
// typing seq for diacritics: diacritics THEN a character
|
// typing seq for diacritics: diacritics THEN a character
|
||||||
if (isDiacritics(s)) {
|
if (isDiacritics(s)) {
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ let isDiacritics = (s) => s !== undefined && inRange(s.charCodeAt(0), 0x0300, 0x
|
|||||||
return Object.freeze({"n":"Ελ. Φωνητικό","v":"none","c":"CuriousTo\uA75Bvald","m":"rewrite",
|
return Object.freeze({"n":"Ελ. Φωνητικό","v":"none","c":"CuriousTo\uA75Bvald","m":"rewrite",
|
||||||
"tf":states.layouttable,
|
"tf":states.layouttable,
|
||||||
"l":"elGR",
|
"l":"elGR",
|
||||||
// return: [displayed output, composed output]
|
// return: [delete count, composed output]
|
||||||
"accept":(headkey,shiftin,altgrin,lowlayerkey)=>{
|
"accept":(headkey,shiftin,altgrin,lowlayerkey)=>{
|
||||||
let layer = 1*shiftin + 2*altgrin
|
let layer = 1*shiftin + 2*altgrin
|
||||||
|
|
||||||
|
|||||||
283
assets/keylayout/hi_in_inscript.ime
Normal file
283
assets/keylayout/hi_in_inscript.ime
Normal file
@@ -0,0 +1,283 @@
|
|||||||
|
let states = {"keylayouts":[[""],[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
["0",")","\u0966",")"],
|
||||||
|
["1","\u090D","\u0967","!"],
|
||||||
|
["2","\u0945","\u0968","@"],
|
||||||
|
["3","\u094D\u0930","\u0969","#"],
|
||||||
|
["4","\u0930\u094D","\u096A","$"],
|
||||||
|
["5","\u091C\u094D\u091E","\u096B","%"],
|
||||||
|
["6","\u0924\u094D\u0930","\u096C","^"],
|
||||||
|
["7","\u0915\u094D\u0937","\u096D","&"],
|
||||||
|
["8","\u0936\u094D\u0930","\u096E","*"],
|
||||||
|
["9","(","\u096F","("],
|
||||||
|
["*"],
|
||||||
|
["#"],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
["\u094B","\u0913"],
|
||||||
|
["\u0935","\u0934"],
|
||||||
|
["\u092E","\u0923","\u0954","\u0923"],
|
||||||
|
["\u094D","\u0905"],
|
||||||
|
["\u093E","\u0906"],
|
||||||
|
["\u093F","\u0907","\u0962","\u090C"],
|
||||||
|
["\u0941","\u0909"],
|
||||||
|
["\u092A","\u092B","\u092A","\u095E"],
|
||||||
|
["\u0917","\u0918","\u095A","\u0918"],
|
||||||
|
["\u0930","\u0931"],
|
||||||
|
["\u0915","\u0916","\u0958","\u0959"],
|
||||||
|
["\u0924","\u0925"],
|
||||||
|
["\u0938","\u0936"],
|
||||||
|
["\u0932","\u0933"],
|
||||||
|
["\u0926","\u0927"],
|
||||||
|
["\u091C","\u091D","\u095B","\u091D"],
|
||||||
|
["\u094C","\u0914"],
|
||||||
|
["\u0940","\u0908","\u0963","\u0961"],
|
||||||
|
["\u0947","\u090F"],
|
||||||
|
["\u0942","\u090A"],
|
||||||
|
["\u0939","\u0919"],
|
||||||
|
["\u0928","\u0929"],
|
||||||
|
["\u0948","\u0910"],
|
||||||
|
["\u0902","\u0901","\u0902","\u0950"],
|
||||||
|
["\u092C","\u092D"],
|
||||||
|
["\u0946","\u090E","\u0953","\u090E"],
|
||||||
|
[",","\u0937","\u0970","\u0970"],
|
||||||
|
[".","\u0964","\u0965","\u093D"],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[" "],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
["\n"],
|
||||||
|
["\x08"],
|
||||||
|
["\u094A","\u0912"],
|
||||||
|
["-","\u0903"],
|
||||||
|
["\u0943","\u090B","\u0944","\u0960"],
|
||||||
|
["\u0921","\u0922","\u095C","\u095D"],
|
||||||
|
["\u093C","\u091E"],
|
||||||
|
["\u0949","\u0911"],
|
||||||
|
["\u091A","\u091B","\u0952","\u091B"],
|
||||||
|
["\u091F","\u0920","\u0951","\u0920"],
|
||||||
|
["\u092F","\u095F"],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
["0"],
|
||||||
|
["1"],
|
||||||
|
["2"],
|
||||||
|
["3"],
|
||||||
|
["4"],
|
||||||
|
["5"],
|
||||||
|
["6"],
|
||||||
|
["7"],
|
||||||
|
["8"],
|
||||||
|
["9"],
|
||||||
|
["/"],
|
||||||
|
["*"],
|
||||||
|
["-"],
|
||||||
|
["+"],
|
||||||
|
["."],
|
||||||
|
["."],
|
||||||
|
["\n"],
|
||||||
|
["="],
|
||||||
|
["("],
|
||||||
|
[")"],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined]
|
||||||
|
],
|
||||||
|
"code":""} // practically unused as long as there are no diacritics on the keyboard
|
||||||
|
let reset = () => {
|
||||||
|
states.code = 0
|
||||||
|
}
|
||||||
|
let inRange = (s,a,b) => (a <= s && s <= b)
|
||||||
|
return Object.freeze({"n":"इनस्क्रिप्ट","v":"none","c":"CuriousTo\uA75Bvald","m":"rewrite",
|
||||||
|
"t":states.keylayouts.slice(0,10).concat([["3","\uDBBF\uDE01\u094D\u0930","\u0969","#"], ["4","\u0930\u094D\uDBBF\uDE01","\u096A","$"]], states.keylayouts.slice(12)),
|
||||||
|
"l":"hiIN",
|
||||||
|
// return: [delete count, composed output]
|
||||||
|
"accept":(headkey,shiftin,altgrin)=>{
|
||||||
|
let layer = 1*shiftin + 2*altgrin
|
||||||
|
|
||||||
|
let s = (states.keylayouts[headkey][layer] || states.keylayouts[headkey][1*shiftin]) || states.keylayouts[headkey][0]
|
||||||
|
|
||||||
|
return ['0', s]
|
||||||
|
},
|
||||||
|
"backspace":()=>{
|
||||||
|
reset()
|
||||||
|
return ''
|
||||||
|
},
|
||||||
|
"end":()=>{
|
||||||
|
reset()
|
||||||
|
return ''
|
||||||
|
},
|
||||||
|
"reset":()=>{ reset() },
|
||||||
|
"composing":()=>(states.code!='')
|
||||||
|
})
|
||||||
@@ -346,12 +346,12 @@ let bufDebugStringify = (buf) => [0,1,2].map(i => (buf[i] == undefined) ? "·" :
|
|||||||
return Object.freeze({"n":"두벌식 표준","v":"none","c":"CuriousTo\uA75Bvald","m":"rewrite",
|
return Object.freeze({"n":"두벌식 표준","v":"none","c":"CuriousTo\uA75Bvald","m":"rewrite",
|
||||||
"t":states.keylayouts.map(it => [it[0],it[1]]),
|
"t":states.keylayouts.map(it => [it[0],it[1]]),
|
||||||
"l":"koKR",
|
"l":"koKR",
|
||||||
// return: [displayed output, composed output]
|
// return: [delete count, composed output]
|
||||||
"accept":(headkey,shiftin,altgrin)=>{
|
"accept":(headkey,shiftin,altgrin)=>{
|
||||||
let layer = 1*shiftin// + 2*altgrin
|
let layer = 1*shiftin// + 2*altgrin
|
||||||
states.code = 1
|
states.code = 1
|
||||||
|
|
||||||
let s = states.keylayouts[headkey][layer]
|
let s = states.keylayouts[headkey][layer] || states.keylayouts[headkey][0]
|
||||||
|
|
||||||
if (isHangul(s)) {
|
if (isHangul(s)) {
|
||||||
let bufIndex = (isJongseongConsonant(s) && isConsonant(states.buf[0]) && undefined !== states.buf[1]) ? 2 :
|
let bufIndex = (isJongseongConsonant(s) && isConsonant(states.buf[0]) && undefined !== states.buf[1]) ? 2 :
|
||||||
|
|||||||
@@ -346,12 +346,12 @@ let bufDebugStringify = (buf) => [0,1,2].map(i => (buf[i] == undefined) ? "·" :
|
|||||||
return Object.freeze({"n":"두벌식 수정 표준","v":"none","c":"CuriousTo\uA75Bvald","m":"rewrite",
|
return Object.freeze({"n":"두벌식 수정 표준","v":"none","c":"CuriousTo\uA75Bvald","m":"rewrite",
|
||||||
"t":states.keylayouts.map(it => [it[0],it[1]]),
|
"t":states.keylayouts.map(it => [it[0],it[1]]),
|
||||||
"l":"koKR",
|
"l":"koKR",
|
||||||
// return: [displayed output, composed output]
|
// return: [delete count, composed output]
|
||||||
"accept":(headkey,shiftin,altgrin)=>{
|
"accept":(headkey,shiftin,altgrin)=>{
|
||||||
let layer = 1*shiftin// + 2*altgrin
|
let layer = 1*shiftin// + 2*altgrin
|
||||||
states.code = 1
|
states.code = 1
|
||||||
|
|
||||||
let s = states.keylayouts[headkey][layer]
|
let s = states.keylayouts[headkey][layer] || states.keylayouts[headkey][0]
|
||||||
|
|
||||||
if (isHangul(s)) {
|
if (isHangul(s)) {
|
||||||
let bufIndex = (isJongseongConsonant(s) && isConsonant(states.buf[0]) && undefined !== states.buf[1]) ? 2 :
|
let bufIndex = (isJongseongConsonant(s) && isConsonant(states.buf[0]) && undefined !== states.buf[1]) ? 2 :
|
||||||
|
|||||||
@@ -375,12 +375,12 @@ let bufDebugStringify = (buf) => [0,1,2].map(i => (buf[i] == undefined) ? "·" :
|
|||||||
return Object.freeze({"n":"세벌식 3-90","v":"none","c":"CuriousTo\uA75Bvald","m":"rewrite",
|
return Object.freeze({"n":"세벌식 3-90","v":"none","c":"CuriousTo\uA75Bvald","m":"rewrite",
|
||||||
"t":states.keylayouts.map(it => [it[0],it[1]]),
|
"t":states.keylayouts.map(it => [it[0],it[1]]),
|
||||||
"l":"koKR",
|
"l":"koKR",
|
||||||
// return: [displayed output, composed output]
|
// return: [delete count, composed output]
|
||||||
"accept":(headkey,shiftin,altgrin)=>{
|
"accept":(headkey,shiftin,altgrin)=>{
|
||||||
let layer = 1*shiftin// + 2*altgrin
|
let layer = 1*shiftin// + 2*altgrin
|
||||||
states.code = 1
|
states.code = 1
|
||||||
|
|
||||||
let s = states.keylayouts[headkey][layer]
|
let s = states.keylayouts[headkey][layer] || states.keylayouts[headkey][0]
|
||||||
let bufIndex = isJungseong(s) ? 1 : isJongseong(s) ? 2 : 0
|
let bufIndex = isJungseong(s) ? 1 : isJongseong(s) ? 2 : 0
|
||||||
|
|
||||||
if (isHangul(s)) {
|
if (isHangul(s)) {
|
||||||
|
|||||||
@@ -375,12 +375,12 @@ let bufDebugStringify = (buf) => [0,1,2].map(i => (buf[i] == undefined) ? "·" :
|
|||||||
return Object.freeze({"n":"세벌식 공자판","v":"none","c":"CuriousTo\uA75Bvald","m":"rewrite",
|
return Object.freeze({"n":"세벌식 공자판","v":"none","c":"CuriousTo\uA75Bvald","m":"rewrite",
|
||||||
"t":states.keylayouts.map(it => [it[0],it[1]]),
|
"t":states.keylayouts.map(it => [it[0],it[1]]),
|
||||||
"l":"koKR",
|
"l":"koKR",
|
||||||
// return: [displayed output, composed output]
|
// return: [delete count, composed output]
|
||||||
"accept":(headkey,shiftin,altgrin)=>{
|
"accept":(headkey,shiftin,altgrin)=>{
|
||||||
let layer = 1*shiftin// + 2*altgrin
|
let layer = 1*shiftin// + 2*altgrin
|
||||||
states.code = 1
|
states.code = 1
|
||||||
|
|
||||||
let s = states.keylayouts[headkey][layer]
|
let s = states.keylayouts[headkey][layer] || states.keylayouts[headkey][0]
|
||||||
let bufIndex = isJungseong(s) ? 1 : isJongseong(s) ? 2 : 0
|
let bufIndex = isJungseong(s) ? 1 : isJongseong(s) ? 2 : 0
|
||||||
|
|
||||||
if (isHangul(s)) {
|
if (isHangul(s)) {
|
||||||
|
|||||||
@@ -385,12 +385,12 @@ let bufDebugStringify = (buf) => [0,1,2].map(i => (buf[i] == undefined) ? "·" :
|
|||||||
return Object.freeze({"n":"신세벌식 ’03","v":"none","c":"CuriousTo\uA75Bvald","m":"rewrite",
|
return Object.freeze({"n":"신세벌식 ’03","v":"none","c":"CuriousTo\uA75Bvald","m":"rewrite",
|
||||||
"t":states.keylayouts.map(it => [it[0],it[1]]),
|
"t":states.keylayouts.map(it => [it[0],it[1]]),
|
||||||
"l":"koKR",
|
"l":"koKR",
|
||||||
// return: [displayed output, composed output]
|
// return: [delete count, composed output]
|
||||||
"accept":(headkey,shiftin,altgrin)=>{
|
"accept":(headkey,shiftin,altgrin)=>{
|
||||||
let layer = 1*shiftin// + 2*altgrin
|
let layer = 1*shiftin// + 2*altgrin
|
||||||
states.code = 1
|
states.code = 1
|
||||||
|
|
||||||
let s = states.keylayouts[headkey][layer]
|
let s = states.keylayouts[headkey][layer] || states.keylayouts[headkey][0]
|
||||||
let s2 = states.keylayouts[headkey][2]
|
let s2 = states.keylayouts[headkey][2]
|
||||||
let bufIndex = isJungseong(s) ? 1 : isJongseong(s) ? 2 : 0
|
let bufIndex = isJungseong(s) ? 1 : isJongseong(s) ? 2 : 0
|
||||||
|
|
||||||
|
|||||||
@@ -385,12 +385,12 @@ let bufDebugStringify = (buf) => [0,1,2].map(i => (buf[i] == undefined) ? "·" :
|
|||||||
return Object.freeze({"n":"신세벌식 P2","v":"none","c":"CuriousTo\uA75Bvald","m":"rewrite",
|
return Object.freeze({"n":"신세벌식 P2","v":"none","c":"CuriousTo\uA75Bvald","m":"rewrite",
|
||||||
"t":states.keylayouts.map(it => [it[0],it[1]]),
|
"t":states.keylayouts.map(it => [it[0],it[1]]),
|
||||||
"l":"koKR",
|
"l":"koKR",
|
||||||
// return: [displayed output, composed output]
|
// return: [delete count, composed output]
|
||||||
"accept":(headkey,shiftin,altgrin)=>{
|
"accept":(headkey,shiftin,altgrin)=>{
|
||||||
let layer = 1*shiftin// + 2*altgrin
|
let layer = 1*shiftin// + 2*altgrin
|
||||||
states.code = 1
|
states.code = 1
|
||||||
|
|
||||||
let s = states.keylayouts[headkey][layer]
|
let s = states.keylayouts[headkey][layer] || states.keylayouts[headkey][0]
|
||||||
let s2 = states.keylayouts[headkey][2]
|
let s2 = states.keylayouts[headkey][2]
|
||||||
let bufIndex = isJungseong(s) ? 1 : isJongseong(s) ? 2 : 0
|
let bufIndex = isJungseong(s) ? 1 : isJongseong(s) ? 2 : 0
|
||||||
|
|
||||||
|
|||||||
@@ -375,11 +375,11 @@ let isDiacritics = (s) => s !== undefined && inRange(s.charCodeAt(0), 0x0300, 0x
|
|||||||
return Object.freeze({"n":"ЙЦУКЕН Многоязычна","v":"none","c":"CuriousTo\uA75Bvald","m":"rewrite",
|
return Object.freeze({"n":"ЙЦУКЕН Многоязычна","v":"none","c":"CuriousTo\uA75Bvald","m":"rewrite",
|
||||||
"t":states.keylayouts,
|
"t":states.keylayouts,
|
||||||
"l":"ruRU",
|
"l":"ruRU",
|
||||||
// return: [displayed output, composed output]
|
// return: [delete count, composed output]
|
||||||
"accept":(headkey,shiftin,altgrin)=>{
|
"accept":(headkey,shiftin,altgrin)=>{
|
||||||
let layer = 1*shiftin + 2*altgrin
|
let layer = 1*shiftin + 2*altgrin
|
||||||
|
|
||||||
let s = states.keylayouts[headkey][layer]
|
let s = (states.keylayouts[headkey][layer] || states.keylayouts[headkey][1*shiftin]) || states.keylayouts[headkey][0]
|
||||||
|
|
||||||
// typing seq for diacritics: diacritics THEN a character
|
// typing seq for diacritics: diacritics THEN a character
|
||||||
if (isDiacritics(s)) {
|
if (isDiacritics(s)) {
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ let states = {"keylayouts":[[""],[undefined],
|
|||||||
[undefined],
|
[undefined],
|
||||||
[undefined],
|
[undefined],
|
||||||
["ф","Ф","ƒ","ƒ"],
|
["ф","Ф","ƒ","ƒ"],
|
||||||
["и","И"],
|
["и","И","и","И"],
|
||||||
["с","С","≠","≠"],
|
["с","С","≠","≠"],
|
||||||
["в","В","ћ","Ћ"],
|
["в","В","ћ","Ћ"],
|
||||||
["у","У","ќ","Ќ"],
|
["у","У","ќ","Ќ"],
|
||||||
@@ -69,10 +69,10 @@ let states = {"keylayouts":[[""],[undefined],
|
|||||||
["-","_","—","–"],
|
["-","_","—","–"],
|
||||||
["=","+","»","«"],
|
["=","+","»","«"],
|
||||||
["х","Х","“","“"],
|
["х","Х","“","“"],
|
||||||
["ъ","Ъ"],
|
["ъ","Ъ","ъ","Ъ"],
|
||||||
["ё","Ё"],
|
["ё","Ё","ё","Ё"],
|
||||||
["ж","Ж","…","…"],
|
["ж","Ж","…","…"],
|
||||||
["э",'Э'],
|
["э",'Э',"э",'Э'],
|
||||||
["/","?","„","„"],
|
["/","?","„","„"],
|
||||||
[undefined],
|
[undefined],
|
||||||
[undefined],
|
[undefined],
|
||||||
@@ -263,12 +263,12 @@ let isDiacritics = (s) => s !== undefined && inRange(s.charCodeAt(0), 0x0300, 0x
|
|||||||
return Object.freeze({"n":"ЙЦУКЕН (Рус. Apple)","v":"none","c":"CuriousTo\uA75Bvald","m":"rewrite",
|
return Object.freeze({"n":"ЙЦУКЕН (Рус. Apple)","v":"none","c":"CuriousTo\uA75Bvald","m":"rewrite",
|
||||||
"t":states.keylayouts,
|
"t":states.keylayouts,
|
||||||
"l":"ruRU",
|
"l":"ruRU",
|
||||||
// return: [displayed output, composed output]
|
// return: [delete count, composed output]
|
||||||
"accept":(headkey,shiftin,altgrin)=>{
|
"accept":(headkey,shiftin,altgrin)=>{
|
||||||
let layer = 1*shiftin + 2*altgrin
|
let layer = 1*shiftin + 2*altgrin
|
||||||
states.code = 1
|
states.code = 1
|
||||||
|
|
||||||
let s = states.keylayouts[headkey][layer]
|
let s = (states.keylayouts[headkey][layer] || states.keylayouts[headkey][1*shiftin]) || states.keylayouts[headkey][0]
|
||||||
|
|
||||||
if (isDiacritics(s)) {
|
if (isDiacritics(s)) {
|
||||||
return ['1', '']
|
return ['1', '']
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ let isDiacritics = (s) => s !== undefined && inRange(s.charCodeAt(0), 0x0300, 0x
|
|||||||
return Object.freeze({"n":"Рус. Фонетическая","v":"none","c":"CuriousTo\uA75Bvald","m":"rewrite",
|
return Object.freeze({"n":"Рус. Фонетическая","v":"none","c":"CuriousTo\uA75Bvald","m":"rewrite",
|
||||||
"tf":states.layouttable,
|
"tf":states.layouttable,
|
||||||
"l":"ruRU",
|
"l":"ruRU",
|
||||||
// return: [displayed output, composed output]
|
// return: [delete count, composed output]
|
||||||
"accept":(headkey,shiftin,altgrin,lowlayerkey)=>{
|
"accept":(headkey,shiftin,altgrin,lowlayerkey)=>{
|
||||||
let layer = 1*shiftin// + 2*altgrin
|
let layer = 1*shiftin// + 2*altgrin
|
||||||
states.code = 1
|
states.code = 1
|
||||||
|
|||||||
290
assets/keylayout/ta_in_tamil99.ime
Normal file
290
assets/keylayout/ta_in_tamil99.ime
Normal file
@@ -0,0 +1,290 @@
|
|||||||
|
let states = {"keylayouts":[[""],[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
["0",")"],
|
||||||
|
["1","!"],
|
||||||
|
["2","@"],
|
||||||
|
["3","#"],
|
||||||
|
["4","$"],
|
||||||
|
["5","%"],
|
||||||
|
["6","^"],
|
||||||
|
["7","&"],
|
||||||
|
["8","*"],
|
||||||
|
["9","("],
|
||||||
|
["*"],
|
||||||
|
["#"],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
["\u0B85","\u0BF9"],
|
||||||
|
["\u0B99","\u0BF7"],
|
||||||
|
["\u0B92","\u0BF5","\u0BCA"],
|
||||||
|
["\u0B89","\u0BF8","\u0BC1"],
|
||||||
|
["\u0B8A","\u0B9C","\u0BC2"],
|
||||||
|
["\u0BCD","\u0B83"],
|
||||||
|
["\u0B8E","\u0B8E","\u0BC6"],
|
||||||
|
["\u0B95","\u0B95"],
|
||||||
|
["\u0BA9","\u0BA9"],
|
||||||
|
["\u0BAA","\u0BAA"],
|
||||||
|
["\u0BAE",'"'],
|
||||||
|
["\u0BA4",":"],
|
||||||
|
["\u0BB0","/"],
|
||||||
|
["\u0BB2","\u0BB2"],
|
||||||
|
["\u0B9F","["],
|
||||||
|
["\u0BA3","]"],
|
||||||
|
["\u0B86","\u0BB8","\u0BBE"],
|
||||||
|
["\u0B90","\u0BB9","\u0BC8"],
|
||||||
|
["\u0B87","\u0BFA","\u0BBF"],
|
||||||
|
["\u0B8F","\u0B95\u0BCD\u0BB7","\u0BC7"],
|
||||||
|
["\u0BB1","\u0BB1"],
|
||||||
|
["\u0BB5","\u0BF6"],
|
||||||
|
["\u0B88","\u0BB7","\u0BC0"],
|
||||||
|
["\u0B93","\u0BF4","\u0BCB"],
|
||||||
|
["\u0BB3","\u0BB8\u0BCD\u0BB0\u0BC0"],
|
||||||
|
["\u0B94","\u0BF3","\u0BCC"],
|
||||||
|
[",","<"],
|
||||||
|
[".",">"],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[" "],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
["\n"],
|
||||||
|
["\x08"],
|
||||||
|
["`","~"],
|
||||||
|
["-","_"],
|
||||||
|
["=","+"],
|
||||||
|
["\u0B9A","{"],
|
||||||
|
["\u0B9E","}"],
|
||||||
|
["\\","|"],
|
||||||
|
["\u0BA8",";"],
|
||||||
|
["\u0BAF","'"],
|
||||||
|
["\u0BB4","?"],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
["0"],
|
||||||
|
["1"],
|
||||||
|
["2"],
|
||||||
|
["3"],
|
||||||
|
["4"],
|
||||||
|
["5"],
|
||||||
|
["6"],
|
||||||
|
["7"],
|
||||||
|
["8"],
|
||||||
|
["9"],
|
||||||
|
["/"],
|
||||||
|
["*"],
|
||||||
|
["-"],
|
||||||
|
["+"],
|
||||||
|
["."],
|
||||||
|
["."],
|
||||||
|
["\n"],
|
||||||
|
["="],
|
||||||
|
["("],
|
||||||
|
[")"],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined],
|
||||||
|
[undefined]
|
||||||
|
],
|
||||||
|
"code":""} // the last character typed
|
||||||
|
let reset = () => {
|
||||||
|
states.code = ""
|
||||||
|
}
|
||||||
|
let inRange = (s,a,b) => (a <= s && s <= b)
|
||||||
|
let isConsonant = (s) => s !== undefined && (inRange(s, 0x0B95, 0x0BB9) || s == 0x0BD0 || inRange(s, 0x0BE6, 0x0BFA)) // determines the behaviour of the vowel key
|
||||||
|
return Object.freeze({"n":"தமிழ் 99","v":"none","c":"CuriousTo\uA75Bvald","m":"rewrite",
|
||||||
|
"t":states.keylayouts,
|
||||||
|
"l":"taIN",
|
||||||
|
// return: [delete count, composed output]
|
||||||
|
"accept":(headkey,shiftin,altgrin)=>{
|
||||||
|
let layer = 1*shiftin
|
||||||
|
|
||||||
|
let s = states.keylayouts[headkey][layer] || states.keylayouts[headkey][0]
|
||||||
|
|
||||||
|
if (layer == 0 && states.code != "" && isConsonant(states.code.charCodeAt(states.code.length - 1))) {
|
||||||
|
s = states.keylayouts[headkey][2] || states.keylayouts[headkey][0]
|
||||||
|
}
|
||||||
|
|
||||||
|
states.code = s
|
||||||
|
|
||||||
|
return ['0', s]
|
||||||
|
},
|
||||||
|
"backspace":()=>{
|
||||||
|
reset()
|
||||||
|
return ''
|
||||||
|
},
|
||||||
|
"end":()=>{
|
||||||
|
reset()
|
||||||
|
return ''
|
||||||
|
},
|
||||||
|
"reset":()=>{ reset() },
|
||||||
|
"composing":()=>(states.code!='')
|
||||||
|
})
|
||||||
@@ -269,12 +269,12 @@ let isDiacritics = (s) => s !== undefined && inRange(s.charCodeAt(0), 0x0300, 0x
|
|||||||
return Object.freeze({"n":"แป้นพิมพ์เกษมณี","v":"none","c":"CuriousTo\uA75Bvald","m":"rewrite",
|
return Object.freeze({"n":"แป้นพิมพ์เกษมณี","v":"none","c":"CuriousTo\uA75Bvald","m":"rewrite",
|
||||||
"t":states.keylayouts,
|
"t":states.keylayouts,
|
||||||
"l":"thTH",
|
"l":"thTH",
|
||||||
// return: [displayed output, composed output]
|
// return: [delete count, composed output]
|
||||||
"accept":(headkey,shiftin,altgrin)=>{
|
"accept":(headkey,shiftin,altgrin)=>{
|
||||||
let layer = 1*shiftin + 2*altgrin // use AltGr to type conventional numbers
|
let layer = 1*shiftin + 2*altgrin // use AltGr to type conventional numbers
|
||||||
states.code = 0
|
states.code = 0
|
||||||
|
|
||||||
let s = states.keylayouts[headkey][layer]
|
let s = (states.keylayouts[headkey][layer] || states.keylayouts[headkey][1*shiftin]) || states.keylayouts[headkey][0]
|
||||||
return ['0', s]
|
return ['0', s]
|
||||||
},
|
},
|
||||||
"backspace":()=>{
|
"backspace":()=>{
|
||||||
|
|||||||
@@ -269,12 +269,12 @@ let isDiacritics = (s) => s !== undefined && (inRange(s.charCodeAt(0), 0x0E31, 0
|
|||||||
return Object.freeze({"n":"แป้นพิมพ์ปัตตะโชติ","v":"none","c":"CuriousTo\uA75Bvald","m":"rewrite",
|
return Object.freeze({"n":"แป้นพิมพ์ปัตตะโชติ","v":"none","c":"CuriousTo\uA75Bvald","m":"rewrite",
|
||||||
"t":states.keylayouts,
|
"t":states.keylayouts,
|
||||||
"l":"thTH",
|
"l":"thTH",
|
||||||
// return: [displayed output, composed output]
|
// return: [delete count, composed output]
|
||||||
"accept":(headkey,shiftin,altgrin)=>{
|
"accept":(headkey,shiftin,altgrin)=>{
|
||||||
let layer = 1*shiftin + 2*altgrin // use AltGr to type conventional numbers
|
let layer = 1*shiftin + 2*altgrin // use AltGr to type conventional numbers
|
||||||
states.code = 0
|
states.code = 0
|
||||||
|
|
||||||
let s = states.keylayouts[headkey][layer]
|
let s = (states.keylayouts[headkey][layer] || states.keylayouts[headkey][1*shiftin]) || states.keylayouts[headkey][0]
|
||||||
return ['0', s]
|
return ['0', s]
|
||||||
},
|
},
|
||||||
"backspace":()=>{
|
"backspace":()=>{
|
||||||
|
|||||||
@@ -276,7 +276,7 @@ return Object.freeze({"n":"五仓简体 Qwerty","v":"many","c":"CuriousTo\uA75Bv
|
|||||||
"accept":(headkey,shiftin,altgrin)=>{
|
"accept":(headkey,shiftin,altgrin)=>{
|
||||||
let layer = 1*shiftin// + 2*altgrin
|
let layer = 1*shiftin// + 2*altgrin
|
||||||
|
|
||||||
let cjkey = states.keylayouts[headkey][layer]
|
let cjkey = states.keylayouts[headkey][layer] || states.keylayouts[headkey][0]
|
||||||
let cjkeyAsc = cjkey.codePointAt(0)
|
let cjkeyAsc = cjkey.codePointAt(0)
|
||||||
|
|
||||||
if (states.code == 1 && 48 <= cjkeyAsc && cjkeyAsc <= 57) {
|
if (states.code == 1 && 48 <= cjkeyAsc && cjkeyAsc <= 57) {
|
||||||
|
|||||||
@@ -276,7 +276,7 @@ return Object.freeze({"n":"五倉正體 Qwerty","v":"many","c":"CuriousTo\uA75Bv
|
|||||||
"accept":(headkey,shiftin,altgrin)=>{
|
"accept":(headkey,shiftin,altgrin)=>{
|
||||||
let layer = 1*shiftin// + 2*altgrin
|
let layer = 1*shiftin// + 2*altgrin
|
||||||
|
|
||||||
let cjkey = states.keylayouts[headkey][layer]
|
let cjkey = states.keylayouts[headkey][layer] || states.keylayouts[headkey][0]
|
||||||
let cjkeyAsc = cjkey.codePointAt(0)
|
let cjkeyAsc = cjkey.codePointAt(0)
|
||||||
|
|
||||||
if (states.code == 1 && 48 <= cjkeyAsc && cjkeyAsc <= 57) {
|
if (states.code == 1 && 48 <= cjkeyAsc && cjkeyAsc <= 57) {
|
||||||
|
|||||||
4
assets/locales/de/input.json
Normal file
4
assets/locales/de/input.json
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"INPUT_KEYBOARD_DEFAULT_LAYOUT": "en_intl_qwertz",
|
||||||
|
"INPUT_KEYBOARD_DEFAULT_IME": "none"
|
||||||
|
}
|
||||||
@@ -1,37 +1,40 @@
|
|||||||
{
|
{
|
||||||
"CONTEXT_CHARACTER": "Character",
|
|
||||||
"MENU_LABEL_COPYRIGHT": "Copyright",
|
|
||||||
"COPYRIGHT_ALL_RIGHTS_RESERVED": "All rights reserved",
|
|
||||||
"COPYRIGHT_GNU_GPL_3": "Distributed under GNU GPL 3",
|
|
||||||
"APP_WARNING_HEALTH_AND_SAFETY": "WARNING-HEALTH AND SAFETY",
|
"APP_WARNING_HEALTH_AND_SAFETY": "WARNING-HEALTH AND SAFETY",
|
||||||
"MENU_LABEL_PRESS_START_SYMBOL": "Press >",
|
"CONTEXT_CHARACTER": "Character",
|
||||||
"MENU_MODULES" : "Modules",
|
|
||||||
"MENU_CREDIT_GPL_DNT" : "GPL",
|
|
||||||
"MENU_LABEL_JVM_DNT" : "JVM",
|
|
||||||
"GAME_ACTION_MOVE_VERB" : "Move",
|
|
||||||
"GAME_ACTION_ZOOM" : "Zoom",
|
|
||||||
"MENU_LABEL_RESET" : "Reset",
|
|
||||||
"MENU_OPTION_STREAMERS_LAYOUT": "Chat Overlay",
|
|
||||||
"MENU_LABEL_RESTART_REQUIRED": "Restart Required",
|
|
||||||
"MENU_LABEL_KEYBOARD_LAYOUT": "Keyboard Layout",
|
|
||||||
"MENU_LABEL_IME": "IME",
|
|
||||||
"MENU_OPTIONS_DITHER": "Dithering",
|
|
||||||
"MENU_OPTIONS_BLUR": "Blur",
|
|
||||||
"MENU_OPTIONS_PARTICLES": "Particles",
|
|
||||||
"MENU_IO_IMPORT": "Import",
|
|
||||||
"MENU_LABEL_IME_TOGGLE": "Toggle IME",
|
|
||||||
"MENU_LABEL_PASTE_FROM_CLIPBOARD": "Paste from Clipboard",
|
|
||||||
"MENU_OPTIONS_PERFORMANCE": "Performance",
|
|
||||||
"MENU_LABEL_DELETE": "Delete",
|
|
||||||
"MENU_OPTIONS_JVM_HEAP_MAX": "Max Heap Memory",
|
|
||||||
"MENU_OPTIONS_AUTOSAVE": "Autosave",
|
|
||||||
"CONTEXT_TIME_MINUTE_PLURAL": "Minutes",
|
"CONTEXT_TIME_MINUTE_PLURAL": "Minutes",
|
||||||
"CONTEXT_TIME_SECOND_PLURAL": "Seconds",
|
"CONTEXT_TIME_SECOND_PLURAL": "Seconds",
|
||||||
"MENU_LABEL_SYSTEM_INFO": "System Info",
|
"COPYRIGHT_ALL_RIGHTS_RESERVED": "All rights reserved",
|
||||||
"MENU_OPTIONS_NOTIFICATION_DISPLAY_DURATION": "Show notification for",
|
"COPYRIGHT_GNU_GPL_3": "Distributed under GNU GPL 3",
|
||||||
"MENU_LABEL_STREAMING": "Livestreaming",
|
"GAME_ACTION_MOVE_VERB" : "Move",
|
||||||
"MENU_LABEL_EXTRA_JVM_ARGUMENTS": "Extra Arguments",
|
"GAME_ACTION_ZOOM" : "Zoom",
|
||||||
"MENU_IO_MANUAL_SAVE": "Manual Save",
|
|
||||||
"MENU_IO_AUTOSAVE": "Autosave",
|
"MENU_IO_AUTOSAVE": "Autosave",
|
||||||
"MENU_OPTIONS_DEBUG_CONSOLE": "Debug Console"
|
"MENU_IO_IMPORT": "Import",
|
||||||
|
"MENU_IO_MANUAL_SAVE": "Manual Save",
|
||||||
|
"MENU_LABEL_COPYRIGHT": "Copyright",
|
||||||
|
"MENU_LABEL_DELETE": "Delete",
|
||||||
|
"MENU_LABEL_EXTRA_JVM_ARGUMENTS": "Extra Arguments",
|
||||||
|
"MENU_LABEL_IME": "IME",
|
||||||
|
"MENU_LABEL_IME_TOGGLE": "Toggle IME",
|
||||||
|
"MENU_LABEL_KEYBOARD_LAYOUT": "Keyboard Layout",
|
||||||
|
"MENU_LABEL_PASTE_FROM_CLIPBOARD": "Paste from Clipboard",
|
||||||
|
"MENU_LABEL_PRESS_START_SYMBOL": "Press >",
|
||||||
|
"MENU_LABEL_RESET" : "Reset",
|
||||||
|
"MENU_LABEL_RESTART_REQUIRED": "Restart Required",
|
||||||
|
"MENU_LABEL_STREAMING": "Livestreaming",
|
||||||
|
"MENU_LABEL_SYSTEM_INFO": "System Info",
|
||||||
|
"MENU_MODULES" : "Modules",
|
||||||
|
"MENU_OPTIONS_AUTOSAVE": "Autosave",
|
||||||
|
"MENU_OPTIONS_BLUR": "Blur",
|
||||||
|
"MENU_OPTIONS_DEBUG_CONSOLE": "Debug Console",
|
||||||
|
"MENU_OPTIONS_DITHER": "Dithering",
|
||||||
|
"MENU_OPTIONS_JVM_HEAP_MAX": "Max Heap Memory",
|
||||||
|
"MENU_OPTIONS_NOTIFICATION_DISPLAY_DURATION": "Show notification for",
|
||||||
|
"MENU_OPTIONS_PARTICLES": "Particles",
|
||||||
|
"MENU_OPTIONS_PERFORMANCE": "Performance",
|
||||||
|
"MENU_OPTIONS_STREAMERS_LAYOUT": "Chat Overlay",
|
||||||
|
"MENU_OPTIONS_NONE" : "None",
|
||||||
|
|
||||||
|
"MENU_CREDIT_GPL_DNT" : "GPL",
|
||||||
|
"MENU_LABEL_JVM_DNT" : "JVM",
|
||||||
|
"MENU_OPTIONS_FILTERING_HQ2X_DNT" : "Hq2x"
|
||||||
}
|
}
|
||||||
@@ -1,16 +1,16 @@
|
|||||||
{
|
{
|
||||||
"GAME_32BIT_WARNING1": "32비트 버전의 Java를 사용중인 것 같습니다.",
|
"GAME_32BIT_WARNING1": "It looks like you’re running a 32-Bit version of Java.",
|
||||||
"GAME_32BIT_WARNING2": "아래 링크에서 최신 64비트 Java를 내려받아 설치해주세요.",
|
"GAME_32BIT_WARNING2": "Please download and install the latest 64-Bit Java at:",
|
||||||
"GAME_32BIT_WARNING3": "https://www.java.com/ko/download/",
|
"GAME_32BIT_WARNING3": "https://www.java.com/en/download/",
|
||||||
"GAME_APPLE_ROSETTA_WARNING1": "Apple Silicon이 탑재된 Mac을 사용 중이지만 x86 빌드의 게임을 실행 중입니다.",
|
"GAME_APPLE_ROSETTA_WARNING1": "It seems you are using a Mac with Apple Silicon but running the x86 build of the game.",
|
||||||
"GAME_APPLE_ROSETTA_WARNING2": "최적의 성능과 게임 경험을 위해 Apple Silicon용 빌드의 게임을 이용해 주십시오.",
|
"GAME_APPLE_ROSETTA_WARNING2": "Please use the native build for improved performance and gameplay experiences.",
|
||||||
"APP_NOMODULE_1": "현재 불러와진 모듈이 없습니다.",
|
"APP_NOMODULE_1": "No Module is currently loaded.",
|
||||||
"APP_NOMODULE_2": "다음의 파일에서 불러오기 순서를 설정하고 게임을 재시작하십시오.",
|
"APP_NOMODULE_2": "Please configure your Load Order and restart:",
|
||||||
"MENU_LABEL_KEYCONFIG_HELP1": "키캡을 클릭해 컨트롤을 배정하십시오",
|
"MENU_LABEL_KEYCONFIG_HELP1": "Click On the Keycap to Assign Actions",
|
||||||
"GAME_PREV_SAVE_WAS_LOADED1": "가장 최근에 저장된 게임이 손상되었습니다.",
|
"GAME_PREV_SAVE_WAS_LOADED1": "The most recently saved game was corrupted.",
|
||||||
"GAME_PREV_SAVE_WAS_LOADED2": "이전에 저장된 게임을 불러왔습니다.",
|
"GAME_PREV_SAVE_WAS_LOADED2": "The previously saved game was loaded.",
|
||||||
"GAME_MORE_RECENT_AUTOSAVE1": "자동 저장된 게임이 수동으로 저장한 게임보다 더 최신입니다.",
|
"GAME_MORE_RECENT_AUTOSAVE1": "The Autosave is more recent than the manual save.",
|
||||||
"GAME_MORE_RECENT_AUTOSAVE2": "불러올 게임을 선택해 주십시오.",
|
"GAME_MORE_RECENT_AUTOSAVE2": "Please select the saved game you wish to play:",
|
||||||
"MENU_LABEL_SAVE_WILL_BE_DELETED": "선택된 세이브가 삭제됩니다.",
|
"MENU_LABEL_SAVE_WILL_BE_DELETED": "The selected save file will be deleted.",
|
||||||
"MENU_LABEL_UNSAVED_PROGRESSES_WILL_BE_LOST": "저장하지 않은 변동사항을 잃게 됩니다."
|
"MENU_LABEL_UNSAVED_PROGRESS_WILL_BE_LOST": "Unsaved progress will be lost."
|
||||||
}
|
}
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
"GAME_ACTION_MOVE_VERB" : "हिलना",
|
"GAME_ACTION_MOVE_VERB" : "हिलना",
|
||||||
"GAME_ACTION_ZOOM" : "ज़ूम",
|
"GAME_ACTION_ZOOM" : "ज़ूम",
|
||||||
"MENU_LABEL_RESET" : "रीसेट",
|
"MENU_LABEL_RESET" : "रीसेट",
|
||||||
"MENU_OPTION_STREAMERS_LAYOUT": "Chat Overlay",
|
"MENU_OPTIONS_STREAMERS_LAYOUT": "Chat Overlay",
|
||||||
"MENU_LABEL_RESTART_REQUIRED": "पुनः शुरआत जरुरी है",
|
"MENU_LABEL_RESTART_REQUIRED": "पुनः शुरआत जरुरी है",
|
||||||
"MENU_LABEL_KEYBOARD_LAYOUT": "कीबोर्ड विन्यास",
|
"MENU_LABEL_KEYBOARD_LAYOUT": "कीबोर्ड विन्यास",
|
||||||
"MENU_LABEL_IME": "इनपुट विधि",
|
"MENU_LABEL_IME": "इनपुट विधि",
|
||||||
|
|||||||
@@ -1,37 +1,36 @@
|
|||||||
{
|
{
|
||||||
"CONTEXT_CHARACTER": "캐릭터",
|
|
||||||
"MENU_LABEL_COPYRIGHT": "저작권",
|
|
||||||
"COPYRIGHT_ALL_RIGHTS_RESERVED": "모든 권리 보유",
|
|
||||||
"COPYRIGHT_GNU_GPL_3": "GNU GPL 3에 따라 배포됨",
|
|
||||||
"APP_WARNING_HEALTH_AND_SAFETY": "경고—건강과 안전을 위하여",
|
"APP_WARNING_HEALTH_AND_SAFETY": "경고—건강과 안전을 위하여",
|
||||||
"MENU_LABEL_PRESS_START_SYMBOL": ">을 누르세요",
|
"CONTEXT_CHARACTER": "캐릭터",
|
||||||
"MENU_MODULES" : "모듈",
|
|
||||||
|
|
||||||
|
|
||||||
"GAME_ACTION_MOVE_VERB" : "이동하기",
|
|
||||||
"GAME_ACTION_ZOOM" : "확대·축소",
|
|
||||||
"MENU_LABEL_RESET" : "재설정",
|
|
||||||
"MENU_OPTION_STREAMERS_LAYOUT": "채팅창 오버레이",
|
|
||||||
"MENU_LABEL_RESTART_REQUIRED": "재시작 필요",
|
|
||||||
"MENU_LABEL_KEYBOARD_LAYOUT": "자판 배열",
|
|
||||||
"MENU_LABEL_IME": "입력기",
|
|
||||||
"MENU_OPTIONS_DITHER": "디더링",
|
|
||||||
"MENU_OPTIONS_BLUR": "흐림",
|
|
||||||
"MENU_OPTIONS_PARTICLES": "입자 수",
|
|
||||||
"MENU_IO_IMPORT": "가져오기",
|
|
||||||
"MENU_LABEL_IME_TOGGLE": "입력기 켜고 끄기",
|
|
||||||
"MENU_LABEL_PASTE_FROM_CLIPBOARD": "복사한 텍스트 붙여넣기",
|
|
||||||
"MENU_OPTIONS_PERFORMANCE": "성능",
|
|
||||||
"MENU_LABEL_DELETE": "삭제",
|
|
||||||
"MENU_OPTIONS_JVM_HEAP_MAX": "최대 힙 메모리",
|
|
||||||
"MENU_OPTIONS_AUTOSAVE": "자동 저장",
|
|
||||||
"CONTEXT_TIME_MINUTE_PLURAL": "분",
|
"CONTEXT_TIME_MINUTE_PLURAL": "분",
|
||||||
"CONTEXT_TIME_SECOND_PLURAL": "초",
|
"CONTEXT_TIME_SECOND_PLURAL": "초",
|
||||||
"MENU_LABEL_SYSTEM_INFO": "시스템 정보",
|
"COPYRIGHT_ALL_RIGHTS_RESERVED": "모든 권리 보유",
|
||||||
"MENU_OPTIONS_NOTIFICATION_DISPLAY_DURATION": "알림 표시 시간",
|
"COPYRIGHT_GNU_GPL_3": "GNU GPL 3에 따라 배포됨",
|
||||||
"MENU_LABEL_STREAMING": "실시간 방송",
|
"GAME_ACTION_MOVE_VERB" : "이동하기",
|
||||||
"MENU_LABEL_EXTRA_JVM_ARGUMENTS": "추가 명령 인수",
|
"GAME_ACTION_ZOOM" : "확대·축소",
|
||||||
"MENU_IO_MANUAL_SAVE": "수동 저장",
|
|
||||||
"MENU_IO_AUTOSAVE": "자동 저장",
|
"MENU_IO_AUTOSAVE": "자동 저장",
|
||||||
"MENU_OPTIONS_DEBUG_CONSOLE": "디버그 콘솔"
|
"MENU_IO_IMPORT": "가져오기",
|
||||||
|
"MENU_IO_MANUAL_SAVE": "수동 저장",
|
||||||
|
"MENU_LABEL_COPYRIGHT": "저작권",
|
||||||
|
"MENU_LABEL_DELETE": "삭제",
|
||||||
|
"MENU_LABEL_EXTRA_JVM_ARGUMENTS": "추가 명령 인수",
|
||||||
|
"MENU_LABEL_IME": "입력기",
|
||||||
|
"MENU_LABEL_IME_TOGGLE": "입력기 켜고 끄기",
|
||||||
|
"MENU_LABEL_KEYBOARD_LAYOUT": "자판 배열",
|
||||||
|
"MENU_LABEL_PASTE_FROM_CLIPBOARD": "복사한 텍스트 붙여넣기",
|
||||||
|
"MENU_LABEL_PRESS_START_SYMBOL": ">을 누르세요",
|
||||||
|
"MENU_LABEL_RESET" : "재설정",
|
||||||
|
"MENU_LABEL_RESTART_REQUIRED": "재시작 필요",
|
||||||
|
"MENU_LABEL_STREAMING": "실시간 방송",
|
||||||
|
"MENU_LABEL_SYSTEM_INFO": "시스템 정보",
|
||||||
|
"MENU_MODULES" : "모듈",
|
||||||
|
"MENU_OPTIONS_AUTOSAVE": "자동 저장",
|
||||||
|
"MENU_OPTIONS_BLUR": "흐림",
|
||||||
|
"MENU_OPTIONS_DEBUG_CONSOLE": "디버그 콘솔",
|
||||||
|
"MENU_OPTIONS_DITHER": "디더링",
|
||||||
|
"MENU_OPTIONS_JVM_HEAP_MAX": "최대 힙 메모리",
|
||||||
|
"MENU_OPTIONS_NOTIFICATION_DISPLAY_DURATION": "알림 표시 시간",
|
||||||
|
"MENU_OPTIONS_PARTICLES": "입자 수",
|
||||||
|
"MENU_OPTIONS_PERFORMANCE": "성능",
|
||||||
|
"MENU_OPTIONS_STREAMERS_LAYOUT": "채팅창 오버레이",
|
||||||
|
"MENU_OPTIONS_NONE" : "없음"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,5 +11,6 @@
|
|||||||
"GAME_PREV_SAVE_WAS_LOADED2": "이전에 저장된 게임을 불러왔습니다.",
|
"GAME_PREV_SAVE_WAS_LOADED2": "이전에 저장된 게임을 불러왔습니다.",
|
||||||
"GAME_MORE_RECENT_AUTOSAVE1": "자동 저장된 게임이 수동으로 저장한 게임보다 더 최신입니다.",
|
"GAME_MORE_RECENT_AUTOSAVE1": "자동 저장된 게임이 수동으로 저장한 게임보다 더 최신입니다.",
|
||||||
"GAME_MORE_RECENT_AUTOSAVE2": "불러올 게임을 선택해 주십시오.",
|
"GAME_MORE_RECENT_AUTOSAVE2": "불러올 게임을 선택해 주십시오.",
|
||||||
"MENU_LABEL_SAVE_WILL_BE_DELETED": "선택된 세이브가 삭제됩니다."
|
"MENU_LABEL_SAVE_WILL_BE_DELETED": "선택된 세이브가 삭제됩니다.",
|
||||||
|
"MENU_LABEL_UNSAVED_PROGRESS_WILL_BE_LOST": "저장하지 않은 진행 상황을 잃게 됩니다."
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
"GAME_32BIT_WARNING1": "看起来您正在运行32位版本的Java。",
|
"GAME_32BIT_WARNING1": "看起来您正在运行32位版本的Java。",
|
||||||
"GAME_32BIT_WARNING2": "请下载并安装最新的64位Java :",
|
"GAME_32BIT_WARNING2": "请下载并安装最新的64位Java :",
|
||||||
"GAME_32BIT_WARNING3": "https://www.java.com/en/download/",
|
"GAME_32BIT_WARNING3": "https://www.java.com/en/download/",
|
||||||
"MENU_OPTION_STREAMERS_LAYOUT": "聊天叠加",
|
"MENU_OPTIONS_STREAMERS_LAYOUT": "聊天叠加",
|
||||||
"MENU_LABEL_RESTART_REQUIRED": "需要重新启动",
|
"MENU_LABEL_RESTART_REQUIRED": "需要重新启动",
|
||||||
"MENU_LABEL_KEYBOARD_LAYOUT": "键盘布局",
|
"MENU_LABEL_KEYBOARD_LAYOUT": "键盘布局",
|
||||||
"MENU_LABEL_IME": "输入法",
|
"MENU_LABEL_IME": "输入法",
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
"GAME_32BIT_WARNING1": "看起來您正在運行32位版本的Java。",
|
"GAME_32BIT_WARNING1": "看起來您正在運行32位版本的Java。",
|
||||||
"GAME_32BIT_WARNING2": "請下載並安裝最新的64位Java :",
|
"GAME_32BIT_WARNING2": "請下載並安裝最新的64位Java :",
|
||||||
"GAME_32BIT_WARNING3": "https://www.java.com/en/download/",
|
"GAME_32BIT_WARNING3": "https://www.java.com/en/download/",
|
||||||
"MENU_OPTION_STREAMERS_LAYOUT": "聊天疊加",
|
"MENU_OPTIONS_STREAMERS_LAYOUT": "聊天疊加",
|
||||||
"MENU_LABEL_RESTART_REQUIRED": "需要重新啟動",
|
"MENU_LABEL_RESTART_REQUIRED": "需要重新啟動",
|
||||||
"MENU_LABEL_KEYBOARD_LAYOUT": "鍵盤配置",
|
"MENU_LABEL_KEYBOARD_LAYOUT": "鍵盤配置",
|
||||||
"MENU_LABEL_IME": "輸入法",
|
"MENU_LABEL_IME": "輸入法",
|
||||||
|
|||||||
@@ -23,12 +23,12 @@
|
|||||||
"65";"65";"65";"BLOCK_TRUNK_EBONY";"0.0312";"0.0312";"0.0312";"0.0312";"19";"1200";"WOOD";"0";"0";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"TREE,NATURAL"
|
"65";"65";"65";"BLOCK_TRUNK_EBONY";"0.0312";"0.0312";"0.0312";"0.0312";"19";"1200";"WOOD";"0";"0";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"TREE,NATURAL"
|
||||||
"66";"66";"66";"BLOCK_TRUNK_BIRCH";"0.0312";"0.0312";"0.0312";"0.0312";"15";"670";"WOOD";"0";"0";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"TREE,NATURAL"
|
"66";"66";"66";"BLOCK_TRUNK_BIRCH";"0.0312";"0.0312";"0.0312";"0.0312";"15";"670";"WOOD";"0";"0";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"TREE,NATURAL"
|
||||||
"67";"67";"67";"BLOCK_TRUNK_BLOODROSE";"0.0312";"0.0312";"0.0312";"0.0312";"17";"900";"WOOD";"0";"0";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"TREE,NATURAL"
|
"67";"67";"67";"BLOCK_TRUNK_BLOODROSE";"0.0312";"0.0312";"0.0312";"0.0312";"17";"900";"WOOD";"0";"0";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"TREE,NATURAL"
|
||||||
"80";"80";"80";"BLOCK_SAND";"0.1252";"0.1252";"0.1252";"0.1252";"24";"2400";"SAND";"1";"0";"0";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.06";"SAND,NATURAL"
|
"80";"80";"80";"BLOCK_SAND";"0.1252";"0.1252";"0.1252";"0.1252";"24";"2400";"SAND";"1";"0";"0";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.06";"SAND,NATURAL,WARM"
|
||||||
"81";"81";"81";"BLOCK_SAND_WHITE";"0.1252";"0.1252";"0.1252";"0.1252";"24";"2400";"SAND";"1";"0";"0";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.06";"SAND,NATURAL"
|
"81";"81";"81";"BLOCK_SAND_WHITE";"0.1252";"0.1252";"0.1252";"0.1252";"24";"2400";"SAND";"1";"0";"0";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.06";"SAND,NATURAL,WARM"
|
||||||
"82";"82";"82";"BLOCK_SAND_RED";"0.1252";"0.1252";"0.1252";"0.1252";"24";"2400";"SAND";"1";"0";"0";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.06";"SAND,NATURAL"
|
"82";"82";"82";"BLOCK_SAND_RED";"0.1252";"0.1252";"0.1252";"0.1252";"24";"2400";"SAND";"1";"0";"0";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.06";"SAND,NATURAL,WARM"
|
||||||
"83";"83";"83";"BLOCK_SAND_DESERT";"0.1252";"0.1252";"0.1252";"0.1252";"24";"2400";"SAND";"1";"0";"0";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.06";"SAND,NATURAL"
|
"83";"83";"83";"BLOCK_SAND_DESERT";"0.1252";"0.1252";"0.1252";"0.1252";"24";"2400";"SAND";"1";"0";"0";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.06";"SAND,NATURAL,WARM"
|
||||||
"84";"84";"84";"BLOCK_SAND_BLACK";"0.1252";"0.1252";"0.1252";"0.1252";"24";"2400";"SAND";"1";"0";"0";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.06";"SAND,NATURAL"
|
"84";"84";"84";"BLOCK_SAND_BLACK";"0.1252";"0.1252";"0.1252";"0.1252";"24";"2400";"SAND";"1";"0";"0";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.06";"SAND,NATURAL,WARM"
|
||||||
"85";"85";"85";"BLOCK_SAND_GREEN";"0.1252";"0.1252";"0.1252";"0.1252";"24";"2400";"SAND";"1";"0";"0";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.06";"SAND,NATURAL"
|
"85";"85";"85";"BLOCK_SAND_GREEN";"0.1252";"0.1252";"0.1252";"0.1252";"24";"2400";"SAND";"1";"0";"0";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.06";"SAND,NATURAL,WARM"
|
||||||
"96";"96";"96";"BLOCK_GRAVEL";"0.1252";"0.1252";"0.1252";"0.1252";"24";"2400";"GRVL";"1";"0";"0";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GRAVEL,NATURAL"
|
"96";"96";"96";"BLOCK_GRAVEL";"0.1252";"0.1252";"0.1252";"0.1252";"24";"2400";"GRVL";"1";"0";"0";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GRAVEL,NATURAL"
|
||||||
"97";"97";"97";"BLOCK_GRAVEL_GREY";"0.1252";"0.1252";"0.1252";"0.1252";"24";"2400";"GRVL";"1";"0";"0";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GRAVEL,NATURAL"
|
"97";"97";"97";"BLOCK_GRAVEL_GREY";"0.1252";"0.1252";"0.1252";"0.1252";"24";"2400";"GRVL";"1";"0";"0";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GRAVEL,NATURAL"
|
||||||
"112";"112";"112";"BLOCK_ORE_MALACHITE";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"OORE";"1";"0";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"ORE,NATURAL"
|
"112";"112";"112";"BLOCK_ORE_MALACHITE";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"OORE";"1";"0";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"ORE,NATURAL"
|
||||||
@@ -44,10 +44,10 @@
|
|||||||
"132";"132";"132";"BLOCK_GEM_DIAMOND";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"OGEM";"1";"0";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GEM,NATURAL"
|
"132";"132";"132";"BLOCK_GEM_DIAMOND";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"OGEM";"1";"0";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GEM,NATURAL"
|
||||||
"133";"133";"133";"BLOCK_GEM_AMETHYST";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"OGEM";"1";"0";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GEM,NATURAL"
|
"133";"133";"133";"BLOCK_GEM_AMETHYST";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"OGEM";"1";"0";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GEM,NATURAL"
|
||||||
"134";"134";"134";"BLOCK_GEM_QUARTZ";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"OGEM";"1";"0";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GEM,NATURAL"
|
"134";"134";"134";"BLOCK_GEM_QUARTZ";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"OGEM";"1";"0";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GEM,NATURAL"
|
||||||
"144";"144";"144";"BLOCK_SNOW";"0.1252";"0.1252";"0.1252";"0.1252";"24";"500";"SNOW";"1";"1";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"SNOW,NATURAL"
|
"144";"144";"144";"BLOCK_SNOW";"0.1252";"0.1252";"0.1252";"0.1252";"24";"500";"SNOW";"1";"1";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"SNOW,NATURAL,COLD"
|
||||||
"145";"N/A";"N/A";"BLOCK_ICE_FRAGILE";"0.0508";"0.0508";"0.0508";"0.0508";"5";"930";"ICEI";"1";"0";"N/A";"0";"0";"4";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"ICE,NATURAL,FRAGIEL"
|
"145";"N/A";"N/A";"BLOCK_ICE_FRAGILE";"0.0508";"0.0508";"0.0508";"0.0508";"5";"930";"ICEI";"1";"0";"N/A";"0";"0";"4";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"ICE,NATURAL,FRAGILE,COLD"
|
||||||
"146";"146";"146";"BLOCK_ICE_NATURAL";"0.1016";"0.1016";"0.1016";"0.1016";"35";"930";"ICEI";"1";"1";"N/A";"0";"0";"4";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"ICE,NATURAL"
|
"146";"146";"146";"BLOCK_ICE_NATURAL";"0.1016";"0.1016";"0.1016";"0.1016";"35";"930";"ICEI";"1";"1";"N/A";"0";"0";"4";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"ICE,NATURAL,COLD"
|
||||||
"147";"147";"147";"BLOCK_ICE_CLEAR_MAGICAL";"0.1252";"0.1252";"0.1252";"0.1252";"48";"3720";"ICEX";"1";"1";"N/A";"0";"0";"4";"0.0744";"0.1252";"0.2268";"0.0000";"N/A";"N/A";"0.0";"ICE"
|
"147";"147";"147";"BLOCK_ICE_CLEAR_MAGICAL";"0.1252";"0.1252";"0.1252";"0.1252";"48";"3720";"ICEX";"1";"1";"N/A";"0";"0";"4";"0.0744";"0.1252";"0.2268";"0.0000";"N/A";"N/A";"0.0";"ICE,COLD"
|
||||||
"148";"148";"148";"BLOCK_GLASS_CRUDE";"0.0876";"0.0424";"0.0876";"0.1252";"5";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GLASS"
|
"148";"148";"148";"BLOCK_GLASS_CRUDE";"0.0876";"0.0424";"0.0876";"0.1252";"5";"2500";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GLASS"
|
||||||
"149";"149";"149";"BLOCK_GLASS_CLEAN";"0.0424";"0.0424";"0.0424";"0.0636";"5";"2203";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GLASS"
|
"149";"149";"149";"BLOCK_GLASS_CLEAN";"0.0424";"0.0424";"0.0424";"0.0636";"5";"2203";"GLAS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GLASS"
|
||||||
"160";"160";"160";"BLOCK_PLATFORM_STONE";"0.0312";"0.0312";"0.0312";"0.0312";"5";"2400";"ROCK";"0";"0";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"PLATFORM"
|
"160";"160";"160";"BLOCK_PLATFORM_STONE";"0.0312";"0.0312";"0.0312";"0.0312";"5";"2400";"ROCK";"0";"0";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"PLATFORM"
|
||||||
|
|||||||
|
@@ -22,6 +22,8 @@ Seed
|
|||||||
SetAV
|
SetAV
|
||||||
SetBulletin
|
SetBulletin
|
||||||
SetScale
|
SetScale
|
||||||
|
SetSol
|
||||||
|
SetTurb
|
||||||
SetTime
|
SetTime
|
||||||
SetTimeDelta
|
SetTimeDelta
|
||||||
SpawnPhysTestBall
|
SpawnPhysTestBall
|
||||||
|
|||||||
|
@@ -19,5 +19,5 @@
|
|||||||
"GAME_CRAFTABLE_ITEMS": "Craftable Items",
|
"GAME_CRAFTABLE_ITEMS": "Craftable Items",
|
||||||
"MENU_LABEL_RENAME": "Rename",
|
"MENU_LABEL_RENAME": "Rename",
|
||||||
"GAME_ACTION_TELEPORT": "Teleport",
|
"GAME_ACTION_TELEPORT": "Teleport",
|
||||||
"CONTEXT_THIS_IS_A_WORLD_CURRENTLY_PLAYING": "This is a world currently playing."
|
"CONTEXT_PLACE_COORDINATE": "Coordinate"
|
||||||
}
|
}
|
||||||
3
assets/mods/basegame/locales/en/sentences.json
Normal file
3
assets/mods/basegame/locales/en/sentences.json
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"CONTEXT_THIS_IS_A_WORLD_CURRENTLY_PLAYING": "This is a world currently playing."
|
||||||
|
}
|
||||||
@@ -20,5 +20,5 @@
|
|||||||
"GAME_CRAFTABLE_ITEMS": "제작 가능한 아이템",
|
"GAME_CRAFTABLE_ITEMS": "제작 가능한 아이템",
|
||||||
"MENU_LABEL_RENAME": "이름 바꾸기",
|
"MENU_LABEL_RENAME": "이름 바꾸기",
|
||||||
"GAME_ACTION_TELEPORT": "텔레포트하기",
|
"GAME_ACTION_TELEPORT": "텔레포트하기",
|
||||||
"CONTEXT_THIS_IS_A_WORLD_CURRENTLY_PLAYING": "현재 플레이 중인 월드입니다."
|
"CONTEXT_PLACE_COORDINATE": "좌표"
|
||||||
}
|
}
|
||||||
3
assets/mods/basegame/locales/koKR/sentences.json
Normal file
3
assets/mods/basegame/locales/koKR/sentences.json
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"CONTEXT_THIS_IS_A_WORLD_CURRENTLY_PLAYING": "현재 플레이 중인 월드입니다."
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"skyboxGradColourMap": "generic_skybox.tga",
|
"skyboxGradColourMap": "generic_skybox.tga",
|
||||||
|
"daylightClut": "clut_daylight.tga",
|
||||||
"classification": "generic",
|
"classification": "generic",
|
||||||
"extraImages": [
|
"extraImages": [
|
||||||
|
|
||||||
|
|||||||
BIN
assets/mods/basegame/weathers/clut_daylight.tga
LFS
Normal file
BIN
assets/mods/basegame/weathers/clut_daylight.tga
LFS
Normal file
Binary file not shown.
@@ -25,6 +25,7 @@ chmod +x $DESTDIR/AppRun
|
|||||||
# Copy over a Java runtime
|
# Copy over a Java runtime
|
||||||
mkdir $DESTDIR/out
|
mkdir $DESTDIR/out
|
||||||
cp -r "../out/$RUNTIME" $DESTDIR/out/
|
cp -r "../out/$RUNTIME" $DESTDIR/out/
|
||||||
|
mv $DESTDIR/out/$RUNTIME/bin/java $DESTDIR/out/$RUNTIME/bin/Terrarum
|
||||||
|
|
||||||
# Copy over all the assets and a jarfile
|
# Copy over all the assets and a jarfile
|
||||||
cp -r "../assets_release" $DESTDIR/
|
cp -r "../assets_release" $DESTDIR/
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ chmod +x $DESTDIR/AppRun
|
|||||||
# Copy over a Java runtime
|
# Copy over a Java runtime
|
||||||
mkdir $DESTDIR/out
|
mkdir $DESTDIR/out
|
||||||
cp -r "../out/$RUNTIME" $DESTDIR/out/
|
cp -r "../out/$RUNTIME" $DESTDIR/out/
|
||||||
|
mv $DESTDIR/out/$RUNTIME/bin/java $DESTDIR/out/$RUNTIME/bin/Terrarum
|
||||||
|
|
||||||
# Copy over all the assets and a jarfile
|
# Copy over all the assets and a jarfile
|
||||||
cp -r "../assets_release" $DESTDIR/
|
cp -r "../assets_release" $DESTDIR/
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ chmod +x $DESTDIR/Contents/MacOS/Terrarum.sh
|
|||||||
# Copy over a Java runtime
|
# Copy over a Java runtime
|
||||||
mkdir $DESTDIR/Contents/MacOS/out
|
mkdir $DESTDIR/Contents/MacOS/out
|
||||||
cp -r "../out/$RUNTIME" $DESTDIR/Contents/MacOS/out/
|
cp -r "../out/$RUNTIME" $DESTDIR/Contents/MacOS/out/
|
||||||
|
mv $DESTDIR/Contents/MacOS/out/$RUNTIME/bin/java $DESTDIR/Contents/MacOS/out/$RUNTIME/bin/Terrarum
|
||||||
|
|
||||||
# Copy over all the assets and a jarfile
|
# Copy over all the assets and a jarfile
|
||||||
cp -r "../assets_release" $DESTDIR/Contents/MacOS/
|
cp -r "../assets_release" $DESTDIR/Contents/MacOS/
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ chmod +x $DESTDIR/Contents/MacOS/Terrarum.sh
|
|||||||
# Copy over a Java runtime
|
# Copy over a Java runtime
|
||||||
mkdir $DESTDIR/Contents/MacOS/out
|
mkdir $DESTDIR/Contents/MacOS/out
|
||||||
cp -r "../out/$RUNTIME" $DESTDIR/Contents/MacOS/out/
|
cp -r "../out/$RUNTIME" $DESTDIR/Contents/MacOS/out/
|
||||||
|
mv $DESTDIR/Contents/MacOS/out/$RUNTIME/bin/java $DESTDIR/Contents/MacOS/out/$RUNTIME/bin/Terrarum
|
||||||
|
|
||||||
# Copy over all the assets and a jarfile
|
# Copy over all the assets and a jarfile
|
||||||
cp -r "../assets_release" $DESTDIR/Contents/MacOS/
|
cp -r "../assets_release" $DESTDIR/Contents/MacOS/
|
||||||
|
|||||||
@@ -21,11 +21,13 @@ then
|
|||||||
echo 'Mingw32 not found; please install mingw64-cross-gcc (or similar) to your system' >&2; exit 1;
|
echo 'Mingw32 not found; please install mingw64-cross-gcc (or similar) to your system' >&2; exit 1;
|
||||||
fi
|
fi
|
||||||
|
|
||||||
x86_64-w64-mingw32-gcc -o $DESTDIR/Terrarum.exe $SRCFILES/Terrarum.c || { echo 'Building EXE failed' >&2; exit 1; }
|
x86_64-w64-mingw32-gcc -Os -s -o $DESTDIR/Terrarum.exe $SRCFILES/Terrarum.c || { echo 'Building EXE failed' >&2; exit 1; }
|
||||||
|
# TODO add icon to the exe (use x86_64-w64-mingw32-windres?)
|
||||||
|
|
||||||
# Copy over a Java runtime
|
# Copy over a Java runtime
|
||||||
mkdir $DESTDIR/out
|
mkdir $DESTDIR/out
|
||||||
cp -r "../out/$RUNTIME" $DESTDIR/out/
|
cp -r "../out/$RUNTIME" $DESTDIR/out/
|
||||||
|
mv $DESTDIR/out/$RUNTIME/bin/java.exe $DESTDIR/out/$RUNTIME/bin/Terrarum.exe
|
||||||
|
|
||||||
# Copy over all the assets and a jarfile
|
# Copy over all the assets and a jarfile
|
||||||
cp -r "../assets_release" $DESTDIR/
|
cp -r "../assets_release" $DESTDIR/
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
cd "${0%/*}"
|
cd "${0%/*}"
|
||||||
./out/runtime-linux-arm/bin/java -Dswing.aatext=true -Dawt.useSystemAAFontSettings=lcd -jar ./out/TerrarumBuild.jar
|
./out/runtime-linux-arm/bin/Terrarum -Dswing.aatext=true -Dawt.useSystemAAFontSettings=lcd -jar ./out/TerrarumBuild.jar
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
cd "${0%/*}"
|
cd "${0%/*}"
|
||||||
./out/runtime-linux-x86/bin/java -Dswing.aatext=true -Dawt.useSystemAAFontSettings=lcd -jar ./out/TerrarumBuild.jar
|
./out/runtime-linux-x86/bin/Terrarum -Dswing.aatext=true -Dawt.useSystemAAFontSettings=lcd -jar ./out/TerrarumBuild.jar
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
cd "${0%/*}"
|
cd "${0%/*}"
|
||||||
./out/runtime-osx-arm/bin/java -jar ./out/TerrarumBuild.jar
|
./out/runtime-osx-arm/bin/Terrarum -jar ./out/TerrarumBuild.jar
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
cd "${0%/*}"
|
cd "${0%/*}"
|
||||||
./out/runtime-osx-x86/bin/java -jar ./out/TerrarumBuild.jar
|
./out/runtime-osx-x86/bin/Terrarum -jar ./out/TerrarumBuild.jar
|
||||||
|
|||||||
@@ -2,5 +2,5 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
return system(".\\out\\runtime-windows-x86\\bin\\java -jar .\\out\\TerrarumBuild.jar");
|
return system(".\\out\\runtime-windows-x86\\bin\\Terrarum.exe -jar .\\out\\TerrarumBuild.jar");
|
||||||
}
|
}
|
||||||
@@ -166,6 +166,19 @@ final public class FastMath {
|
|||||||
return ((1f - scale) * startValue) + (scale * endValue);
|
return ((1f - scale) * startValue) + (scale * endValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static double interpolateLinear(double scale, double startValue, double endValue) {
|
||||||
|
if (startValue == endValue) {
|
||||||
|
return startValue;
|
||||||
|
}
|
||||||
|
if (scale <= 0.0) {
|
||||||
|
return startValue;
|
||||||
|
}
|
||||||
|
if (scale >= 1.0) {
|
||||||
|
return endValue;
|
||||||
|
}
|
||||||
|
return ((1.0 - scale) * startValue) + (scale * endValue);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Linear interpolation from startValue to endValue by the given percent.
|
* Linear interpolation from startValue to endValue by the given percent.
|
||||||
* Basically: ((1 - percent) * startValue) + (percent * endValue)
|
* Basically: ((1 - percent) * startValue) + (percent * endValue)
|
||||||
@@ -800,28 +813,6 @@ final public class FastMath {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Take a float input and clamp it between min and max.
|
|
||||||
*
|
|
||||||
* @param input
|
|
||||||
* @param min
|
|
||||||
* @param max
|
|
||||||
* @return clamped input
|
|
||||||
*/
|
|
||||||
public static float clamp(float input, float min, float max) {
|
|
||||||
return (input < min) ? min : (input > max) ? max : input;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clamps the given float to be between 0 and 1.
|
|
||||||
*
|
|
||||||
* @param input
|
|
||||||
* @return input clamped between 0 and 1.
|
|
||||||
*/
|
|
||||||
public static float saturate(float input) {
|
|
||||||
return clamp(input, 0f, 1f);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a single precision (32 bit) floating point value
|
* Converts a single precision (32 bit) floating point value
|
||||||
* into half precision (16 bit).
|
* into half precision (16 bit).
|
||||||
@@ -876,31 +867,6 @@ final public class FastMath {
|
|||||||
| ((((f & 0x7f800000) - 0x38000000) >> 13) & 0x7c00)
|
| ((((f & 0x7f800000) - 0x38000000) >> 13) & 0x7c00)
|
||||||
| ((f >> 13) & 0x03ff));
|
| ((f >> 13) & 0x03ff));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float min(float... f) {
|
|
||||||
float min = f[0];
|
|
||||||
for (int i = 1; i < f.length; i++) min = (f[i] < min) ? f[i] : min;
|
|
||||||
return min;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static float max(float... f) {
|
|
||||||
float max = f[0];
|
|
||||||
for (int i = 1; i < f.length; i++) max = (f[i] > max) ? f[i] : max;
|
|
||||||
return max;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int min(int... f) {
|
|
||||||
int min = f[0];
|
|
||||||
for (int i = 1; i < f.length; i++) min = (f[i] < min) ? f[i] : min;
|
|
||||||
return min;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int max(int... f) {
|
|
||||||
int max = f[0];
|
|
||||||
for (int i = 1; i < f.length; i++) max = (f[i] > max) ? f[i] : max;
|
|
||||||
return max;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int getGCD(int a, int b) {
|
public static int getGCD(int a, int b) {
|
||||||
while (a != b) {
|
while (a != b) {
|
||||||
if (a > b) a = a-b;
|
if (a > b) a = a-b;
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ fun Color.toXYZ(): CIEXYZ = RGB(this).toXYZ()
|
|||||||
}
|
}
|
||||||
val step = value.clampOne() * 255f // 0.0 .. 255.0
|
val step = value.clampOne() * 255f // 0.0 .. 255.0
|
||||||
val intStep = step.toInt() // 0 .. 255
|
val intStep = step.toInt() // 0 .. 255
|
||||||
val NeXTSTEP = minOf(intStep + 1, 255) // 1 .. 255
|
val NeXTSTEP = min(intStep + 1, 255) // 1 .. 255
|
||||||
|
|
||||||
out[i] = interpolateLinear(step - intStep, rgbLinLUT[intStep], rgbLinLUT[NeXTSTEP])
|
out[i] = interpolateLinear(step - intStep, rgbLinLUT[intStep], rgbLinLUT[NeXTSTEP])
|
||||||
}
|
}
|
||||||
@@ -123,7 +123,7 @@ fun RGB.linearise(): RGB {
|
|||||||
}
|
}
|
||||||
val step = value.clampOne() * 255f // 0.0 .. 255.0
|
val step = value.clampOne() * 255f // 0.0 .. 255.0
|
||||||
val intStep = step.toInt() // 0 .. 255
|
val intStep = step.toInt() // 0 .. 255
|
||||||
val NeXTSTEP = minOf(intStep + 1, 255) // 1 .. 255
|
val NeXTSTEP = min(intStep + 1, 255) // 1 .. 255
|
||||||
|
|
||||||
out[i] = interpolateLinear(step - intStep, rgbUnLinLUT[intStep], rgbUnLinLUT[NeXTSTEP])
|
out[i] = interpolateLinear(step - intStep, rgbUnLinLUT[intStep], rgbUnLinLUT[NeXTSTEP])
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package net.torvald.colourutil
|
|||||||
|
|
||||||
import com.jme3.math.FastMath
|
import com.jme3.math.FastMath
|
||||||
import com.badlogic.gdx.graphics.Color
|
import com.badlogic.gdx.graphics.Color
|
||||||
|
import kotlin.math.max
|
||||||
|
import kotlin.math.min
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OBSOLETE; use CIELchUtil for natural-looking colour
|
* OBSOLETE; use CIELchUtil for natural-looking colour
|
||||||
@@ -75,8 +77,8 @@ object HSVUtil {
|
|||||||
val g = color.g
|
val g = color.g
|
||||||
val b = color.b
|
val b = color.b
|
||||||
|
|
||||||
val rgbMin = FastMath.min(r, g, b)
|
val rgbMin = min(min(r, g), b)
|
||||||
val rgbMax = FastMath.max(r, g, b)
|
val rgbMax = max(max(r, g), b)
|
||||||
|
|
||||||
var h: Float
|
var h: Float
|
||||||
val s: Float
|
val s: Float
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ public class HUSLColorConverter {
|
|||||||
float x = intersectLineLine(line, new float[]{-1 / m1, 0});
|
float x = intersectLineLine(line, new float[]{-1 / m1, 0});
|
||||||
float length = distanceFromPole(new float[]{x, b1 + x * m1});
|
float length = distanceFromPole(new float[]{x, b1 + x * m1});
|
||||||
|
|
||||||
min = FastMath.min(min, length);
|
min = Math.min(min, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
return min;
|
return min;
|
||||||
@@ -125,7 +125,7 @@ public class HUSLColorConverter {
|
|||||||
for (float[] bound : bounds) {
|
for (float[] bound : bounds) {
|
||||||
Length length = lengthOfRayUntilIntersect(hrad, bound);
|
Length length = lengthOfRayUntilIntersect(hrad, bound);
|
||||||
if (length.greaterEqualZero) {
|
if (length.greaterEqualZero) {
|
||||||
min = FastMath.min(min, length.length);
|
min = Math.min(min, length.length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -55,6 +55,13 @@ class Cvec {
|
|||||||
this.a = color.a
|
this.a = color.a
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constructor(rgb: Color, alpha: Float) {
|
||||||
|
this.r = rgb.r
|
||||||
|
this.g = rgb.g
|
||||||
|
this.b = rgb.b
|
||||||
|
this.a = alpha
|
||||||
|
}
|
||||||
|
|
||||||
/** Constructor, sets the components of the color
|
/** Constructor, sets the components of the color
|
||||||
*
|
*
|
||||||
* @param r the red component
|
* @param r the red component
|
||||||
|
|||||||
@@ -104,10 +104,10 @@ internal class UnsafeCvecArray(val width: Int, val height: Int) {
|
|||||||
// operators
|
// operators
|
||||||
fun max(x: Int, y: Int, other: Cvec) {
|
fun max(x: Int, y: Int, other: Cvec) {
|
||||||
val a = toAddr(x, y)
|
val a = toAddr(x, y)
|
||||||
array.setFloat(a + 0, maxOf(array.getFloat(a + 0), other.r))
|
array.setFloat(a + 0, kotlin.math.max(array.getFloat(a + 0), other.r))
|
||||||
array.setFloat(a + 1, maxOf(array.getFloat(a + 1), other.g))
|
array.setFloat(a + 1, kotlin.math.max(array.getFloat(a + 1), other.g))
|
||||||
array.setFloat(a + 2, maxOf(array.getFloat(a + 2), other.b))
|
array.setFloat(a + 2, kotlin.math.max(array.getFloat(a + 2), other.b))
|
||||||
array.setFloat(a + 3, maxOf(array.getFloat(a + 3), other.a))
|
array.setFloat(a + 3, kotlin.math.max(array.getFloat(a + 3), other.a))
|
||||||
}
|
}
|
||||||
fun mul(x: Int, y: Int, scalar: Float) {
|
fun mul(x: Int, y: Int, scalar: Float) {
|
||||||
val a = toAddr(x, y)
|
val a = toAddr(x, y)
|
||||||
@@ -202,10 +202,10 @@ internal class TestCvecArr(val width: Int, val height: Int) {
|
|||||||
|
|
||||||
// operators
|
// operators
|
||||||
inline fun max(x: Int, y: Int, other: Cvec) {
|
inline fun max(x: Int, y: Int, other: Cvec) {
|
||||||
setR(x, y, maxOf(getR(x, y), other.r))
|
setR(x, y, kotlin.math.max(getR(x, y), other.r))
|
||||||
setG(x, y, maxOf(getG(x, y), other.g))
|
setG(x, y, kotlin.math.max(getG(x, y), other.g))
|
||||||
setB(x, y, maxOf(getB(x, y), other.b))
|
setB(x, y, kotlin.math.max(getB(x, y), other.b))
|
||||||
setA(x, y, maxOf(getA(x, y), other.a))
|
setA(x, y, kotlin.math.max(getA(x, y), other.a))
|
||||||
}
|
}
|
||||||
inline fun mul(x: Int, y: Int, scalar: Float) {
|
inline fun mul(x: Int, y: Int, scalar: Float) {
|
||||||
setR(x, y, getR(x, y) * scalar)
|
setR(x, y, getR(x, y) * scalar)
|
||||||
|
|||||||
@@ -14,22 +14,36 @@ import net.torvald.colourutil.*
|
|||||||
import net.torvald.parametricsky.datasets.DatasetCIEXYZ
|
import net.torvald.parametricsky.datasets.DatasetCIEXYZ
|
||||||
import net.torvald.parametricsky.datasets.DatasetRGB
|
import net.torvald.parametricsky.datasets.DatasetRGB
|
||||||
import net.torvald.parametricsky.datasets.DatasetSpectral
|
import net.torvald.parametricsky.datasets.DatasetSpectral
|
||||||
|
import net.torvald.terrarum.abs
|
||||||
import net.torvald.terrarum.inUse
|
import net.torvald.terrarum.inUse
|
||||||
import net.torvald.terrarum.modulebasegame.worldgenerator.HALF_PI
|
import net.torvald.terrarum.modulebasegame.worldgenerator.HALF_PI
|
||||||
import net.torvald.terrarum.modulebasegame.worldgenerator.TWO_PI
|
import net.torvald.terrarum.modulebasegame.worldgenerator.TWO_PI
|
||||||
|
import java.awt.BorderLayout
|
||||||
import java.awt.Dimension
|
import java.awt.Dimension
|
||||||
|
import java.awt.FlowLayout
|
||||||
|
import java.awt.GridLayout
|
||||||
|
import java.lang.Math.pow
|
||||||
import javax.swing.*
|
import javax.swing.*
|
||||||
import kotlin.math.PI
|
import kotlin.math.*
|
||||||
import kotlin.math.pow
|
|
||||||
|
|
||||||
|
|
||||||
const val WIDTH = 1200
|
val INITIAL_TURBIDITY = 4.0
|
||||||
const val HEIGHT = 600
|
val INITIAL_ALBEDO = 0.1
|
||||||
|
val INITIAL_ELEV = 0.0
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2018-08-01.
|
* Created by minjaesong on 2018-08-01.
|
||||||
*/
|
*/
|
||||||
class Application : Game() {
|
class Application(val WIDTH: Int, val HEIGHT: Int) : Game() {
|
||||||
|
|
||||||
|
private val HW = WIDTH / 2
|
||||||
|
private val HH = HEIGHT / 2
|
||||||
|
|
||||||
|
private val wf = WIDTH.toFloat()
|
||||||
|
private val hf = HEIGHT.toFloat()
|
||||||
|
private val hwf = HW.toFloat()
|
||||||
|
// private val hhf = HH.toFloat()
|
||||||
|
|
||||||
/* Variables:
|
/* Variables:
|
||||||
* 1. Canvas Y (theta)
|
* 1. Canvas Y (theta)
|
||||||
@@ -53,12 +67,12 @@ class Application : Game() {
|
|||||||
private lateinit var oneScreen: Pixmap
|
private lateinit var oneScreen: Pixmap
|
||||||
private lateinit var batch: SpriteBatch
|
private lateinit var batch: SpriteBatch
|
||||||
|
|
||||||
private lateinit var testTex: Texture
|
var turbidity = INITIAL_TURBIDITY
|
||||||
|
var albedo = INITIAL_ALBEDO
|
||||||
|
var elevation = Math.toRadians(INITIAL_ELEV)
|
||||||
|
|
||||||
var turbidity = 5.0
|
var solarBearing = Math.toRadians(90.0)
|
||||||
var albedo = 0.1
|
var cameraHeading = Math.toRadians(90.0)
|
||||||
var elevation = 0.0
|
|
||||||
var scalefactor = 1f
|
|
||||||
|
|
||||||
override fun getScreen(): Screen {
|
override fun getScreen(): Screen {
|
||||||
return super.getScreen()
|
return super.getScreen()
|
||||||
@@ -68,20 +82,29 @@ class Application : Game() {
|
|||||||
super.setScreen(screen)
|
super.setScreen(screen)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var model = ArHosekSkyModel.arhosek_xyz_skymodelstate_alloc_init(turbidity, albedo, elevation.abs())
|
||||||
|
|
||||||
|
fun regenerateModel() {
|
||||||
|
model = ArHosekSkyModel.arhosek_xyz_skymodelstate_alloc_init(turbidity, albedo, elevation.abs())
|
||||||
|
}
|
||||||
|
|
||||||
override fun render() {
|
override fun render() {
|
||||||
Gdx.graphics.setTitle("Daylight Model $EMDASH F: ${Gdx.graphics.framesPerSecond}")
|
Gdx.graphics.setTitle("Daylight Model $EMDASH F: ${Gdx.graphics.framesPerSecond}")
|
||||||
|
|
||||||
if (turbidity <= 0) throw IllegalStateException()
|
if (turbidity <= 0) throw IllegalStateException()
|
||||||
|
|
||||||
// we need to use different modelstate to accomodate different albedo for each spectral band but oh well...
|
// we need to use different model-state to accommodate different albedo for each spectral band but oh well...
|
||||||
genTexLoop(ArHosekSkyModel.arhosek_xyz_skymodelstate_alloc_init(turbidity, albedo, elevation))
|
genTexLoop(model)
|
||||||
|
|
||||||
|
|
||||||
val tex = Texture(oneScreen)
|
val tex = Texture(oneScreen)
|
||||||
tex.setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest)
|
tex.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear)
|
||||||
|
|
||||||
batch.inUse {
|
batch.inUse {
|
||||||
batch.draw(tex, 0f, 0f, WIDTH.toFloat(), HEIGHT.toFloat())
|
// batch.draw(tex, hwf, 0f, hwf, hf)
|
||||||
|
// batch.draw(tex, hwf, 0f, -hwf, hf)
|
||||||
|
|
||||||
|
batch.draw(tex, 0f, 0f, wf, hf)
|
||||||
}
|
}
|
||||||
|
|
||||||
tex.dispose()
|
tex.dispose()
|
||||||
@@ -103,9 +126,37 @@ class Application : Game() {
|
|||||||
oneScreen.dispose()
|
oneScreen.dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
val outTexWidth = 256
|
val outTexWidth = 1
|
||||||
val outTexHeight = 256
|
val outTexHeight = 256
|
||||||
|
|
||||||
|
private fun Float.scaleFun() =
|
||||||
|
(1f - 1f / 2f.pow(this/6f)) * 0.97f
|
||||||
|
|
||||||
|
private fun CIEXYZ.scaleToFit(elevation: Double): CIEXYZ {
|
||||||
|
return if (elevation >= 0) {
|
||||||
|
CIEXYZ(
|
||||||
|
this.X.scaleFun(),
|
||||||
|
this.Y.scaleFun(),
|
||||||
|
this.Z.scaleFun(),
|
||||||
|
this.alpha
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
val elevation1 = -Math.toDegrees(elevation)
|
||||||
|
val elevation2 = -Math.toDegrees(elevation) / 28.5
|
||||||
|
val scale = (1f - (1f - 1f / 1.8.pow(elevation1)) * 0.97f).toFloat()
|
||||||
|
val scale2 = (1.0 - (elevation2.pow(E) / E.pow(elevation2))*0.8).toFloat()
|
||||||
|
CIEXYZ(
|
||||||
|
this.X.scaleFun() * scale * scale2,
|
||||||
|
this.Y.scaleFun() * scale * scale2,
|
||||||
|
this.Z.scaleFun() * scale * scale2,
|
||||||
|
this.alpha
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Double.mapCircle() = sin(HALF_PI * this)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generated texture is as if you took the panorama picture of sky: up 70deg to horizon, east-south-west;
|
* Generated texture is as if you took the panorama picture of sky: up 70deg to horizon, east-south-west;
|
||||||
* with sun not moving (sun is at exact south, sun's height is adjustable)
|
* with sun not moving (sun is at exact south, sun's height is adjustable)
|
||||||
@@ -120,20 +171,46 @@ class Application : Game() {
|
|||||||
return v.toFloat()
|
return v.toFloat()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val ys = ArrayList<Float>()
|
||||||
|
val ys2 = ArrayList<Float>()
|
||||||
|
|
||||||
|
val halfHeight = oneScreen.height * 0.5
|
||||||
|
|
||||||
|
for (x in 0 until oneScreen.width) {
|
||||||
|
for (y in 0 until oneScreen.height) {
|
||||||
|
|
||||||
|
// sky-sphere mapping
|
||||||
|
/*val xf = ((x + 0.5) / oneScreen.width) * 2.0 - 1.0
|
||||||
|
val yf = ((y + 0.5) / oneScreen.height) * 2.0 - 1.0
|
||||||
|
val gamma = atan2(yf, xf) + PI
|
||||||
|
val theta = sqrt(xf*xf + yf*yf) * HALF_PI*/
|
||||||
|
|
||||||
|
// AM-PM mapping (use with WIDTH=1)
|
||||||
|
var yf = (y * 2.0 / oneScreen.height) % 1.0
|
||||||
|
if (elevation < 0) yf *= 1.0 - pow(-elevation / HALF_PI, 0.333)
|
||||||
|
val gamma = if (y < halfHeight) HALF_PI else 3 * HALF_PI
|
||||||
|
val theta = yf.mapCircle() * HALF_PI
|
||||||
|
|
||||||
|
|
||||||
for (y in 0 until oneScreen.height) {
|
|
||||||
for (x in 0 until oneScreen.width) {
|
|
||||||
val gamma = (x / oneScreen.width.toDouble()) * TWO_PI // 0deg..360deg
|
|
||||||
val theta = (1.0 - (y / oneScreen.height.toDouble())) * HALF_PI // 90deg..0deg
|
|
||||||
|
|
||||||
val xyz = CIEXYZ(
|
val xyz = CIEXYZ(
|
||||||
ArHosekSkyModel.arhosek_tristim_skymodel_radiance(state, theta, gamma, 0).toFloat().times(scalefactor / 10f),
|
ArHosekSkyModel.arhosek_tristim_skymodel_radiance(state, theta, gamma, 0).toFloat(),
|
||||||
ArHosekSkyModel.arhosek_tristim_skymodel_radiance(state, theta, gamma, 1).toFloat().times(scalefactor / 10f),
|
ArHosekSkyModel.arhosek_tristim_skymodel_radiance(state, theta, gamma, 1).toFloat(),
|
||||||
ArHosekSkyModel.arhosek_tristim_skymodel_radiance(state, theta, gamma, 2).toFloat().times(scalefactor / 10f)
|
ArHosekSkyModel.arhosek_tristim_skymodel_radiance(state, theta, gamma, 2).toFloat()
|
||||||
)
|
)
|
||||||
val rgb = xyz.toRGB().toColor()
|
val xyz2 = xyz.scaleToFit(elevation)
|
||||||
|
ys.add(xyz.Y)
|
||||||
|
ys2.add(xyz2.Y)
|
||||||
|
val rgb = xyz2.toRGB().toColor()
|
||||||
rgb.a = 1f
|
rgb.a = 1f
|
||||||
|
|
||||||
|
val rgb2 = Color(
|
||||||
|
((rgb.r * 255f).roundToInt() xor 0xAA) / 255f,
|
||||||
|
((rgb.g * 255f).roundToInt() xor 0xAA) / 255f,
|
||||||
|
((rgb.b * 255f).roundToInt() xor 0xAA) / 255f,
|
||||||
|
rgb.a
|
||||||
|
)
|
||||||
|
|
||||||
oneScreen.setColor(rgb)
|
oneScreen.setColor(rgb)
|
||||||
oneScreen.drawPixel(x, y)
|
oneScreen.drawPixel(x, y)
|
||||||
|
|
||||||
@@ -142,140 +219,148 @@ class Application : Game() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ymaxDisp.text = "${ys.max()}"
|
||||||
|
ymaxDisp2.text = "${ys2.max()}"
|
||||||
|
|
||||||
//System.exit(0)
|
//System.exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Generated texture is as if you took the panorama picture of sky: up 70deg to horizon, east-south-west;
|
|
||||||
* with sun not moving (sun is at exact south, sun's height is adjustable)
|
|
||||||
*/
|
|
||||||
/*private fun genTexLoop2(T: Double, theta_s: Double) {
|
|
||||||
|
|
||||||
fun hazeFun(T: Double): Double {
|
|
||||||
val T = T - 1
|
|
||||||
if (T >= 10) return 1.0
|
|
||||||
else return 2.0.pow(T).div(1024.0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// loop thru gamma and theta
|
|
||||||
for (y in 0..outTexDim) { // theta
|
|
||||||
for (x in 0..outTexDim) { // gamma
|
|
||||||
val theta = Math.toRadians(y * (90.0 / outTexDim.toDouble())) // of observer
|
|
||||||
val gamma = Math.toRadians(x * (90.0 / outTexDim.toDouble())) // of observer
|
|
||||||
|
|
||||||
val Y_z = Model.getAbsoluteZenithLuminance(T, theta_s)
|
|
||||||
val x_z = Model.getZenithChromaX(T, theta_s)
|
|
||||||
val y_z = Model.getZenithChromaY(T, theta_s)
|
|
||||||
|
|
||||||
val Y_p = Y_z * Model.getFforLuma(theta, gamma, T) / Model.getFforLuma(0.0, theta_s, T)
|
|
||||||
val Y_oc = Y_z * (1.0 + 2.0 * Math.cos(theta)) / 3.0
|
|
||||||
val x_p = (x_z * Model.getFforChromaX(theta, gamma, T) / Model.getFforChromaX(0.0, theta_s, T)).coerceIn(0.0, 1.0)
|
|
||||||
val y_p = (y_z * Model.getFforChromaY(theta, gamma, T) / Model.getFforChromaY(0.0, theta_s, T)).coerceIn(0.0, 1.0)
|
|
||||||
|
|
||||||
val normalisedY = Y_p.toFloat().pow(0.5f).div(10f)
|
|
||||||
val normalisedY_oc = Y_oc.toFloat().pow(0.5f).div(10f)
|
|
||||||
|
|
||||||
//println("$Y_p -> $normalisedY, $x_p, $y_p")
|
|
||||||
|
|
||||||
if (T < 11) {
|
|
||||||
val rgbColour = CIEYXY(normalisedY, x_p.toFloat(), y_p.toFloat()).toXYZ().toColorRaw()
|
|
||||||
val hazeColour = CIEYXY(normalisedY_oc, 0.3128f, 0.3290f).toXYZ().toColorRaw()
|
|
||||||
|
|
||||||
val hazeAmount = hazeFun(T).toFloat()
|
|
||||||
val newColour = Color(
|
|
||||||
FastMath.interpolateLinear(hazeAmount, rgbColour.r, hazeColour.r),
|
|
||||||
FastMath.interpolateLinear(hazeAmount, rgbColour.g, hazeColour.g),
|
|
||||||
FastMath.interpolateLinear(hazeAmount, rgbColour.b, hazeColour.b),
|
|
||||||
1f
|
|
||||||
)
|
|
||||||
|
|
||||||
oneScreen.setColor(newColour)
|
|
||||||
oneScreen.drawPixel(x, y)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
val hazeColour = CIEYXY(normalisedY_oc, 0.3128f, 0.3290f).toXYZ().toColorRaw()
|
|
||||||
oneScreen.setColor(hazeColour)
|
|
||||||
oneScreen.drawPixel(x, y)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// end loop
|
|
||||||
}*/
|
|
||||||
|
|
||||||
override fun create() {
|
override fun create() {
|
||||||
batch = SpriteBatch()
|
batch = SpriteBatch()
|
||||||
testTex = Texture(Gdx.files.internal("assets/test_texture.tga"))
|
|
||||||
|
|
||||||
oneScreen = Pixmap(outTexWidth * 2, outTexHeight, Pixmap.Format.RGBA8888)
|
oneScreen = Pixmap(outTexWidth, outTexHeight, Pixmap.Format.RGBA8888)
|
||||||
|
|
||||||
DatasetSpectral
|
// DatasetSpectral
|
||||||
DatasetCIEXYZ
|
DatasetCIEXYZ
|
||||||
DatasetRGB
|
// DatasetRGB
|
||||||
|
|
||||||
ApplicationController(this)
|
ApplicationController(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val ymaxDisp = JTextField().also {
|
||||||
|
it.preferredSize = Dimension(64, 20)
|
||||||
|
}
|
||||||
|
val ymaxDisp2 = JTextField().also {
|
||||||
|
it.preferredSize = Dimension(64, 20)
|
||||||
|
}
|
||||||
|
|
||||||
|
class ApplicationController(val app: Application) : JFrame() {
|
||||||
|
|
||||||
class ApplicationController(app: Application) : JFrame() {
|
val dialSize = Dimension(45, 20)
|
||||||
|
|
||||||
val mainPanel = JPanel()
|
val turbidityControl = JSpinner(SpinnerNumberModel(INITIAL_TURBIDITY, 1.0, 10.0, 0.1)).also {
|
||||||
|
it.preferredSize = dialSize
|
||||||
val turbidityControl = JSpinner(SpinnerNumberModel(5.0, 1.0, 10.0, 0.1))
|
it.addChangeListener { _ ->
|
||||||
val albedoControl = JSpinner(SpinnerNumberModel(0.1, 0.0, 1.0, 0.05))
|
app.turbidity = it.value as Double
|
||||||
val elevationControl = JSpinner(SpinnerNumberModel(0.0, 0.0, 90.0, 0.5))
|
app.regenerateModel()
|
||||||
val scalefactorControl = JSpinner(SpinnerNumberModel(1.0, 0.0, 2.0, 0.01))
|
}
|
||||||
|
}
|
||||||
|
val albedoControl = JSpinner(SpinnerNumberModel(INITIAL_ALBEDO, 0.0, 1.0, 0.05)).also {
|
||||||
|
it.preferredSize = dialSize
|
||||||
|
it.addChangeListener { _ ->
|
||||||
|
app.albedo = it.value as Double
|
||||||
|
app.regenerateModel()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val elevationControl = JSpinner(SpinnerNumberModel(INITIAL_ELEV, -75.0, 75.0, 0.5)).also {
|
||||||
|
it.preferredSize = dialSize
|
||||||
|
it.addChangeListener { _ ->
|
||||||
|
app.elevation = Math.toRadians(it.value as Double)
|
||||||
|
app.regenerateModel()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val solarBearing = JSpinner(SpinnerNumberModel(90.0, 0.0, 180.0, 1.0)).also {
|
||||||
|
it.preferredSize = dialSize
|
||||||
|
it.addChangeListener { _ ->
|
||||||
|
app.solarBearing = (it.value as Double)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val cameraHeading = JSpinner(SpinnerNumberModel(90.0, 0.0, 180.0, 1.0)).also {
|
||||||
|
it.preferredSize = dialSize
|
||||||
|
it.addChangeListener { _ ->
|
||||||
|
app.cameraHeading = (it.value as Double)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
val turbidityPanel = JPanel()
|
val atmosPanel = JPanel()
|
||||||
val albedoPanel = JPanel()
|
val turbidityPanel = JPanel().also {
|
||||||
val elevationPanel = JPanel()
|
it.add(JLabel("Turbidity (log_2)"))
|
||||||
val scalefactorPanel = JPanel()
|
it.add(turbidityControl)
|
||||||
|
atmosPanel.add(it)
|
||||||
|
}
|
||||||
|
val albedoPanel = JPanel().also {
|
||||||
|
it.add(JLabel("Albedo"))
|
||||||
|
it.add(albedoControl)
|
||||||
|
atmosPanel.add(it)
|
||||||
|
}
|
||||||
|
|
||||||
turbidityControl.preferredSize = Dimension(45, 18)
|
val sunPanel = JPanel()
|
||||||
albedoControl.preferredSize = Dimension(45, 18)
|
val elevationPanel = JPanel().also {
|
||||||
elevationControl.preferredSize = Dimension(45, 18)
|
it.add(JLabel("Elevation"))
|
||||||
scalefactorControl.preferredSize = Dimension(45, 18)
|
it.add(elevationControl)
|
||||||
|
sunPanel.add(it)
|
||||||
|
}
|
||||||
|
val scalefactorPanel = JPanel().also {
|
||||||
|
it.add(JLabel("Bearing"))
|
||||||
|
it.add(solarBearing)
|
||||||
|
sunPanel.add(it)
|
||||||
|
}
|
||||||
|
|
||||||
turbidityPanel.add(JLabel("Turbidity"))
|
val cameraPanel = JPanel()
|
||||||
turbidityPanel.add(turbidityControl)
|
val headingPanel = JPanel().also {
|
||||||
|
it.add(JLabel("Heading"))
|
||||||
|
it.add(cameraHeading)
|
||||||
|
cameraPanel.add(it)
|
||||||
|
}
|
||||||
|
|
||||||
albedoPanel.add(JLabel("Albedo"))
|
val statsPanel = JPanel()
|
||||||
albedoPanel.add(albedoControl)
|
val ymaxPanel = JPanel().also {
|
||||||
|
it.add(JLabel("Ymax (CIEXYZ)"))
|
||||||
|
it.add(app.ymaxDisp)
|
||||||
|
statsPanel.add(it)
|
||||||
|
}
|
||||||
|
val ymaxPanel2 = JPanel().also {
|
||||||
|
it.add(JLabel("Ymax (scaled)"))
|
||||||
|
it.add(app.ymaxDisp2)
|
||||||
|
statsPanel.add(it)
|
||||||
|
}
|
||||||
|
|
||||||
elevationPanel.add(JLabel("Elevation"))
|
val mainPanel = JPanel()
|
||||||
elevationPanel.add(elevationControl)
|
|
||||||
|
|
||||||
scalefactorPanel.add(JLabel("Scaling Factor"))
|
mainPanel.layout = BoxLayout(mainPanel, BoxLayout.Y_AXIS)
|
||||||
scalefactorPanel.add(scalefactorControl)
|
JPanel().also {
|
||||||
|
it.layout = BorderLayout()
|
||||||
mainPanel.add(turbidityPanel)
|
it.add(JPanel().also { it.add(JLabel("Atmosphere")) }, BorderLayout.NORTH)
|
||||||
mainPanel.add(albedoPanel)
|
it.add(atmosPanel, BorderLayout.CENTER)
|
||||||
mainPanel.add(elevationPanel)
|
it.add(JSeparator(), BorderLayout.SOUTH)
|
||||||
mainPanel.add(scalefactorPanel)
|
mainPanel.add(it)
|
||||||
|
}
|
||||||
|
JPanel().also {
|
||||||
|
it.layout = BorderLayout()
|
||||||
|
it.add(JPanel().also { it.add(JLabel("Sun")) }, BorderLayout.NORTH)
|
||||||
|
it.add(sunPanel, BorderLayout.CENTER)
|
||||||
|
it.add(JSeparator(), BorderLayout.SOUTH)
|
||||||
|
mainPanel.add(it)
|
||||||
|
}
|
||||||
|
JPanel().also {
|
||||||
|
it.layout = BorderLayout()
|
||||||
|
it.add(JPanel().also { it.add(JLabel("Camera")) }, BorderLayout.NORTH)
|
||||||
|
it.add(cameraPanel, BorderLayout.CENTER)
|
||||||
|
it.add(JSeparator(), BorderLayout.SOUTH)
|
||||||
|
mainPanel.add(it)
|
||||||
|
}
|
||||||
|
JPanel().also {
|
||||||
|
it.layout = BorderLayout()
|
||||||
|
it.add(JPanel().also { it.add(JLabel("Statistics")) }, BorderLayout.NORTH)
|
||||||
|
it.add(statsPanel, BorderLayout.CENTER)
|
||||||
|
mainPanel.add(it)
|
||||||
|
}
|
||||||
|
|
||||||
this.isVisible = true
|
this.isVisible = true
|
||||||
this.defaultCloseOperation = WindowConstants.EXIT_ON_CLOSE
|
this.defaultCloseOperation = WindowConstants.EXIT_ON_CLOSE
|
||||||
this.size = Dimension(300, 400)
|
this.size = Dimension(300, 600)
|
||||||
|
this.add(mainPanel, BorderLayout.CENTER)
|
||||||
this.add(mainPanel)
|
|
||||||
|
|
||||||
|
|
||||||
turbidityControl.addChangeListener {
|
|
||||||
app.turbidity = turbidityControl.value as Double
|
|
||||||
}
|
|
||||||
|
|
||||||
albedoControl.addChangeListener {
|
|
||||||
app.albedo = albedoControl.value as Double
|
|
||||||
}
|
|
||||||
|
|
||||||
elevationControl.addChangeListener {
|
|
||||||
app.elevation = Math.toRadians(elevationControl.value as Double)
|
|
||||||
}
|
|
||||||
|
|
||||||
scalefactorControl.addChangeListener {
|
|
||||||
app.scalefactor = (scalefactorControl.value as Double).toFloat()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -285,7 +370,10 @@ class Application : Game() {
|
|||||||
|
|
||||||
fun main(args: Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
val config = Lwjgl3ApplicationConfiguration()
|
val config = Lwjgl3ApplicationConfiguration()
|
||||||
config.setWindowedMode(WIDTH, HEIGHT)
|
|
||||||
|
|
||||||
Lwjgl3Application(Application(), config)
|
val WIDTH = 2048
|
||||||
|
val HEIGHT = 2048
|
||||||
|
|
||||||
|
config.setWindowedMode(WIDTH, HEIGHT)
|
||||||
|
Lwjgl3Application(Application(WIDTH, HEIGHT), config)
|
||||||
}
|
}
|
||||||
@@ -11,8 +11,8 @@ object DatasetOp {
|
|||||||
val entrysize = file.length().toInt() / 8
|
val entrysize = file.length().toInt() / 8
|
||||||
val fis = FileInputStream(file)
|
val fis = FileInputStream(file)
|
||||||
|
|
||||||
|
val inputbuf = ByteArray(8)
|
||||||
val ret = DoubleArray(entrysize) {
|
val ret = DoubleArray(entrysize) {
|
||||||
val inputbuf = ByteArray(8)
|
|
||||||
fis.read(inputbuf)
|
fis.read(inputbuf)
|
||||||
val rawnum = inputbuf.toLittleInt64()
|
val rawnum = inputbuf.toLittleInt64()
|
||||||
Double.fromBits(rawnum)
|
Double.fromBits(rawnum)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package net.torvald.random
|
package net.torvald.random
|
||||||
|
|
||||||
import com.jme3.math.FastMath
|
import com.jme3.math.FastMath
|
||||||
import net.torvald.terrarum.floorInt
|
import net.torvald.terrarum.floorToInt
|
||||||
import net.torvald.terrarum.gameworld.fmod
|
import net.torvald.terrarum.gameworld.fmod
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@@ -45,9 +45,9 @@ class TileableValueNoise(
|
|||||||
try {
|
try {
|
||||||
for (x in 0..width) {
|
for (x in 0..width) {
|
||||||
val thisSampleStart: Int = // 0-256 -> 0-4 -> 0-256(qnt)
|
val thisSampleStart: Int = // 0-256 -> 0-4 -> 0-256(qnt)
|
||||||
(x / width.toFloat() * samples).floorInt() * (width / samples)
|
(x / width.toFloat() * samples).floorToInt() * (width / samples)
|
||||||
val nextSampleStart: Int =
|
val nextSampleStart: Int =
|
||||||
(x / width.toFloat() * samples).floorInt().plus(1) * (width / samples)
|
(x / width.toFloat() * samples).floorToInt().plus(1) * (width / samples)
|
||||||
val stepWithinWindow: Int = x % (nextSampleStart - thisSampleStart)
|
val stepWithinWindow: Int = x % (nextSampleStart - thisSampleStart)
|
||||||
val windowScale: Float = stepWithinWindow.toFloat() / (width / samples)
|
val windowScale: Float = stepWithinWindow.toFloat() / (width / samples)
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import com.badlogic.gdx.graphics.g2d.TextureRegion
|
|||||||
import com.badlogic.gdx.utils.GdxRuntimeException
|
import com.badlogic.gdx.utils.GdxRuntimeException
|
||||||
import net.torvald.terrarum.ItemCodex
|
import net.torvald.terrarum.ItemCodex
|
||||||
import net.torvald.terrarum.Second
|
import net.torvald.terrarum.Second
|
||||||
import net.torvald.terrarum.floor
|
import net.torvald.terrarum.floorToFloat
|
||||||
import net.torvald.terrarum.gameactors.ActorWithBody
|
import net.torvald.terrarum.gameactors.ActorWithBody
|
||||||
import net.torvald.terrarum.gameitems.GameItem
|
import net.torvald.terrarum.gameitems.GameItem
|
||||||
import net.torvald.terrarum.modulebasegame.gameactors.Pocketed
|
import net.torvald.terrarum.modulebasegame.gameactors.Pocketed
|
||||||
@@ -19,6 +19,7 @@ import net.torvald.terrarum.spriteassembler.ADProperties
|
|||||||
import net.torvald.terrarum.spriteassembler.ADPropertyObject
|
import net.torvald.terrarum.spriteassembler.ADPropertyObject
|
||||||
import net.torvald.terrarum.spriteassembler.AssembleFrameBase
|
import net.torvald.terrarum.spriteassembler.AssembleFrameBase
|
||||||
import net.torvald.terrarum.spriteassembler.AssembleSheetPixmap
|
import net.torvald.terrarum.spriteassembler.AssembleSheetPixmap
|
||||||
|
import net.torvald.terrarum.tryDispose
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@@ -122,8 +123,8 @@ class AssembledSpriteAnimation(
|
|||||||
val drawPos = adp.origin + bodypartPos // imgCentre for held items are (0,0)
|
val drawPos = adp.origin + bodypartPos // imgCentre for held items are (0,0)
|
||||||
val w = image.regionWidth * scale
|
val w = image.regionWidth * scale
|
||||||
val h = image.regionHeight * scale
|
val h = image.regionHeight * scale
|
||||||
val fposX = posX.floor() + drawPos.x * scale
|
val fposX = posX.floorToFloat() + drawPos.x * scale
|
||||||
val fposY = posY.floor() + drawPos.y * scale - h
|
val fposY = posY.floorToFloat() + drawPos.y * scale - h
|
||||||
|
|
||||||
// draw
|
// draw
|
||||||
if (flipHorizontal && flipVertical)
|
if (flipHorizontal && flipVertical)
|
||||||
@@ -146,8 +147,8 @@ class AssembledSpriteAnimation(
|
|||||||
val drawPos = adp.origin + bodypartPos - imgCentre
|
val drawPos = adp.origin + bodypartPos - imgCentre
|
||||||
val w = image.regionWidth * scale
|
val w = image.regionWidth * scale
|
||||||
val h = image.regionHeight * scale
|
val h = image.regionHeight * scale
|
||||||
val fposX = posX.floor() + drawPos.x * scale
|
val fposX = posX.floorToFloat() + drawPos.x * scale
|
||||||
val fposY = posY.floor() + drawPos.y * scale
|
val fposY = posY.floorToFloat() + drawPos.y * scale
|
||||||
|
|
||||||
if (flipHorizontal && flipVertical)
|
if (flipHorizontal && flipVertical)
|
||||||
batch.draw(image, fposX + txFlp, fposY + tyFlp, -w, -h)
|
batch.draw(image, fposX + txFlp, fposY + tyFlp, -w, -h)
|
||||||
@@ -172,7 +173,7 @@ class AssembledSpriteAnimation(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun dispose() {
|
override fun dispose() {
|
||||||
res.values.forEach { try { it?.texture?.dispose() } catch (_: GdxRuntimeException) {} }
|
res.values.forEach { it?.texture?.tryDispose() }
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ import net.torvald.terrarum.langpack.Lang;
|
|||||||
import net.torvald.terrarum.modulebasegame.IngameRenderer;
|
import net.torvald.terrarum.modulebasegame.IngameRenderer;
|
||||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame;
|
import net.torvald.terrarum.modulebasegame.TerrarumIngame;
|
||||||
import net.torvald.terrarum.modulebasegame.ui.ItemSlotImageFactory;
|
import net.torvald.terrarum.modulebasegame.ui.ItemSlotImageFactory;
|
||||||
import net.torvald.terrarum.savegame.DiskSkimmer;
|
|
||||||
import net.torvald.terrarum.serialise.WriteConfig;
|
import net.torvald.terrarum.serialise.WriteConfig;
|
||||||
import net.torvald.terrarum.ui.Toolkit;
|
import net.torvald.terrarum.ui.Toolkit;
|
||||||
import net.torvald.terrarum.utils.JsonFetcher;
|
import net.torvald.terrarum.utils.JsonFetcher;
|
||||||
@@ -240,6 +239,7 @@ public class App implements ApplicationListener {
|
|||||||
public static ShaderProgram shaderColLUT;
|
public static ShaderProgram shaderColLUT;
|
||||||
public static ShaderProgram shaderReflect;
|
public static ShaderProgram shaderReflect;
|
||||||
public static ShaderProgram shaderGhastlyWhite;
|
public static ShaderProgram shaderGhastlyWhite;
|
||||||
|
public static Hq2x hq2x;
|
||||||
|
|
||||||
public static Mesh fullscreenQuad;
|
public static Mesh fullscreenQuad;
|
||||||
private static OrthographicCamera camera;
|
private static OrthographicCamera camera;
|
||||||
@@ -392,6 +392,7 @@ public class App implements ApplicationListener {
|
|||||||
appConfig.useVsync(getConfigBoolean("usevsync"));
|
appConfig.useVsync(getConfigBoolean("usevsync"));
|
||||||
appConfig.setResizable(false);
|
appConfig.setResizable(false);
|
||||||
appConfig.setWindowedMode(width, height);
|
appConfig.setWindowedMode(width, height);
|
||||||
|
appConfig.setTransparentFramebuffer(false);
|
||||||
int fpsActive = Math.min(GLOBAL_FRAMERATE_LIMIT, getConfigInt("displayfps"));
|
int fpsActive = Math.min(GLOBAL_FRAMERATE_LIMIT, getConfigInt("displayfps"));
|
||||||
if (fpsActive <= 0) fpsActive = GLOBAL_FRAMERATE_LIMIT;
|
if (fpsActive <= 0) fpsActive = GLOBAL_FRAMERATE_LIMIT;
|
||||||
int fpsBack = Math.min(GLOBAL_FRAMERATE_LIMIT, getConfigInt("displayfpsidle"));
|
int fpsBack = Math.min(GLOBAL_FRAMERATE_LIMIT, getConfigInt("displayfpsidle"));
|
||||||
@@ -439,13 +440,10 @@ public class App implements ApplicationListener {
|
|||||||
|
|
||||||
glInfo.create();
|
glInfo.create();
|
||||||
|
|
||||||
CommonResourcePool.INSTANCE.addToLoadingList("blockmarkings_common", () -> new TextureRegionPack(Gdx.files.internal("assets/graphics/blocks/block_markings_common.tga"), 16, 16, 0, 0, 0, 0, false, false, false));
|
|
||||||
CommonResourcePool.INSTANCE.addToLoadingList("blockmarking_actor", () -> new BlockMarkerActor());
|
|
||||||
CommonResourcePool.INSTANCE.addToLoadingList("loading_circle_64", () -> new TextureRegionPack(Gdx.files.internal("assets/graphics/gui/loading_circle_64.tga"), 64, 64, 0, 0, 0, 0, false, false, false));
|
|
||||||
CommonResourcePool.INSTANCE.addToLoadingList("inline_loading_spinner", () -> new TextureRegionPack(Gdx.files.internal("assets/graphics/gui/inline_loading_spinner.tga"), 20, 20, 0, 0, 0, 0, false, false, false));
|
|
||||||
CommonResourcePool.INSTANCE.addToLoadingList("inventory_category", () -> new TextureRegionPack("./assets/graphics/gui/inventory/category.tga", 20, 20, 0, 0, 0, 0, false, false, false));
|
|
||||||
CommonResourcePool.INSTANCE.addToLoadingList("title_health1", () -> new Texture(Gdx.files.internal("./assets/graphics/gui/health_take_a_break.tga")));
|
CommonResourcePool.INSTANCE.addToLoadingList("title_health1", () -> new Texture(Gdx.files.internal("./assets/graphics/gui/health_take_a_break.tga")));
|
||||||
CommonResourcePool.INSTANCE.addToLoadingList("title_health2", () -> new Texture(Gdx.files.internal("./assets/graphics/gui/health_distance.tga")));
|
CommonResourcePool.INSTANCE.addToLoadingList("title_health2", () -> new Texture(Gdx.files.internal("./assets/graphics/gui/health_distance.tga")));
|
||||||
|
// make loading list
|
||||||
|
CommonResourcePool.INSTANCE.loadAll();
|
||||||
|
|
||||||
newTempFile("wenquanyi.tga"); // temp file required by the font
|
newTempFile("wenquanyi.tga"); // temp file required by the font
|
||||||
|
|
||||||
@@ -474,12 +472,9 @@ public class App implements ApplicationListener {
|
|||||||
shaderBayerSkyboxFill = loadShaderFromClasspath("shaders/default.vert",
|
shaderBayerSkyboxFill = loadShaderFromClasspath("shaders/default.vert",
|
||||||
"shaders/float_to_disp_dither_static.frag"
|
"shaders/float_to_disp_dither_static.frag"
|
||||||
);
|
);
|
||||||
shaderHicolour = loadShaderFromClasspath("shaders/default.vert", "shaders/hicolour.frag");
|
|
||||||
shaderDebugDiff = loadShaderFromClasspath("shaders/default.vert", "shaders/diff.frag");
|
|
||||||
shaderPassthruRGBA = loadShaderFromClasspath("shaders/gl32spritebatch.vert", "shaders/gl32spritebatch.frag");
|
shaderPassthruRGBA = loadShaderFromClasspath("shaders/gl32spritebatch.vert", "shaders/gl32spritebatch.frag");
|
||||||
shaderColLUT = loadShaderFromClasspath("shaders/default.vert", "shaders/passthrurgb.frag");
|
|
||||||
shaderReflect = loadShaderFromClasspath("shaders/default.vert", "shaders/reflect.frag");
|
shaderReflect = loadShaderFromClasspath("shaders/default.vert", "shaders/reflect.frag");
|
||||||
shaderGhastlyWhite = loadShaderFromClasspath("shaders/default.vert", "shaders/ghastlywhite.frag");
|
hq2x = new Hq2x(2);
|
||||||
|
|
||||||
fullscreenQuad = new Mesh(
|
fullscreenQuad = new Mesh(
|
||||||
true, 4, 6,
|
true, 4, 6,
|
||||||
@@ -487,97 +482,21 @@ public class App implements ApplicationListener {
|
|||||||
VertexAttribute.ColorUnpacked(),
|
VertexAttribute.ColorUnpacked(),
|
||||||
VertexAttribute.TexCoords(0)
|
VertexAttribute.TexCoords(0)
|
||||||
);
|
);
|
||||||
updateFullscreenQuad(scr.getWidth(), scr.getHeight());
|
updateFullscreenQuad(fullscreenQuad, scr.getWidth(), scr.getHeight());
|
||||||
|
|
||||||
|
|
||||||
// set up renderer info variables
|
// set up renderer info variables
|
||||||
renderer = Gdx.graphics.getGLVersion().getRendererString();
|
renderer = Gdx.graphics.getGLVersion().getRendererString();
|
||||||
rendererVendor = Gdx.graphics.getGLVersion().getVendorString();
|
rendererVendor = Gdx.graphics.getGLVersion().getVendorString();
|
||||||
|
|
||||||
|
|
||||||
// make gamepad(s)
|
|
||||||
if (App.getConfigBoolean("usexinput")) {
|
|
||||||
try {
|
|
||||||
gamepad = new XinputControllerAdapter(XInputDevice.getDeviceFor(0));
|
|
||||||
}
|
|
||||||
catch (Throwable e) {
|
|
||||||
gamepad = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// nullify if not actually connected
|
|
||||||
try {
|
|
||||||
if (!((XinputControllerAdapter) gamepad).getC().isConnected()) {
|
|
||||||
gamepad = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (NullPointerException notQuiteWindows) {
|
|
||||||
gamepad = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gamepad == null) {
|
|
||||||
try {
|
|
||||||
gamepad = new GdxControllerAdapter(Controllers.getControllers().get(0));
|
|
||||||
}
|
|
||||||
catch (Throwable e) {
|
|
||||||
gamepad = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// tell the game that we have a gamepad
|
|
||||||
environment = RunningEnvironment.PC;
|
|
||||||
|
|
||||||
if (gamepad != null) {
|
|
||||||
String name = gamepad.getName().toLowerCase();
|
|
||||||
for (String allowedName : gamepadWhitelist) {
|
|
||||||
if (name.contains(allowedName)) {
|
|
||||||
environment = RunningEnvironment.CONSOLE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*if (gamepad != null) {
|
|
||||||
environment = RunningEnvironment.CONSOLE;
|
|
||||||
|
|
||||||
// calibrate the sticks
|
|
||||||
printdbg(this, "Calibrating the gamepad...");
|
|
||||||
float[] axesZeroPoints = new float[]{
|
|
||||||
gamepad.getAxisRaw(0),
|
|
||||||
gamepad.getAxisRaw(1),
|
|
||||||
gamepad.getAxisRaw(2),
|
|
||||||
gamepad.getAxisRaw(3)
|
|
||||||
};
|
|
||||||
setConfig("control_gamepad_axiszeropoints", axesZeroPoints);
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
printdbg(this, "Axis " + i + ": " + axesZeroPoints[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
environment = RunningEnvironment.PC;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
fontGame = new TerrarumSansBitmap(FONT_DIR, false, false, false,
|
fontGame = new TerrarumSansBitmap(FONT_DIR, false, false, false,
|
||||||
false,
|
false,
|
||||||
256, false, 0.5f, false
|
256, false, 0.5f, false
|
||||||
);
|
);
|
||||||
fontUITitle = new TerrarumSansBitmap(FONT_DIR, false, false, false,
|
|
||||||
false,
|
|
||||||
64, false, 0.5f, false
|
|
||||||
);
|
|
||||||
fontUITitle.setInterchar(1);
|
|
||||||
fontGameFBO = new TerrarumSansBitmap(FONT_DIR, false, true, false,
|
|
||||||
false,
|
|
||||||
64, false, 203f/255f, false
|
|
||||||
);
|
|
||||||
Lang.invoke();
|
|
||||||
|
|
||||||
// make loading list
|
|
||||||
CommonResourcePool.INSTANCE.loadAll();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private FrameBuffer postProcessorOutFBO;
|
private FrameBuffer postProcessorOutFBO;
|
||||||
|
private FrameBuffer postProcessorOutFBO2;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render() {
|
public void render() {
|
||||||
@@ -636,30 +555,44 @@ public class App implements ApplicationListener {
|
|||||||
FrameBufferManager.end();
|
FrameBufferManager.end();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// process screenshot request
|
// process screenshot request
|
||||||
if (screenshotRequested) {
|
processScreenshotRequest(postProcessorOutFBO);
|
||||||
FrameBufferManager.begin(postProcessorOutFBO);
|
|
||||||
try {
|
|
||||||
Pixmap p = Pixmap.createFromFrameBuffer(0, 0, scr.getWidth(), scr.getHeight());
|
|
||||||
PixmapIO.writePNG(Gdx.files.absolute(defaultDir+"/Screenshot-"+String.valueOf(System.currentTimeMillis())+".png"), p, 9, true);
|
if (getConfigString("screenmagnifyingfilter").equals("hq2x") ) {
|
||||||
p.dispose();
|
FrameBufferManager.begin(postProcessorOutFBO2);
|
||||||
Terrarum.INSTANCE.getIngame().sendNotification("Screenshot taken");
|
shaderPassthruRGBA.bind();
|
||||||
}
|
shaderPassthruRGBA.setUniformMatrix("u_projTrans", camera.combined);
|
||||||
catch (Throwable e) {
|
shaderPassthruRGBA.setUniformi("u_texture", 0);
|
||||||
e.printStackTrace();
|
hq2x.renderToScreen(postProcessorOutFBO.getColorBufferTexture());
|
||||||
Terrarum.INSTANCE.getIngame().sendNotification("Failed to take screenshot: "+e.getMessage());
|
|
||||||
}
|
|
||||||
FrameBufferManager.end();
|
FrameBufferManager.end();
|
||||||
screenshotRequested = false;
|
|
||||||
|
shaderPassthruRGBA.bind();
|
||||||
|
shaderPassthruRGBA.setUniformMatrix("u_projTrans", camera.combined);
|
||||||
|
shaderPassthruRGBA.setUniformi("u_texture", 0);
|
||||||
|
postProcessorOutFBO2.getColorBufferTexture().setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear);
|
||||||
|
postProcessorOutFBO2.getColorBufferTexture().bind(0);
|
||||||
|
fullscreenQuad.render(shaderPassthruRGBA, GL20.GL_TRIANGLES);
|
||||||
|
}
|
||||||
|
else if (getConfigDouble("screenmagnifying") < 1.01 || getConfigString("screenmagnifyingfilter").equals("none")) {
|
||||||
|
shaderPassthruRGBA.bind();
|
||||||
|
shaderPassthruRGBA.setUniformMatrix("u_projTrans", camera.combined);
|
||||||
|
shaderPassthruRGBA.setUniformi("u_texture", 0);
|
||||||
|
postProcessorOutFBO.getColorBufferTexture().setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest);
|
||||||
|
postProcessorOutFBO.getColorBufferTexture().bind(0);
|
||||||
|
fullscreenQuad.render(shaderPassthruRGBA, GL20.GL_TRIANGLES);
|
||||||
|
}
|
||||||
|
else if (getConfigString("screenmagnifyingfilter").equals("bilinear")) {
|
||||||
|
shaderPassthruRGBA.bind();
|
||||||
|
shaderPassthruRGBA.setUniformMatrix("u_projTrans", camera.combined);
|
||||||
|
shaderPassthruRGBA.setUniformi("u_texture", 0);
|
||||||
|
postProcessorOutFBO.getColorBufferTexture().setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear);
|
||||||
|
postProcessorOutFBO.getColorBufferTexture().bind(0);
|
||||||
|
fullscreenQuad.render(shaderPassthruRGBA, GL20.GL_TRIANGLES);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
shaderPassthruRGBA.bind();
|
|
||||||
shaderPassthruRGBA.setUniformMatrix("u_projTrans", camera.combined);
|
|
||||||
shaderPassthruRGBA.setUniformi("u_texture", 0);
|
|
||||||
postProcessorOutFBO.getColorBufferTexture().bind(0);
|
|
||||||
fullscreenQuad.render(shaderPassthruRGBA, GL20.GL_TRIANGLES);
|
|
||||||
|
|
||||||
// process resize request
|
// process resize request
|
||||||
if (resizeRequested) {
|
if (resizeRequested) {
|
||||||
@@ -674,6 +607,24 @@ public class App implements ApplicationListener {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void processScreenshotRequest(FrameBuffer fb) {
|
||||||
|
if (screenshotRequested) {
|
||||||
|
FrameBufferManager.begin(fb);
|
||||||
|
try {
|
||||||
|
Pixmap p = Pixmap.createFromFrameBuffer(0, 0, fb.getWidth(), fb.getHeight());
|
||||||
|
PixmapIO.writePNG(Gdx.files.absolute(defaultDir+"/Screenshot-"+String.valueOf(System.currentTimeMillis())+".png"), p, 9, true);
|
||||||
|
p.dispose();
|
||||||
|
Terrarum.INSTANCE.getIngame().sendNotification("Screenshot taken");
|
||||||
|
}
|
||||||
|
catch (Throwable e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
Terrarum.INSTANCE.getIngame().sendNotification("Failed to take screenshot: "+e.getMessage());
|
||||||
|
}
|
||||||
|
FrameBufferManager.end();
|
||||||
|
screenshotRequested = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static Texture getCurrentDitherTex() {
|
public static Texture getCurrentDitherTex() {
|
||||||
int hash = 31 + GLOBAL_RENDER_TIMER + 0x165667B1 + GLOBAL_RENDER_TIMER * 0xC2B2AE3D;
|
int hash = 31 + GLOBAL_RENDER_TIMER + 0x165667B1 + GLOBAL_RENDER_TIMER * 0xC2B2AE3D;
|
||||||
hash = Integer.rotateLeft(hash, 17) * 0x27D4EB2F;
|
hash = Integer.rotateLeft(hash, 17) * 0x27D4EB2F;
|
||||||
@@ -792,7 +743,7 @@ public class App implements ApplicationListener {
|
|||||||
|
|
||||||
if (currentScreen != null) currentScreen.resize(scr.getWidth(), scr.getHeight());
|
if (currentScreen != null) currentScreen.resize(scr.getWidth(), scr.getHeight());
|
||||||
TerrarumPostProcessor.INSTANCE.resize(scr.getWidth(), scr.getHeight());
|
TerrarumPostProcessor.INSTANCE.resize(scr.getWidth(), scr.getHeight());
|
||||||
updateFullscreenQuad(scr.getWidth(), scr.getHeight());
|
updateFullscreenQuad(fullscreenQuad, scr.getWidth(), scr.getHeight());
|
||||||
|
|
||||||
|
|
||||||
if (renderFBO == null ||
|
if (renderFBO == null ||
|
||||||
@@ -804,6 +755,11 @@ public class App implements ApplicationListener {
|
|||||||
scr.getHeight(),
|
scr.getHeight(),
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
postProcessorOutFBO2 = new FloatFrameBuffer(
|
||||||
|
scr.getWidth() * 2,
|
||||||
|
scr.getHeight() * 2,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
if (IS_DEVELOPMENT_BUILD) {
|
if (IS_DEVELOPMENT_BUILD) {
|
||||||
@@ -856,6 +812,7 @@ public class App implements ApplicationListener {
|
|||||||
shaderColLUT.dispose();
|
shaderColLUT.dispose();
|
||||||
shaderReflect.dispose();
|
shaderReflect.dispose();
|
||||||
shaderGhastlyWhite.dispose();
|
shaderGhastlyWhite.dispose();
|
||||||
|
hq2x.dispose();
|
||||||
|
|
||||||
CommonResourcePool.INSTANCE.dispose();
|
CommonResourcePool.INSTANCE.dispose();
|
||||||
fullscreenQuad.dispose();
|
fullscreenQuad.dispose();
|
||||||
@@ -954,6 +911,93 @@ public class App implements ApplicationListener {
|
|||||||
* Init stuffs which needs GL context
|
* Init stuffs which needs GL context
|
||||||
*/
|
*/
|
||||||
private void postInit() {
|
private void postInit() {
|
||||||
|
CommonResourcePool.INSTANCE.addToLoadingList("blockmarkings_common", () -> new TextureRegionPack(Gdx.files.internal("assets/graphics/blocks/block_markings_common.tga"), 16, 16, 0, 0, 0, 0, false, false, false));
|
||||||
|
CommonResourcePool.INSTANCE.addToLoadingList("blockmarking_actor", () -> new BlockMarkerActor());
|
||||||
|
CommonResourcePool.INSTANCE.addToLoadingList("loading_circle_64", () -> new TextureRegionPack(Gdx.files.internal("assets/graphics/gui/loading_circle_64.tga"), 64, 64, 0, 0, 0, 0, false, false, false));
|
||||||
|
CommonResourcePool.INSTANCE.addToLoadingList("inline_loading_spinner", () -> new TextureRegionPack(Gdx.files.internal("assets/graphics/gui/inline_loading_spinner.tga"), 20, 20, 0, 0, 0, 0, false, false, false));
|
||||||
|
CommonResourcePool.INSTANCE.addToLoadingList("inventory_category", () -> new TextureRegionPack("./assets/graphics/gui/inventory/category.tga", 20, 20, 0, 0, 0, 0, false, false, false));
|
||||||
|
CommonResourcePool.INSTANCE.loadAll();
|
||||||
|
|
||||||
|
shaderHicolour = loadShaderFromClasspath("shaders/default.vert", "shaders/hicolour.frag");
|
||||||
|
shaderDebugDiff = loadShaderFromClasspath("shaders/default.vert", "shaders/diff.frag");
|
||||||
|
shaderColLUT = loadShaderFromClasspath("shaders/default.vert", "shaders/rgbonly.frag");
|
||||||
|
shaderGhastlyWhite = loadShaderFromClasspath("shaders/default.vert", "shaders/ghastlywhite.frag");
|
||||||
|
|
||||||
|
// make gamepad(s)
|
||||||
|
if (App.getConfigBoolean("usexinput")) {
|
||||||
|
try {
|
||||||
|
gamepad = new XinputControllerAdapter(XInputDevice.getDeviceFor(0));
|
||||||
|
}
|
||||||
|
catch (Throwable e) {
|
||||||
|
gamepad = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// nullify if not actually connected
|
||||||
|
try {
|
||||||
|
if (!((XinputControllerAdapter) gamepad).getC().isConnected()) {
|
||||||
|
gamepad = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (NullPointerException notQuiteWindows) {
|
||||||
|
gamepad = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gamepad == null) {
|
||||||
|
try {
|
||||||
|
gamepad = new GdxControllerAdapter(Controllers.getControllers().get(0));
|
||||||
|
}
|
||||||
|
catch (Throwable e) {
|
||||||
|
gamepad = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// tell the game that we have a gamepad
|
||||||
|
environment = RunningEnvironment.PC;
|
||||||
|
|
||||||
|
if (gamepad != null) {
|
||||||
|
String name = gamepad.getName().toLowerCase();
|
||||||
|
for (String allowedName : gamepadWhitelist) {
|
||||||
|
if (name.contains(allowedName)) {
|
||||||
|
environment = RunningEnvironment.CONSOLE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*if (gamepad != null) {
|
||||||
|
environment = RunningEnvironment.CONSOLE;
|
||||||
|
|
||||||
|
// calibrate the sticks
|
||||||
|
printdbg(this, "Calibrating the gamepad...");
|
||||||
|
float[] axesZeroPoints = new float[]{
|
||||||
|
gamepad.getAxisRaw(0),
|
||||||
|
gamepad.getAxisRaw(1),
|
||||||
|
gamepad.getAxisRaw(2),
|
||||||
|
gamepad.getAxisRaw(3)
|
||||||
|
};
|
||||||
|
setConfig("control_gamepad_axiszeropoints", axesZeroPoints);
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
printdbg(this, "Axis " + i + ": " + axesZeroPoints[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
environment = RunningEnvironment.PC;
|
||||||
|
}*/
|
||||||
|
fontUITitle = new TerrarumSansBitmap(FONT_DIR, false, false, false,
|
||||||
|
false,
|
||||||
|
64, false, 0.5f, false
|
||||||
|
);
|
||||||
|
fontUITitle.setInterchar(1);
|
||||||
|
fontGameFBO = new TerrarumSansBitmap(FONT_DIR, false, true, false,
|
||||||
|
false,
|
||||||
|
64, false, 203f/255f, false
|
||||||
|
);
|
||||||
|
Lang.invoke();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ModMgr.INSTANCE.invoke(); // invoke Module Manager
|
ModMgr.INSTANCE.invoke(); // invoke Module Manager
|
||||||
|
|
||||||
|
|
||||||
@@ -1032,14 +1076,14 @@ public class App implements ApplicationListener {
|
|||||||
logoBatch.setProjectionMatrix(camera.combined);
|
logoBatch.setProjectionMatrix(camera.combined);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateFullscreenQuad(int WIDTH, int HEIGHT) { // NOT y-flipped quads!
|
private void updateFullscreenQuad(Mesh mesh, int WIDTH, int HEIGHT) { // NOT y-flipped quads!
|
||||||
fullscreenQuad.setVertices(new float[]{
|
mesh.setVertices(new float[]{
|
||||||
0f, 0f, 0f, 1f, 1f, 1f, 1f, 0f, 1f,
|
0f, 0f, 0f, 1f, 1f, 1f, 1f, 0f, 1f,
|
||||||
WIDTH, 0f, 0f, 1f, 1f, 1f, 1f, 1f, 1f,
|
WIDTH, 0f, 0f, 1f, 1f, 1f, 1f, 1f, 1f,
|
||||||
WIDTH, HEIGHT, 0f, 1f, 1f, 1f, 1f, 1f, 0f,
|
WIDTH, HEIGHT, 0f, 1f, 1f, 1f, 1f, 1f, 0f,
|
||||||
0f, HEIGHT, 0f, 1f, 1f, 1f, 1f, 0f, 0f
|
0f, HEIGHT, 0f, 1f, 1f, 1f, 1f, 0f, 0f
|
||||||
});
|
});
|
||||||
fullscreenQuad.setIndices(new short[]{0, 1, 2, 2, 3, 0});
|
mesh.setIndices(new short[]{0, 1, 2, 2, 3, 0});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setGamepadButtonLabels() {
|
public static void setGamepadButtonLabels() {
|
||||||
|
|||||||
@@ -33,9 +33,9 @@ object CommonResourcePool {
|
|||||||
addToLoadingList("itemplaceholder_48") {
|
addToLoadingList("itemplaceholder_48") {
|
||||||
TextureRegion(Texture("assets/item_kari_48.tga")).also { it.flip(false, false) }
|
TextureRegion(Texture("assets/item_kari_48.tga")).also { it.flip(false, false) }
|
||||||
}
|
}
|
||||||
addToLoadingList("test_texture") {
|
/*addToLoadingList("test_texture") {
|
||||||
TextureRegion(Texture("assets/test_texture.tga")).also { it.flip(false, false) }
|
TextureRegion(Texture("assets/test_texture.tga")).also { it.flip(false, false) }
|
||||||
}
|
}*/
|
||||||
loadAll()
|
loadAll()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ object DefaultConfig {
|
|||||||
"language" to App.getSysLang(),
|
"language" to App.getSysLang(),
|
||||||
"notificationshowuptime" to 4000, // 4s
|
"notificationshowuptime" to 4000, // 4s
|
||||||
"selecteditemnameshowuptime" to 4000, // 4s
|
"selecteditemnameshowuptime" to 4000, // 4s
|
||||||
"autosaveinterval" to 300000, // 5s
|
"autosaveinterval" to 300000, // 5m
|
||||||
"multithread" to true,
|
"multithread" to true,
|
||||||
|
|
||||||
"showhealthmessageonstartup" to true,
|
"showhealthmessageonstartup" to true,
|
||||||
@@ -112,6 +112,7 @@ object DefaultConfig {
|
|||||||
"inputmethod" to "none",
|
"inputmethod" to "none",
|
||||||
|
|
||||||
"screenmagnifying" to 1.0,
|
"screenmagnifying" to 1.0,
|
||||||
|
"screenmagnifyingfilter" to "none", // "none", "bilinear", "hq2x"
|
||||||
|
|
||||||
"fx_newlight" to false,
|
"fx_newlight" to false,
|
||||||
|
|
||||||
@@ -119,6 +120,12 @@ object DefaultConfig {
|
|||||||
"debug_deltat_benchmark_sample_sizes" to 2048,
|
"debug_deltat_benchmark_sample_sizes" to 2048,
|
||||||
|
|
||||||
|
|
||||||
|
"mastervolume" to 1.0,
|
||||||
|
"musicvolume" to 1.0,
|
||||||
|
"bgmvolume" to 1.0,
|
||||||
|
"sfxvolume" to 1.0,
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// settings regarding debugger
|
// settings regarding debugger
|
||||||
/*"buildingmakerfavs" to arrayOf(
|
/*"buildingmakerfavs" to arrayOf(
|
||||||
|
|||||||
@@ -64,8 +64,8 @@ object GlslTilingTest : ApplicationAdapter() {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
val tilesInHorizontal = (Gdx.graphics.width.toFloat() / TILING_SIZE).ceil() + 1f
|
val tilesInHorizontal = (Gdx.graphics.width.toFloat() / TILING_SIZE).ceilToFloat() + 1f
|
||||||
val tilesInVertical = (Gdx.graphics.height.toFloat() / TILING_SIZE).ceil() + 1f
|
val tilesInVertical = (Gdx.graphics.height.toFloat() / TILING_SIZE).ceilToFloat() + 1f
|
||||||
|
|
||||||
tilesQuad = Mesh(
|
tilesQuad = Mesh(
|
||||||
true, 4, 6,
|
true, 4, 6,
|
||||||
@@ -129,8 +129,8 @@ object GlslTilingTest : ApplicationAdapter() {
|
|||||||
Gdx.gl.glEnable(GL20.GL_BLEND)
|
Gdx.gl.glEnable(GL20.GL_BLEND)
|
||||||
Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA)
|
Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA)
|
||||||
|
|
||||||
val tilesInHorizontal = (Gdx.graphics.width.toFloat() / TILING_SIZE).ceil() + 1f
|
val tilesInHorizontal = (Gdx.graphics.width.toFloat() / TILING_SIZE).ceilToFloat() + 1f
|
||||||
val tilesInVertical = (Gdx.graphics.height.toFloat() / TILING_SIZE).ceil() + 1f
|
val tilesInVertical = (Gdx.graphics.height.toFloat() / TILING_SIZE).ceilToFloat() + 1f
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
214
src/net/torvald/terrarum/Hq2x.kt
Normal file
214
src/net/torvald/terrarum/Hq2x.kt
Normal file
@@ -0,0 +1,214 @@
|
|||||||
|
package net.torvald.terrarum
|
||||||
|
|
||||||
|
import com.badlogic.gdx.Gdx
|
||||||
|
import com.badlogic.gdx.files.FileHandle
|
||||||
|
import com.badlogic.gdx.graphics.*
|
||||||
|
import com.badlogic.gdx.graphics.VertexAttributes.Usage
|
||||||
|
import com.badlogic.gdx.graphics.glutils.FrameBuffer
|
||||||
|
import com.badlogic.gdx.graphics.glutils.ShaderProgram
|
||||||
|
import com.badlogic.gdx.math.Matrix4
|
||||||
|
import com.badlogic.gdx.utils.Disposable
|
||||||
|
import com.badlogic.gdx.utils.GdxRuntimeException
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [HQnX](https://en.wikipedia.org/wiki/Pixel-art_scaling_algorithms#hqnx_family)
|
||||||
|
* upscale algorithm GLSL implementation based on
|
||||||
|
* [CrossVR](https://github.com/CrossVR/hqx-shader/tree/master/glsl) project.
|
||||||
|
*/
|
||||||
|
class Hq2x : Disposable {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val TEXTURE_HANDLE0 = 0
|
||||||
|
private const val TEXTURE_HANDLE1 = 1
|
||||||
|
|
||||||
|
private const val U_TEXTURE = "u_texture"
|
||||||
|
private const val U_LUT = "u_lut"
|
||||||
|
private const val U_TEXTURE_SIZE = "u_textureSize"
|
||||||
|
}
|
||||||
|
|
||||||
|
private val mesh = ViewportQuadMesh(
|
||||||
|
VertexAttribute(Usage.Position, 2, "a_position"),
|
||||||
|
VertexAttribute(Usage.TextureCoordinates, 2, "a_texCoord0"))
|
||||||
|
|
||||||
|
private val program: ShaderProgram
|
||||||
|
private val lutTexture: Texture
|
||||||
|
private val scaleFactor: Int
|
||||||
|
|
||||||
|
private var dstBuffer: FrameBuffer? = null
|
||||||
|
private var dstWidth = 0
|
||||||
|
private var dstHeight = 0
|
||||||
|
|
||||||
|
/** @param scaleFactor should be 2, 3 or 4 value. */
|
||||||
|
constructor(scaleFactor: Int) {
|
||||||
|
if (scaleFactor !in 2..4) {
|
||||||
|
throw GdxRuntimeException("Scale factor should be 2, 3 or 4.")
|
||||||
|
}
|
||||||
|
|
||||||
|
program = compileShader(
|
||||||
|
Gdx.files.classpath("shaders/hq2x.vert"),
|
||||||
|
Gdx.files.classpath("shaders/hq2x.frag"),
|
||||||
|
"")
|
||||||
|
|
||||||
|
lutTexture = Texture(Gdx.files.classpath("shaders/hq${scaleFactor}x.png"))
|
||||||
|
|
||||||
|
this.scaleFactor = scaleFactor
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun dispose() {
|
||||||
|
mesh.dispose()
|
||||||
|
program.dispose()
|
||||||
|
lutTexture.dispose()
|
||||||
|
dstBuffer?.dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun rebind() {
|
||||||
|
program.bind()
|
||||||
|
program.setUniformi(U_TEXTURE, TEXTURE_HANDLE0)
|
||||||
|
program.setUniformi(U_LUT, TEXTURE_HANDLE1)
|
||||||
|
program.setUniformf(U_TEXTURE_SIZE,
|
||||||
|
dstWidth / scaleFactor.toFloat(),
|
||||||
|
dstHeight / scaleFactor.toFloat())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun renderToScreen(src: Texture) {
|
||||||
|
validate(src)
|
||||||
|
|
||||||
|
lutTexture.bind(TEXTURE_HANDLE1)
|
||||||
|
src.bind(TEXTURE_HANDLE0)
|
||||||
|
src.setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest)
|
||||||
|
|
||||||
|
program.bind()
|
||||||
|
mesh.render(program)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun renderToBuffer(src: Texture): Texture {
|
||||||
|
validate(src)
|
||||||
|
validateDstBuffer()
|
||||||
|
|
||||||
|
lutTexture.bind(TEXTURE_HANDLE1)
|
||||||
|
src.bind(TEXTURE_HANDLE0)
|
||||||
|
src.setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest)
|
||||||
|
|
||||||
|
dstBuffer!!.begin()
|
||||||
|
program.bind()
|
||||||
|
mesh.render(program)
|
||||||
|
dstBuffer!!.end()
|
||||||
|
|
||||||
|
return dstBuffer!!.colorBufferTexture
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun validate(src: Texture) {
|
||||||
|
val targetWidth = src.width * scaleFactor
|
||||||
|
val targetHeight = src.height * scaleFactor
|
||||||
|
|
||||||
|
// println("[Hq2x] $targetWidth x $targetHeight")
|
||||||
|
|
||||||
|
if (dstWidth != targetWidth || dstHeight != targetHeight) {
|
||||||
|
dstWidth = targetWidth
|
||||||
|
dstHeight = targetHeight
|
||||||
|
rebind()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun validateDstBuffer() {
|
||||||
|
if (dstBuffer == null || dstBuffer!!.width != dstWidth || dstBuffer!!.height != dstHeight) {
|
||||||
|
dstBuffer?.dispose()
|
||||||
|
dstBuffer = FrameBuffer(Pixmap.Format.RGB888, dstWidth, dstHeight, false)
|
||||||
|
dstBuffer!!.colorBufferTexture.setFilter(
|
||||||
|
Texture.TextureFilter.Nearest,
|
||||||
|
Texture.TextureFilter.Nearest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encapsulates a fullscreen quad mesh. Geometry is aligned to the viewport corners.
|
||||||
|
*
|
||||||
|
* @author bmanuel
|
||||||
|
* @author metaphore
|
||||||
|
*/
|
||||||
|
private class ViewportQuadMesh : Disposable {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val VERT_SIZE = 16
|
||||||
|
private const val X1 = 0
|
||||||
|
private const val Y1 = 1
|
||||||
|
private const val U1 = 2
|
||||||
|
private const val V1 = 3
|
||||||
|
private const val X2 = 4
|
||||||
|
private const val Y2 = 5
|
||||||
|
private const val U2 = 6
|
||||||
|
private const val V2 = 7
|
||||||
|
private const val X3 = 8
|
||||||
|
private const val Y3 = 9
|
||||||
|
private const val U3 = 10
|
||||||
|
private const val V3 = 11
|
||||||
|
private const val X4 = 12
|
||||||
|
private const val Y4 = 13
|
||||||
|
private const val U4 = 14
|
||||||
|
private const val V4 = 15
|
||||||
|
|
||||||
|
private val verts: FloatArray
|
||||||
|
|
||||||
|
init {
|
||||||
|
verts = FloatArray(VERT_SIZE)
|
||||||
|
|
||||||
|
// Vertex coords
|
||||||
|
verts[X1] = -1f
|
||||||
|
verts[Y1] = -1f
|
||||||
|
verts[X2] = 1f
|
||||||
|
verts[Y2] = -1f
|
||||||
|
verts[X3] = 1f
|
||||||
|
verts[Y3] = 1f
|
||||||
|
verts[X4] = -1f
|
||||||
|
verts[Y4] = 1f
|
||||||
|
|
||||||
|
// Tex coords
|
||||||
|
verts[U1] = 0f
|
||||||
|
verts[V1] = 0f
|
||||||
|
verts[U2] = 1f
|
||||||
|
verts[V2] = 0f
|
||||||
|
verts[U3] = 1f
|
||||||
|
verts[V3] = 1f
|
||||||
|
verts[U4] = 0f
|
||||||
|
verts[V4] = 1f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val mesh: Mesh
|
||||||
|
|
||||||
|
constructor(vararg attributes: VertexAttribute) {
|
||||||
|
mesh = Mesh(true, 4, 0, *attributes)
|
||||||
|
mesh.setVertices(verts)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun dispose() {
|
||||||
|
mesh.dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Renders the quad with the specified shader program. */
|
||||||
|
fun render(program: ShaderProgram) {
|
||||||
|
mesh.render(program, GL20.GL_TRIANGLE_FAN, 0, 4)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun compileShader(vertexFile: FileHandle, fragmentFile: FileHandle, defines: String): ShaderProgram {
|
||||||
|
val sb = StringBuilder()
|
||||||
|
sb.append("Compiling \"").append(vertexFile.name()).append('/').append(fragmentFile.name()).append('\"')
|
||||||
|
if (defines.isNotEmpty()) {
|
||||||
|
sb.append(" w/ (").append(defines.replace("\n", ", ")).append(")")
|
||||||
|
}
|
||||||
|
sb.append("...")
|
||||||
|
Gdx.app.log("HqnxEffect", sb.toString())
|
||||||
|
|
||||||
|
val srcVert = vertexFile.readString()
|
||||||
|
val srcFrag = fragmentFile.readString()
|
||||||
|
val shader = ShaderProgram(
|
||||||
|
"$defines\n$srcVert".trimIndent(),
|
||||||
|
"$defines\n$srcFrag".trimIndent())
|
||||||
|
|
||||||
|
if (!shader.isCompiled) {
|
||||||
|
throw GdxRuntimeException("Shader compilation error: ${vertexFile.name()}/${fragmentFile.name()}\n${shader.log}")
|
||||||
|
}
|
||||||
|
return shader
|
||||||
|
}
|
||||||
@@ -32,6 +32,7 @@ import java.nio.file.StandardCopyOption
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.locks.Lock
|
import java.util.concurrent.locks.Lock
|
||||||
import java.util.function.Consumer
|
import java.util.function.Consumer
|
||||||
|
import kotlin.math.min
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Although the game (as product) can have infinitely many stages/planets/etc., those stages must be manually managed by YOU;
|
* Although the game (as product) can have infinitely many stages/planets/etc., those stages must be manually managed by YOU;
|
||||||
@@ -64,7 +65,7 @@ open class IngameInstance(val batch: FlippingSpriteBatch, val isMultiplayer: Boo
|
|||||||
lateinit var playerDisk: VirtualDisk; internal set
|
lateinit var playerDisk: VirtualDisk; internal set
|
||||||
lateinit var worldSavefileName: String; internal set
|
lateinit var worldSavefileName: String; internal set
|
||||||
lateinit var playerSavefileName: String; internal set
|
lateinit var playerSavefileName: String; internal set
|
||||||
var savegameNickname: String = "SplinesReticulated"; internal set
|
var worldName: String = "SplinesReticulated"; internal set // worldName is stored as a name of the disk
|
||||||
|
|
||||||
var screenZoom = 1.0f
|
var screenZoom = 1.0f
|
||||||
val ZOOM_MAXIMUM = 4.0f
|
val ZOOM_MAXIMUM = 4.0f
|
||||||
@@ -204,13 +205,7 @@ open class IngameInstance(val batch: FlippingSpriteBatch, val isMultiplayer: Boo
|
|||||||
actorContainerInactive.forEach { it.dispose() }
|
actorContainerInactive.forEach { it.dispose() }
|
||||||
world.dispose()
|
world.dispose()
|
||||||
|
|
||||||
disposables.forEach(Consumer {
|
disposables.forEach(Consumer { it.tryDispose() })
|
||||||
try { it.dispose() }
|
|
||||||
catch (_: NullPointerException) { }
|
|
||||||
catch (_: IllegalArgumentException) { }
|
|
||||||
catch (_: GdxRuntimeException) { }
|
|
||||||
catch (_: ConcurrentModificationException) { }
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////
|
////////////
|
||||||
@@ -490,7 +485,7 @@ open class IngameInstance(val batch: FlippingSpriteBatch, val isMultiplayer: Boo
|
|||||||
val dist2 = (p.getOrd(0) - (t.hitbox.centeredX - world.width * TILE_SIZE)).sqr() + (p.getOrd(1) - t.hitbox.centeredY).sqr()
|
val dist2 = (p.getOrd(0) - (t.hitbox.centeredX - world.width * TILE_SIZE)).sqr() + (p.getOrd(1) - t.hitbox.centeredY).sqr()
|
||||||
val dist3 = (p.getOrd(0) - (t.hitbox.centeredX + world.width * TILE_SIZE)).sqr() + (p.getOrd(1) - t.hitbox.centeredY).sqr()
|
val dist3 = (p.getOrd(0) - (t.hitbox.centeredX + world.width * TILE_SIZE)).sqr() + (p.getOrd(1) - t.hitbox.centeredY).sqr()
|
||||||
|
|
||||||
minOf(dist1, dist2, dist3)
|
min(min(dist1, dist2), dist3)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -5,8 +5,7 @@ import net.torvald.terrarum.utils.JsonFetcher;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
import java.util.*;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bootstrapper that launches the bundled JVM and injects VM configs such as -Xmx
|
* Bootstrapper that launches the bundled JVM and injects VM configs such as -Xmx
|
||||||
@@ -25,7 +24,6 @@ public class Principii {
|
|||||||
/** defaultDir + "/config.json" */
|
/** defaultDir + "/config.json" */
|
||||||
private static String configDir;
|
private static String configDir;
|
||||||
|
|
||||||
|
|
||||||
public static void getDefaultDirRoot() {
|
public static void getDefaultDirRoot() {
|
||||||
String OS = OSName.toUpperCase();
|
String OS = OSName.toUpperCase();
|
||||||
if (OS.contains("WIN")) {
|
if (OS.contains("WIN")) {
|
||||||
@@ -63,7 +61,7 @@ public class Principii {
|
|||||||
devMode = true;
|
devMode = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
String extracmd = devMode ? " -ea" : "";
|
String extracmd0 = devMode ? " -ea" : "";
|
||||||
String OS = OSName.toUpperCase();
|
String OS = OSName.toUpperCase();
|
||||||
String CPUARCH = System.getProperty("os.arch").toUpperCase();
|
String CPUARCH = System.getProperty("os.arch").toUpperCase();
|
||||||
String runtimeRoot;
|
String runtimeRoot;
|
||||||
@@ -82,14 +80,14 @@ public class Principii {
|
|||||||
}
|
}
|
||||||
else if (OS.contains("OS X") || OS.contains("MACOS")) { // OpenJDK for mac will still report "Mac OS X" with version number "10.16", even on Big Sur and beyond
|
else if (OS.contains("OS X") || OS.contains("MACOS")) { // OpenJDK for mac will still report "Mac OS X" with version number "10.16", even on Big Sur and beyond
|
||||||
runtimeRoot = "runtime-osx-" + runtimeArch;
|
runtimeRoot = "runtime-osx-" + runtimeArch;
|
||||||
extracmd += " -XstartOnFirstThread";
|
extracmd0 += " -XstartOnFirstThread";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
runtimeRoot = "runtime-linux-" + runtimeArch;
|
runtimeRoot = "runtime-linux-" + runtimeArch;
|
||||||
extracmd += " -Dswing.aatext=true -Dawt.useSystemAAFontSettings=lcd";
|
extracmd0 += " -Dswing.aatext=true -Dawt.useSystemAAFontSettings=lcd";
|
||||||
}
|
}
|
||||||
|
|
||||||
String runtime = new File("out/"+runtimeRoot+"/bin/java").getAbsolutePath();
|
String runtime = new File("out/"+runtimeRoot+"/bin/Terrarum").getAbsolutePath(); // /bin/Terrarum is just a renamed version of /bin/java
|
||||||
System.out.println("Runtime path: "+runtime);
|
System.out.println("Runtime path: "+runtime);
|
||||||
|
|
||||||
|
|
||||||
@@ -102,13 +100,27 @@ public class Principii {
|
|||||||
|
|
||||||
|
|
||||||
int xmx = getConfigInt("jvm_xmx");
|
int xmx = getConfigInt("jvm_xmx");
|
||||||
String userDefinedExtraCmd = getConfigString("jvm_extra_cmd").trim();
|
String userDefinedExtraCmd0 = getConfigString("jvm_extra_cmd").trim();
|
||||||
if (!userDefinedExtraCmd.isEmpty()) userDefinedExtraCmd = " "+userDefinedExtraCmd;
|
if (!userDefinedExtraCmd0.isEmpty()) userDefinedExtraCmd0 = " "+userDefinedExtraCmd0;
|
||||||
|
|
||||||
|
// String[] cmd = (runtime+extracmd0+userDefinedExtraCmd0+" -Xms1G -Xmx"+xmx+"G -cp ./out/TerrarumBuild.jar net.torvald.terrarum.App").split(" ");
|
||||||
|
|
||||||
|
List<String> extracmds = Arrays.stream(extracmd0.split(" ")).toList();
|
||||||
|
List<String> userDefinedExtraCmds = Arrays.stream(userDefinedExtraCmd0.split(" +")).filter((it) -> !it.isBlank()).toList();
|
||||||
|
ArrayList<String> cmd0 = new ArrayList<>();
|
||||||
|
cmd0.add(runtime);
|
||||||
|
cmd0.addAll(extracmds);
|
||||||
|
cmd0.addAll(userDefinedExtraCmds);
|
||||||
|
cmd0.add("-Xms1G");
|
||||||
|
cmd0.add("-Xmx"+xmx+"G");
|
||||||
|
cmd0.add("-cp");
|
||||||
|
cmd0.add("./out/TerrarumBuild.jar");
|
||||||
|
cmd0.add("net.torvald.terrarum.App");
|
||||||
|
var cmd = cmd0.stream().filter((it) -> !it.isBlank()).toList();
|
||||||
|
|
||||||
|
System.out.println(cmd);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String[] cmd = (runtime+extracmd+userDefinedExtraCmd+" -Xms1G -Xmx"+xmx+"G -cp ./out/TerrarumBuild.jar net.torvald.terrarum.App").split(" ");
|
|
||||||
ProcessBuilder pb = new ProcessBuilder(cmd);
|
ProcessBuilder pb = new ProcessBuilder(cmd);
|
||||||
pb.inheritIO();
|
pb.inheritIO();
|
||||||
System.exit(pb.start().waitFor());
|
System.exit(pb.start().waitFor());
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package net.torvald.terrarum.modulebasegame
|
package net.torvald.terrarum
|
||||||
|
|
||||||
import net.torvald.random.HQRNG
|
import net.torvald.random.HQRNG
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@@ -9,6 +9,7 @@ import com.jme3.math.FastMath
|
|||||||
import net.torvald.terrarum.langpack.Lang
|
import net.torvald.terrarum.langpack.Lang
|
||||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||||
import net.torvald.terrarum.ui.Toolkit
|
import net.torvald.terrarum.ui.Toolkit
|
||||||
|
import kotlin.math.max
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2017-07-13.
|
* Created by minjaesong on 2017-07-13.
|
||||||
@@ -46,7 +47,7 @@ object SanicLoadScreen : LoadScreenBase() {
|
|||||||
|
|
||||||
textFbo = FrameBuffer(
|
textFbo = FrameBuffer(
|
||||||
Pixmap.Format.RGBA4444,
|
Pixmap.Format.RGBA4444,
|
||||||
maxOf(
|
max(
|
||||||
App.fontGame.getWidth(Lang["MENU_IO_LOADING"]),
|
App.fontGame.getWidth(Lang["MENU_IO_LOADING"]),
|
||||||
App.fontGame.getWidth(Lang["ERROR_GENERIC_TEXT"])
|
App.fontGame.getWidth(Lang["ERROR_GENERIC_TEXT"])
|
||||||
),
|
),
|
||||||
@@ -61,7 +62,7 @@ object SanicLoadScreen : LoadScreenBase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
val textX: Float; get() = (App.scr.width * 0.72f).floor()
|
val textX: Float; get() = (App.scr.width * 0.72f).floorToFloat()
|
||||||
|
|
||||||
private var genuineSonic = false // the "NOW LOADING..." won't appear unless the arrow first run passes it
|
private var genuineSonic = false // the "NOW LOADING..." won't appear unless the arrow first run passes it
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,27 @@
|
|||||||
package net.torvald.terrarum
|
package net.torvald.terrarum
|
||||||
|
|
||||||
|
import com.badlogic.gdx.graphics.Pixmap
|
||||||
|
import com.badlogic.gdx.graphics.Texture
|
||||||
|
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
||||||
|
import com.badlogic.gdx.utils.JsonWriter
|
||||||
import net.torvald.terrarum.App.printdbg
|
import net.torvald.terrarum.App.printdbg
|
||||||
import net.torvald.terrarum.savegame.DiskSkimmer
|
import net.torvald.terrarum.gameactors.AVKey
|
||||||
|
import net.torvald.terrarum.savegame.*
|
||||||
|
import net.torvald.terrarum.savegame.VDFileID.PLAYER_SCREENSHOT
|
||||||
|
import net.torvald.terrarum.savegame.VDFileID.ROOT
|
||||||
|
import net.torvald.terrarum.savegame.VDFileID.SAVEGAMEINFO
|
||||||
|
import net.torvald.terrarum.savegame.VDFileID.WORLD_SCREENSHOT
|
||||||
|
import net.torvald.terrarum.serialise.Common
|
||||||
|
import net.torvald.terrarum.utils.JsonFetcher
|
||||||
|
import net.torvald.terrarum.utils.forEachSiblings
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
import java.nio.file.StandardCopyOption
|
import java.nio.file.StandardCopyOption
|
||||||
|
import java.util.*
|
||||||
|
import java.util.zip.GZIPInputStream
|
||||||
import kotlin.io.path.Path
|
import kotlin.io.path.Path
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2023-06-24.
|
* Created by minjaesong on 2023-06-24.
|
||||||
@@ -14,7 +29,7 @@ import kotlin.io.path.Path
|
|||||||
class SavegameCollection(files0: List<DiskSkimmer>) {
|
class SavegameCollection(files0: List<DiskSkimmer>) {
|
||||||
|
|
||||||
/** Sorted in reverse by the last modified time of the files, index zero being the most recent */
|
/** Sorted in reverse by the last modified time of the files, index zero being the most recent */
|
||||||
val files = files0.sortedByDescending {
|
val files = files0.sortedBy { it.diskFile.name }.sortedByDescending {
|
||||||
it.getLastModifiedTime().shl(2) or
|
it.getLastModifiedTime().shl(2) or
|
||||||
it.diskFile.extension.matches(Regex("^[abc]${'$'}")).toLong(1) or
|
it.diskFile.extension.matches(Regex("^[abc]${'$'}")).toLong(1) or
|
||||||
it.diskFile.extension.isBlank().toLong(0)
|
it.diskFile.extension.isBlank().toLong(0)
|
||||||
@@ -57,22 +72,161 @@ class SavegameCollection(files0: List<DiskSkimmer>) {
|
|||||||
fun getBaseFile(): DiskSkimmer {
|
fun getBaseFile(): DiskSkimmer {
|
||||||
return files.first { it.diskFile.extension.isBlank() }
|
return files.first { it.diskFile.extension.isBlank() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getUUID(): UUID {
|
||||||
|
var uuid: UUID? = null
|
||||||
|
loadable().getFile(SAVEGAMEINFO)!!.let {
|
||||||
|
JsonFetcher.readFromJsonString(ByteArray64Reader(it.bytes, Common.CHARSET)).forEachSiblings { name, value ->
|
||||||
|
if (name == "worldIndex" || name == "uuid") uuid = UUID.fromString(value.asString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return uuid!!
|
||||||
|
}
|
||||||
|
|
||||||
|
fun renamePlayer(name: String) {
|
||||||
|
files.forEach { skimmer ->
|
||||||
|
skimmer.rebuild()
|
||||||
|
skimmer.getFile(SAVEGAMEINFO)!!.let { file ->
|
||||||
|
val json = JsonFetcher.readFromJsonString(ByteArray64Reader(file.bytes, Common.CHARSET))
|
||||||
|
|
||||||
|
json["actorValue"]["hashMap"]["name"]["value"].set(name) // getChild() does NOT work as [] does
|
||||||
|
|
||||||
|
val jsonBytes = json.prettyPrint(JsonWriter.OutputType.json, 0).encodeToByteArray().toByteArray64()
|
||||||
|
val newEntry = DiskEntry(SAVEGAMEINFO, ROOT, skimmer.requestFile(SAVEGAMEINFO)!!.creationDate, App.getTIME_T(), EntryFile(jsonBytes))
|
||||||
|
|
||||||
|
skimmer.appendEntry(newEntry)
|
||||||
|
|
||||||
|
skimmer.setDiskName(name, Common.CHARSET)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun renameWorld(name: String) {
|
||||||
|
files.forEach { skimmer ->
|
||||||
|
skimmer.setDiskName(name, Common.CHARSET)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getThumbnail(width: Int, height: Int, shrinkage: Double) = this.loadable().getThumbnail(width, height, shrinkage)
|
||||||
}
|
}
|
||||||
|
|
||||||
class SavegameCollectionPair(player: SavegameCollection?, world: SavegameCollection?) {
|
fun DiskSkimmer.getTgaGz(vid: EntryID, width: Int, height: Int, shrinkage: Double): TextureRegion? {
|
||||||
|
return this.requestFile(vid).let { file ->
|
||||||
|
if (file != null) {
|
||||||
|
val zippedTga = (file.contents as EntryFile).bytes
|
||||||
|
val gzin = GZIPInputStream(ByteArray64InputStream(zippedTga))
|
||||||
|
val tgaFileContents = gzin.readAllBytes(); gzin.close()
|
||||||
|
val pixmap = Pixmap(tgaFileContents, 0, tgaFileContents.size)
|
||||||
|
TextureRegion(Texture(pixmap)).also {
|
||||||
|
App.disposables.add(it.texture)
|
||||||
|
// do cropping and resizing
|
||||||
|
it.setRegion(
|
||||||
|
((pixmap.width - width*2) / shrinkage).roundToInt(),
|
||||||
|
((pixmap.height - height*2) / shrinkage).roundToInt(),
|
||||||
|
(width * shrinkage).roundToInt(),
|
||||||
|
(height * shrinkage).roundToInt()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fun DiskSkimmer.getTgaGzPixmap(vid: EntryID, width: Int, height: Int, shrinkage: Double): Pixmap? {
|
||||||
|
return this.requestFile(vid).let { file ->
|
||||||
|
if (file != null) {
|
||||||
|
val zippedTga = (file.contents as EntryFile).bytes
|
||||||
|
val gzin = GZIPInputStream(ByteArray64InputStream(zippedTga))
|
||||||
|
val tgaFileContents = gzin.readAllBytes(); gzin.close()
|
||||||
|
val pixmap = Pixmap(tgaFileContents, 0, tgaFileContents.size)
|
||||||
|
return pixmap
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fun DiskSkimmer.getThumbnail(width: Int, height: Int, shrinkage: Double) =
|
||||||
|
when (this.getSaveKind()) {
|
||||||
|
1 -> this.getTgaGz(PLAYER_SCREENSHOT, width, height, shrinkage)
|
||||||
|
2 -> this.getTgaGz(WORLD_SCREENSHOT, width, height, shrinkage)
|
||||||
|
else -> throw IllegalArgumentException("Unknown save kind: ${this.getSaveKind()}")
|
||||||
|
}
|
||||||
|
fun DiskSkimmer.getThumbnailPixmap(width: Int, height: Int, shrinkage: Double) =
|
||||||
|
when (this.getSaveKind()) {
|
||||||
|
1 -> this.getTgaGzPixmap(PLAYER_SCREENSHOT, width, height, shrinkage)
|
||||||
|
2 -> this.getTgaGzPixmap(WORLD_SCREENSHOT, width, height, shrinkage)
|
||||||
|
else -> throw IllegalArgumentException("Unknown save kind: ${this.getSaveKind()}")
|
||||||
|
}
|
||||||
|
|
||||||
private var manualPlayer: DiskSkimmer? = null
|
class SavegameCollectionPair(private val player: SavegameCollection?, private val world: SavegameCollection?) {
|
||||||
private var manualWorld: DiskSkimmer? = null
|
|
||||||
private var autoPlayer: DiskSkimmer? = null
|
// private var manualPlayer: DiskSkimmer? = null
|
||||||
private var autoWorld: DiskSkimmer? = null
|
// private var manualWorld: DiskSkimmer? = null
|
||||||
|
// private var autoPlayer: DiskSkimmer? = null
|
||||||
|
// private var autoWorld: DiskSkimmer? = null
|
||||||
|
|
||||||
|
/* removing auto/manual discrimination: on Local Asynchronous Multiplayer, if newer autosave is available, there is
|
||||||
|
* no choice but loading one to preserve the data; then why bother having two? */
|
||||||
|
private var playerDisk: DiskSkimmer? = null; private set
|
||||||
|
private var worldDisk: DiskSkimmer? = null; private set
|
||||||
|
|
||||||
var status = 0 // 0: none available, 1: loadable manual save is newer than loadable auto; 2: loadable autosave is newer than loadable manual
|
var status = 0 // 0: none available, 1: loadable manual save is newer than loadable auto; 2: loadable autosave is newer than loadable manual
|
||||||
private set
|
private set
|
||||||
|
|
||||||
var newerSaveIsDamaged = false // only when most recent save is corrupted
|
val newerSaveIsDamaged: Boolean // only when most recent save is corrupted
|
||||||
private set
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
if (player != null && world != null) {
|
||||||
|
printdbg(this, "player files: " + player.files.joinToString { it.diskFile.name })
|
||||||
|
printdbg(this, "world files:" + world.files.joinToString { it.diskFile.name })
|
||||||
|
|
||||||
|
var pc = 0
|
||||||
|
var wc = 0
|
||||||
|
|
||||||
|
playerDisk = player.files[pc]
|
||||||
|
worldDisk = world.files[wc]
|
||||||
|
|
||||||
|
while (pc < player.files.size && wc < world.files.size) {
|
||||||
|
// 0b pw
|
||||||
|
val dmgflag = playerDiskNotDamaged(playerDisk!!).toInt(1) or worldDiskNotDamaged(worldDisk!!).toInt()
|
||||||
|
|
||||||
|
when (dmgflag) {
|
||||||
|
3 -> break
|
||||||
|
2 -> {
|
||||||
|
worldDisk = world.files[++wc]
|
||||||
|
}
|
||||||
|
1 -> {
|
||||||
|
playerDisk = player.files[++pc]
|
||||||
|
}
|
||||||
|
0 -> {
|
||||||
|
worldDisk = world.files[++wc]
|
||||||
|
playerDisk = player.files[++pc]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if it's time to exit the loop and all tested saves were damaged:
|
||||||
|
if (pc == player.files.size) playerDisk = null
|
||||||
|
if (wc == world.files.size) worldDisk = null
|
||||||
|
}
|
||||||
|
|
||||||
|
newerSaveIsDamaged = (pc + wc > 0)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
newerSaveIsDamaged = false
|
||||||
|
}
|
||||||
|
|
||||||
|
status = if (playerDisk != null && worldDisk != null && (playerDisk!!.isAutosaved() || worldDisk!!.isAutosaved()))
|
||||||
|
2
|
||||||
|
else (player != null && world != null).toInt()
|
||||||
|
|
||||||
|
printdbg(this, "playerDisk = ${playerDisk?.diskFile?.path}")
|
||||||
|
printdbg(this, "worldDisk = ${worldDisk?.diskFile?.path}")
|
||||||
|
printdbg(this, "status = $status")
|
||||||
|
}
|
||||||
|
|
||||||
|
/*init {
|
||||||
printdbg(this, "init ($player, $world)")
|
printdbg(this, "init ($player, $world)")
|
||||||
|
|
||||||
if (player != null && world != null) {
|
if (player != null && world != null) {
|
||||||
@@ -119,8 +273,11 @@ class SavegameCollectionPair(player: SavegameCollection?, world: SavegameCollect
|
|||||||
pc += 1
|
pc += 1
|
||||||
wc += 1
|
wc += 1
|
||||||
}
|
}
|
||||||
else
|
// world is modified after another player playing on the same world but only left an autosave
|
||||||
|
// there is no choice but loading the autosave in such scenario to preserve the data
|
||||||
|
else {
|
||||||
wc += 1
|
wc += 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -147,7 +304,7 @@ class SavegameCollectionPair(player: SavegameCollection?, world: SavegameCollect
|
|||||||
printdbg(this, "autoWorld = ${autoWorld?.diskFile?.path}")
|
printdbg(this, "autoWorld = ${autoWorld?.diskFile?.path}")
|
||||||
printdbg(this, "status = $status")
|
printdbg(this, "status = $status")
|
||||||
}
|
}
|
||||||
}
|
} */
|
||||||
|
|
||||||
private fun DiskSkimmer.isAutosaved() = this.getSaveMode().and(0b0000_0010) != 0
|
private fun DiskSkimmer.isAutosaved() = this.getSaveMode().and(0b0000_0010) != 0
|
||||||
|
|
||||||
@@ -162,7 +319,7 @@ class SavegameCollectionPair(player: SavegameCollection?, world: SavegameCollect
|
|||||||
fun moreRecentAutosaveAvailable() = (status == 2)
|
fun moreRecentAutosaveAvailable() = (status == 2)
|
||||||
fun saveAvaliable() = (status > 0)
|
fun saveAvaliable() = (status > 0)
|
||||||
|
|
||||||
fun getManualSave(): DiskPair? {
|
/*fun getManualSave(): DiskPair? {
|
||||||
if (status == 0) return null
|
if (status == 0) return null
|
||||||
return DiskPair(manualPlayer!!, manualWorld!!)
|
return DiskPair(manualPlayer!!, manualWorld!!)
|
||||||
}
|
}
|
||||||
@@ -178,7 +335,14 @@ class SavegameCollectionPair(player: SavegameCollection?, world: SavegameCollect
|
|||||||
DiskPair(manualPlayer!!, manualWorld!!)
|
DiskPair(manualPlayer!!, manualWorld!!)
|
||||||
else
|
else
|
||||||
DiskPair(autoPlayer!!, autoWorld!!)
|
DiskPair(autoPlayer!!, autoWorld!!)
|
||||||
|
}*/
|
||||||
|
|
||||||
|
fun getLoadableSave(): DiskPair? {
|
||||||
|
return if (status == 0) null
|
||||||
|
else DiskPair(playerDisk!!, worldDisk!!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class DiskPair(val player: DiskSkimmer, val world: DiskSkimmer)
|
data class DiskPair(val player: DiskSkimmer, val world: DiskSkimmer) {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -10,7 +10,7 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
|||||||
import com.badlogic.gdx.graphics.glutils.FrameBuffer
|
import com.badlogic.gdx.graphics.glutils.FrameBuffer
|
||||||
import com.badlogic.gdx.graphics.glutils.ShapeRenderer
|
import com.badlogic.gdx.graphics.glutils.ShapeRenderer
|
||||||
import com.badlogic.gdx.utils.Disposable
|
import com.badlogic.gdx.utils.Disposable
|
||||||
import com.badlogic.gdx.utils.JsonReader
|
import com.badlogic.gdx.utils.GdxRuntimeException
|
||||||
import com.jme3.math.FastMath
|
import com.jme3.math.FastMath
|
||||||
import net.torvald.gdx.graphics.Cvec
|
import net.torvald.gdx.graphics.Cvec
|
||||||
import net.torvald.random.HQRNG
|
import net.torvald.random.HQRNG
|
||||||
@@ -26,13 +26,9 @@ import net.torvald.terrarum.gameworld.fmod
|
|||||||
import net.torvald.terrarum.itemproperties.CraftingCodex
|
import net.torvald.terrarum.itemproperties.CraftingCodex
|
||||||
import net.torvald.terrarum.itemproperties.ItemCodex
|
import net.torvald.terrarum.itemproperties.ItemCodex
|
||||||
import net.torvald.terrarum.itemproperties.MaterialCodex
|
import net.torvald.terrarum.itemproperties.MaterialCodex
|
||||||
import net.torvald.terrarum.savegame.ByteArray64Reader
|
|
||||||
import net.torvald.terrarum.savegame.DiskSkimmer
|
import net.torvald.terrarum.savegame.DiskSkimmer
|
||||||
import net.torvald.terrarum.savegame.VDFileID.SAVEGAMEINFO
|
|
||||||
import net.torvald.terrarum.serialise.Common
|
import net.torvald.terrarum.serialise.Common
|
||||||
import net.torvald.terrarum.ui.UICanvas
|
import net.torvald.terrarum.ui.UICanvas
|
||||||
import net.torvald.terrarum.utils.JsonFetcher
|
|
||||||
import net.torvald.terrarum.utils.forEachSiblings
|
|
||||||
import net.torvald.terrarum.worlddrawer.WorldCamera
|
import net.torvald.terrarum.worlddrawer.WorldCamera
|
||||||
import net.torvald.terrarumsansbitmap.gdx.TerrarumSansBitmap
|
import net.torvald.terrarumsansbitmap.gdx.TerrarumSansBitmap
|
||||||
import net.torvald.unsafe.UnsafeHelper
|
import net.torvald.unsafe.UnsafeHelper
|
||||||
@@ -40,10 +36,7 @@ import net.torvald.util.CircularArray
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.PrintStream
|
import java.io.PrintStream
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.math.absoluteValue
|
import kotlin.math.*
|
||||||
import kotlin.math.round
|
|
||||||
import kotlin.math.roundToInt
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typealias RGBA8888 = Int
|
typealias RGBA8888 = Int
|
||||||
@@ -238,16 +231,16 @@ object Terrarum : Disposable {
|
|||||||
get() = WorldCamera.zoomedY + (Gdx.input.y - Gdx.input.deltaY) / (ingame?.screenZoom ?: 1f).times(scr.magn.toDouble())
|
get() = WorldCamera.zoomedY + (Gdx.input.y - Gdx.input.deltaY) / (ingame?.screenZoom ?: 1f).times(scr.magn.toDouble())
|
||||||
/** Position of the cursor in the world, rounded */
|
/** Position of the cursor in the world, rounded */
|
||||||
@JvmStatic val mouseTileX: Int
|
@JvmStatic val mouseTileX: Int
|
||||||
get() = (mouseX / TILE_SIZE).floorInt()
|
get() = (mouseX / TILE_SIZE).floorToInt()
|
||||||
/** Position of the cursor in the world */
|
/** Position of the cursor in the world */
|
||||||
@JvmStatic val mouseTileY: Int
|
@JvmStatic val mouseTileY: Int
|
||||||
get() = (mouseY / TILE_SIZE).floorInt()
|
get() = (mouseY / TILE_SIZE).floorToInt()
|
||||||
/** Position of the cursor in the world, rounded */
|
/** Position of the cursor in the world, rounded */
|
||||||
@JvmStatic val oldMouseTileX: Int
|
@JvmStatic val oldMouseTileX: Int
|
||||||
get() = (oldMouseX / TILE_SIZE).floorInt()
|
get() = (oldMouseX / TILE_SIZE).floorToInt()
|
||||||
/** Position of the cursor in the world */
|
/** Position of the cursor in the world */
|
||||||
@JvmStatic val oldMouseTileY: Int
|
@JvmStatic val oldMouseTileY: Int
|
||||||
get() = (oldMouseY / TILE_SIZE).floorInt()
|
get() = (oldMouseY / TILE_SIZE).floorToInt()
|
||||||
inline val mouseScreenX: Int
|
inline val mouseScreenX: Int
|
||||||
get() = Gdx.input.x.div(scr.magn).roundToInt()
|
get() = Gdx.input.x.div(scr.magn).roundToInt()
|
||||||
inline val mouseScreenY: Int
|
inline val mouseScreenY: Int
|
||||||
@@ -321,8 +314,8 @@ object Terrarum : Disposable {
|
|||||||
|
|
||||||
val mx = mouseX
|
val mx = mouseX
|
||||||
val my = mouseY
|
val my = mouseY
|
||||||
val mtx = (mouseX / TILE_SIZE).floorInt()
|
val mtx = (mouseX / TILE_SIZE).floorToInt()
|
||||||
val mty = (mouseY / TILE_SIZE).floorInt()
|
val mty = (mouseY / TILE_SIZE).floorToInt()
|
||||||
val msx = mx fmod TILE_SIZED
|
val msx = mx fmod TILE_SIZED
|
||||||
val msy = my fmod TILE_SIZED
|
val msy = my fmod TILE_SIZED
|
||||||
val vector = if (msx < SMALLGAP) { // X to the left
|
val vector = if (msx < SMALLGAP) { // X to the left
|
||||||
@@ -399,8 +392,10 @@ inline fun FrameBuffer.inAction(camera: OrthographicCamera?, batch: SpriteBatch?
|
|||||||
//this.begin()
|
//this.begin()
|
||||||
FrameBufferManager.begin(this)
|
FrameBufferManager.begin(this)
|
||||||
|
|
||||||
|
val oldCamPos = camera?.position?.cpy()
|
||||||
|
|
||||||
camera?.setToOrtho(true, this.width.toFloat(), this.height.toFloat())
|
camera?.setToOrtho(true, this.width.toFloat(), this.height.toFloat())
|
||||||
camera?.position?.set((this.width / 2f).round(), (this.height / 2f).round(), 0f) // TODO floor? ceil? round?
|
camera?.position?.set((this.width / 2f).roundToFloat(), (this.height / 2f).roundToFloat(), 0f) // TODO floor? ceil? round?
|
||||||
camera?.update()
|
camera?.update()
|
||||||
batch?.projectionMatrix = camera?.combined
|
batch?.projectionMatrix = camera?.combined
|
||||||
|
|
||||||
@@ -410,6 +405,7 @@ inline fun FrameBuffer.inAction(camera: OrthographicCamera?, batch: SpriteBatch?
|
|||||||
FrameBufferManager.end()
|
FrameBufferManager.end()
|
||||||
|
|
||||||
camera?.setToOrtho(true, App.scr.wf, App.scr.hf)
|
camera?.setToOrtho(true, App.scr.wf, App.scr.hf)
|
||||||
|
camera?.position?.set(oldCamPos)
|
||||||
camera?.update()
|
camera?.update()
|
||||||
batch?.projectionMatrix = camera?.combined
|
batch?.projectionMatrix = camera?.combined
|
||||||
}
|
}
|
||||||
@@ -421,8 +417,10 @@ inline fun FrameBuffer.inActionF(camera: OrthographicCamera?, batch: SpriteBatch
|
|||||||
//this.begin()
|
//this.begin()
|
||||||
FrameBufferManager.begin(this)
|
FrameBufferManager.begin(this)
|
||||||
|
|
||||||
|
val oldCamPos = camera?.position?.cpy()
|
||||||
|
|
||||||
camera?.setToOrtho(false, this.width.toFloat(), this.height.toFloat())
|
camera?.setToOrtho(false, this.width.toFloat(), this.height.toFloat())
|
||||||
camera?.position?.set((this.width / 2f).round(), (this.height / 2f).round(), 0f) // TODO floor? ceil? round?
|
camera?.position?.set((this.width / 2f).roundToFloat(), (this.height / 2f).roundToFloat(), 0f) // TODO floor? ceil? round?
|
||||||
camera?.update()
|
camera?.update()
|
||||||
batch?.projectionMatrix = camera?.combined
|
batch?.projectionMatrix = camera?.combined
|
||||||
|
|
||||||
@@ -432,6 +430,7 @@ inline fun FrameBuffer.inActionF(camera: OrthographicCamera?, batch: SpriteBatch
|
|||||||
FrameBufferManager.end()
|
FrameBufferManager.end()
|
||||||
|
|
||||||
camera?.setToOrtho(true, App.scr.wf, App.scr.hf)
|
camera?.setToOrtho(true, App.scr.wf, App.scr.hf)
|
||||||
|
camera?.position?.set(oldCamPos)
|
||||||
camera?.update()
|
camera?.update()
|
||||||
batch?.projectionMatrix = camera?.combined
|
batch?.projectionMatrix = camera?.combined
|
||||||
}
|
}
|
||||||
@@ -611,28 +610,28 @@ val emphVerb = TerrarumSansBitmap.toColorCode(0xFFF6)
|
|||||||
|
|
||||||
typealias Second = Float
|
typealias Second = Float
|
||||||
|
|
||||||
fun Int.sqr(): Int = this * this
|
inline fun Double.floorToInt() = floor(this).toInt()
|
||||||
fun Double.floorInt() = Math.floor(this).toInt()
|
inline fun Float.floorToInt() = FastMath.floor(this)
|
||||||
fun Float.floorInt() = FastMath.floor(this)
|
inline fun Double.ceilToInt() = Math.ceil(this).toInt()
|
||||||
fun Float.floor() = FastMath.floor(this).toFloat()
|
inline fun Float.ceilToFloat(): Float = FastMath.ceil(this).toFloat()
|
||||||
fun Double.ceilInt() = Math.ceil(this).toInt()
|
inline fun Float.ceilToInt() = FastMath.ceil(this)
|
||||||
fun Float.ceil(): Float = FastMath.ceil(this).toFloat()
|
inline fun Float.floorToFloat() = FastMath.floor(this).toFloat()
|
||||||
fun Float.ceilInt() = FastMath.ceil(this)
|
inline fun Float.roundToFloat(): Float = round(this)
|
||||||
fun Float.round(): Float = round(this)
|
//inline fun Double.round() = Math.round(this).toDouble()
|
||||||
fun Double.round() = Math.round(this).toDouble()
|
inline fun Double.floorToDouble() = floor(this)
|
||||||
fun Double.floor() = Math.floor(this)
|
inline fun Double.ceilToDouble() = ceil(this)
|
||||||
fun Double.ceil() = this.floor() + 1.0
|
inline fun Int.sqr(): Int = this * this
|
||||||
fun Double.abs() = Math.abs(this)
|
inline fun Double.sqr() = this * this
|
||||||
fun Double.sqr() = this * this
|
inline fun Float.sqr() = this * this
|
||||||
fun Float.sqr() = this * this
|
inline fun Double.sqrt() = Math.sqrt(this)
|
||||||
fun Double.sqrt() = Math.sqrt(this)
|
inline fun Float.sqrt() = FastMath.sqrt(this)
|
||||||
fun Float.sqrt() = FastMath.sqrt(this)
|
inline fun Int.abs() = this.absoluteValue
|
||||||
fun Int.abs() = this.absoluteValue
|
inline fun Double.abs() = this.absoluteValue
|
||||||
fun Double.bipolarClamp(limit: Double) = this.coerceIn(-limit, limit)
|
inline fun Double.bipolarClamp(limit: Double) = this.coerceIn(-limit, limit)
|
||||||
fun Boolean.toInt(shift: Int = 0) = if (this) 1.shl(shift) else 0
|
inline fun Boolean.toInt(shift: Int = 0) = if (this) 1.shl(shift) else 0
|
||||||
fun Boolean.toLong(shift: Int = 0) = if (this) 1L.shl(shift) else 0L
|
inline fun Boolean.toLong(shift: Int = 0) = if (this) 1L.shl(shift) else 0L
|
||||||
fun Int.bitCount() = java.lang.Integer.bitCount(this)
|
inline fun Int.bitCount() = java.lang.Integer.bitCount(this)
|
||||||
fun Long.bitCount() = java.lang.Long.bitCount(this)
|
inline fun Long.bitCount() = java.lang.Long.bitCount(this)
|
||||||
|
|
||||||
|
|
||||||
fun absMax(left: Double, right: Double): Double {
|
fun absMax(left: Double, right: Double): Double {
|
||||||
@@ -651,7 +650,6 @@ fun absMax(left: Double, right: Double): Double {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun Double.magnSqr() = if (this >= 0.0) this.sqr() else -this.sqr()
|
fun Double.magnSqr() = if (this >= 0.0) this.sqr() else -this.sqr()
|
||||||
fun Double.sign() = if (this > 0.0) 1.0 else if (this < 0.0) -1.0 else 0.0
|
|
||||||
fun interpolateLinear(scale: Double, startValue: Double, endValue: Double): Double {
|
fun interpolateLinear(scale: Double, startValue: Double, endValue: Double): Double {
|
||||||
if (startValue == endValue) {
|
if (startValue == endValue) {
|
||||||
return startValue
|
return startValue
|
||||||
@@ -788,6 +786,7 @@ fun AppUpdateListOfSavegames() {
|
|||||||
|
|
||||||
println("Listing saved worlds...")
|
println("Listing saved worlds...")
|
||||||
|
|
||||||
|
|
||||||
// create list of worlds
|
// create list of worlds
|
||||||
File(worldsDir).listFiles().filter { !it.isDirectory && !it.name.contains('.') }.mapNotNull { file ->
|
File(worldsDir).listFiles().filter { !it.isDirectory && !it.name.contains('.') }.mapNotNull { file ->
|
||||||
try {
|
try {
|
||||||
@@ -800,17 +799,20 @@ fun AppUpdateListOfSavegames() {
|
|||||||
}
|
}
|
||||||
}.sortedByDescending { it.getLastModifiedTime() }.forEachIndexed { index, it ->
|
}.sortedByDescending { it.getLastModifiedTime() }.forEachIndexed { index, it ->
|
||||||
println("${index+1}.\t${it.diskFile.absolutePath}")
|
println("${index+1}.\t${it.diskFile.absolutePath}")
|
||||||
it.rebuild()
|
// it.rebuild()
|
||||||
|
|
||||||
val jsonFile = it.getFile(SAVEGAMEINFO)!!
|
// val jsonFile = it.getFile(SAVEGAMEINFO)!!
|
||||||
var worldUUID: UUID? = null
|
// var worldUUID: UUID? = null
|
||||||
JsonFetcher.readFromJsonString(ByteArray64Reader(jsonFile.bytes, Common.CHARSET)).forEachSiblings { name, value ->
|
// JsonFetcher.readFromJsonString(ByteArray64Reader(jsonFile.bytes, Common.CHARSET)).forEachSiblings { name, value ->
|
||||||
if (name == "worldIndex") worldUUID = UUID.fromString(value.asString())
|
// if (name == "worldIndex") worldUUID = UUID.fromString(value.asString())
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
val collection = SavegameCollection.collectFromBaseFilename(File(worldsDir), it.diskFile.name)
|
||||||
|
val worldUUID = collection.getUUID()
|
||||||
|
|
||||||
// if multiple valid savegames with same UUID exist, only the most recent one is retained
|
// if multiple valid savegames with same UUID exist, only the most recent one is retained
|
||||||
if (!App.savegameWorlds.contains(worldUUID)) {
|
if (!App.savegameWorlds.contains(worldUUID)) {
|
||||||
App.savegameWorlds[worldUUID] = SavegameCollection.collectFromBaseFilename(File(worldsDir), it.diskFile.name)
|
App.savegameWorlds[worldUUID] = collection
|
||||||
App.savegameWorldsName[worldUUID] = it.getDiskName(Common.CHARSET)
|
App.savegameWorldsName[worldUUID] = it.getDiskName(Common.CHARSET)
|
||||||
App.sortedSavegameWorlds.add(worldUUID)
|
App.sortedSavegameWorlds.add(worldUUID)
|
||||||
}
|
}
|
||||||
@@ -832,22 +834,30 @@ fun AppUpdateListOfSavegames() {
|
|||||||
}
|
}
|
||||||
}.sortedByDescending { it.getLastModifiedTime() }.forEachIndexed { index, it ->
|
}.sortedByDescending { it.getLastModifiedTime() }.forEachIndexed { index, it ->
|
||||||
println("${index+1}.\t${it.diskFile.absolutePath}")
|
println("${index+1}.\t${it.diskFile.absolutePath}")
|
||||||
it.rebuild()
|
// it.rebuild()
|
||||||
|
|
||||||
val jsonFile = it.getFile(SAVEGAMEINFO)!!
|
// val jsonFile = it.getFile(SAVEGAMEINFO)!!
|
||||||
var playerUUID: UUID? = null
|
// var playerUUID: UUID? = null
|
||||||
JsonFetcher.readFromJsonString(ByteArray64Reader(jsonFile.bytes, Common.CHARSET)).forEachSiblings { name, value ->
|
// JsonFetcher.readFromJsonString(ByteArray64Reader(jsonFile.bytes, Common.CHARSET)).forEachSiblings { name, value ->
|
||||||
if (name == "uuid") playerUUID = UUID.fromString(value.asString())
|
// if (name == "uuid") playerUUID = UUID.fromString(value.asString())
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
val collection = SavegameCollection.collectFromBaseFilename(File(playersDir), it.diskFile.name)
|
||||||
|
val playerUUID = collection.getUUID()
|
||||||
|
|
||||||
// if multiple valid savegames with same UUID exist, only the most recent one is retained
|
// if multiple valid savegames with same UUID exist, only the most recent one is retained
|
||||||
if (!App.savegamePlayers.contains(playerUUID)) {
|
if (!App.savegamePlayers.contains(playerUUID)) {
|
||||||
App.savegamePlayers[playerUUID] = SavegameCollection.collectFromBaseFilename(File(playersDir), it.diskFile.name)
|
App.savegamePlayers[playerUUID] = collection
|
||||||
App.savegamePlayersName[playerUUID] = it.getDiskName(Common.CHARSET)
|
App.savegamePlayersName[playerUUID] = it.getDiskName(Common.CHARSET)
|
||||||
App.sortedPlayers.add(playerUUID)
|
App.sortedPlayers.add(playerUUID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
println("SortedPlayers...")
|
||||||
|
App.sortedPlayers.forEach {
|
||||||
|
println(it)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -887,3 +897,11 @@ fun checkForSavegameDamage(skimmer: DiskSkimmer): Boolean {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No lateinit!
|
||||||
|
*/
|
||||||
|
inline fun Disposable.tryDispose() {
|
||||||
|
try { this.dispose() }
|
||||||
|
catch (_: Throwable) {}
|
||||||
|
}
|
||||||
@@ -63,7 +63,7 @@ object TerrarumPostProcessor : Disposable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun resize(w: Int, h: Int) {
|
fun resize(w: Int, h: Int) {
|
||||||
try { outFBO.dispose() } catch (_: UninitializedPropertyAccessException) {}
|
if (::outFBO.isInitialized) outFBO.tryDispose()
|
||||||
outFBO = FrameBuffer(Pixmap.Format.RGBA8888, w, h, false)
|
outFBO = FrameBuffer(Pixmap.Format.RGBA8888, w, h, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,10 +71,10 @@ object TerrarumPostProcessor : Disposable {
|
|||||||
batch.dispose()
|
batch.dispose()
|
||||||
shapeRenderer.dispose()
|
shapeRenderer.dispose()
|
||||||
functionRowHelper.dispose()
|
functionRowHelper.dispose()
|
||||||
try { lutTex.dispose() } catch (_: UninitializedPropertyAccessException) {}
|
|
||||||
shaderPostDither.dispose()
|
shaderPostDither.dispose()
|
||||||
shaderPostNoDither.dispose()
|
shaderPostNoDither.dispose()
|
||||||
outFBO.dispose()
|
if (::lutTex.isInitialized) lutTex.tryDispose()
|
||||||
|
if (::outFBO.isInitialized) outFBO.dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
private var deltatBenchStr = "ΔF: Gathering data"
|
private var deltatBenchStr = "ΔF: Gathering data"
|
||||||
@@ -168,11 +168,11 @@ object TerrarumPostProcessor : Disposable {
|
|||||||
val average = tallies.average()
|
val average = tallies.average()
|
||||||
|
|
||||||
val halfPos = 0.5f * INGAME.deltaTeeBenchmarks.size
|
val halfPos = 0.5f * INGAME.deltaTeeBenchmarks.size
|
||||||
val halfInd = halfPos.floorInt()
|
val halfInd = halfPos.floorToInt()
|
||||||
val low5pos = 0.05f * INGAME.deltaTeeBenchmarks.size
|
val low5pos = 0.05f * INGAME.deltaTeeBenchmarks.size
|
||||||
val low5ind = low5pos.floorInt()
|
val low5ind = low5pos.floorToInt()
|
||||||
val low1pos = 0.01f * INGAME.deltaTeeBenchmarks.size
|
val low1pos = 0.01f * INGAME.deltaTeeBenchmarks.size
|
||||||
val low1ind = low1pos.floorInt()
|
val low1ind = low1pos.floorToInt()
|
||||||
|
|
||||||
val median = FastMath.interpolateLinear(halfPos - halfInd, tallies[halfInd], tallies[halfInd + 1])
|
val median = FastMath.interpolateLinear(halfPos - halfInd, tallies[halfInd], tallies[halfInd + 1])
|
||||||
val low5 = FastMath.interpolateLinear(low5pos - low5ind, tallies[low5ind], tallies[low5ind + 1])
|
val low5 = FastMath.interpolateLinear(low5pos - low5ind, tallies[low5ind], tallies[low5ind + 1])
|
||||||
@@ -196,35 +196,35 @@ object TerrarumPostProcessor : Disposable {
|
|||||||
private fun Double.format(digits: Int) = "%.${digits}f".format(this)
|
private fun Double.format(digits: Int) = "%.${digits}f".format(this)
|
||||||
private fun Float.format(digits: Int) = "%.${digits}f".format(this)
|
private fun Float.format(digits: Int) = "%.${digits}f".format(this)
|
||||||
|
|
||||||
private val swizzler = intArrayOf(
|
private val swizzler = floatArrayOf(
|
||||||
1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1,
|
1f,0f,0f,0f, 0f,1f,0f,0f, 0f,0f,1f,0f, 0f,0f,0f,1f,
|
||||||
1,0,0,0, 0,1,0,0, 0,0,0,1, 0,0,1,0,
|
1f,0f,0f,0f, 0f,1f,0f,0f, 0f,0f,0f,1f, 0f,0f,1f,0f,
|
||||||
1,0,0,0, 0,0,1,0, 0,1,0,0, 0,0,0,1,
|
1f,0f,0f,0f, 0f,0f,1f,0f, 0f,1f,0f,0f, 0f,0f,0f,1f,
|
||||||
1,0,0,0, 0,0,1,0, 0,0,0,1, 0,1,0,0,
|
1f,0f,0f,0f, 0f,0f,1f,0f, 0f,0f,0f,1f, 0f,1f,0f,0f,
|
||||||
1,0,0,0, 0,0,0,1, 0,1,0,0, 0,0,1,0,
|
1f,0f,0f,0f, 0f,0f,0f,1f, 0f,1f,0f,0f, 0f,0f,1f,0f,
|
||||||
1,0,0,0, 0,0,0,1, 0,0,1,0, 0,1,0,0,
|
1f,0f,0f,0f, 0f,0f,0f,1f, 0f,0f,1f,0f, 0f,1f,0f,0f,
|
||||||
|
|
||||||
0,1,0,0, 1,0,0,0, 0,0,1,0, 0,0,0,1,
|
0f,1f,0f,0f, 1f,0f,0f,0f, 0f,0f,1f,0f, 0f,0f,0f,1f,
|
||||||
0,1,0,0, 1,0,0,0, 0,0,0,1, 0,0,1,0,
|
0f,1f,0f,0f, 1f,0f,0f,0f, 0f,0f,0f,1f, 0f,0f,1f,0f,
|
||||||
0,1,0,0, 0,0,1,0, 1,0,0,0, 0,0,0,1,
|
0f,1f,0f,0f, 0f,0f,1f,0f, 1f,0f,0f,0f, 0f,0f,0f,1f,
|
||||||
0,1,0,0, 0,0,1,0, 0,0,0,1, 1,0,0,0,
|
0f,1f,0f,0f, 0f,0f,1f,0f, 0f,0f,0f,1f, 1f,0f,0f,0f,
|
||||||
0,1,0,0, 0,0,0,1, 1,0,0,0, 0,0,1,0,
|
0f,1f,0f,0f, 0f,0f,0f,1f, 1f,0f,0f,0f, 0f,0f,1f,0f,
|
||||||
0,1,0,0, 0,0,0,1, 0,0,1,0, 1,0,0,0,
|
0f,1f,0f,0f, 0f,0f,0f,1f, 0f,0f,1f,0f, 1f,0f,0f,0f,
|
||||||
|
|
||||||
0,0,1,0, 1,0,0,0, 0,1,0,0, 0,0,0,1,
|
0f,0f,1f,0f, 1f,0f,0f,0f, 0f,1f,0f,0f, 0f,0f,0f,1f,
|
||||||
0,0,1,0, 1,0,0,0, 0,0,0,1, 0,1,0,0,
|
0f,0f,1f,0f, 1f,0f,0f,0f, 0f,0f,0f,1f, 0f,1f,0f,0f,
|
||||||
0,0,1,0, 0,1,0,0, 1,0,0,0, 0,0,0,1,
|
0f,0f,1f,0f, 0f,1f,0f,0f, 1f,0f,0f,0f, 0f,0f,0f,1f,
|
||||||
0,0,1,0, 0,1,0,0, 0,0,0,1, 1,0,0,0,
|
0f,0f,1f,0f, 0f,1f,0f,0f, 0f,0f,0f,1f, 1f,0f,0f,0f,
|
||||||
0,0,1,0, 0,0,0,1, 1,0,0,0, 0,1,0,0,
|
0f,0f,1f,0f, 0f,0f,0f,1f, 1f,0f,0f,0f, 0f,1f,0f,0f,
|
||||||
0,0,1,0, 0,0,0,1, 0,1,0,0, 1,0,0,0,
|
0f,0f,1f,0f, 0f,0f,0f,1f, 0f,1f,0f,0f, 1f,0f,0f,0f,
|
||||||
|
|
||||||
0,0,0,1, 1,0,0,0, 0,1,0,0, 0,0,1,0,
|
0f,0f,0f,1f, 1f,0f,0f,0f, 0f,1f,0f,0f, 0f,0f,1f,0f,
|
||||||
0,0,0,1, 1,0,0,0, 0,0,1,0, 0,1,0,0,
|
0f,0f,0f,1f, 1f,0f,0f,0f, 0f,0f,1f,0f, 0f,1f,0f,0f,
|
||||||
0,0,0,1, 0,1,0,0, 1,0,0,0, 0,0,1,0,
|
0f,0f,0f,1f, 0f,1f,0f,0f, 1f,0f,0f,0f, 0f,0f,1f,0f,
|
||||||
0,0,0,1, 0,1,0,0, 0,0,1,0, 1,0,0,0,
|
0f,0f,0f,1f, 0f,1f,0f,0f, 0f,0f,1f,0f, 1f,0f,0f,0f,
|
||||||
0,0,0,1, 0,0,1,0, 1,0,0,0, 0,1,0,0,
|
0f,0f,0f,1f, 0f,0f,1f,0f, 1f,0f,0f,0f, 0f,1f,0f,0f,
|
||||||
0,0,0,1, 0,0,1,0, 0,1,0,0, 1,0,0,0,
|
0f,0f,0f,1f, 0f,0f,1f,0f, 0f,1f,0f,0f, 1f,0f,0f,0f,
|
||||||
).map { it.toFloat() }.toFloatArray()
|
)
|
||||||
|
|
||||||
private fun postShader(projMat: Matrix4, fbo: FrameBuffer) {
|
private fun postShader(projMat: Matrix4, fbo: FrameBuffer) {
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
package net.torvald.terrarum
|
package net.torvald.terrarum
|
||||||
|
|
||||||
import net.torvald.terrarum.App.printdbg
|
import net.torvald.terrarum.App.printdbg
|
||||||
|
import kotlin.math.max
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
class TerrarumScreenSize(scrw: Int = defaultW, scrh: Int = defaultH) {
|
class TerrarumScreenSize(scrw: Int = defaultW, scrh: Int = defaultH) {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val minimumW = 1080
|
const val minimumW = 1024
|
||||||
const val minimumH = 720
|
const val minimumH = 720
|
||||||
const val defaultW = 1280
|
const val defaultW = 1280
|
||||||
const val defaultH = 720
|
const val defaultH = 720
|
||||||
@@ -39,7 +40,7 @@ class TerrarumScreenSize(scrw: Int = defaultW, scrh: Int = defaultH) {
|
|||||||
var windowH: Int = 0; private set
|
var windowH: Int = 0; private set
|
||||||
|
|
||||||
init {
|
init {
|
||||||
setDimension(maxOf(minimumW, scrw), maxOf(minimumH, scrh), App.getConfigDouble("screenmagnifying").toFloat())
|
setDimension(max(minimumW, scrw), max(minimumH, scrh), App.getConfigDouble("screenmagnifying").toFloat())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setDimension(scrw: Int, scrh: Int, magn: Float,) {
|
fun setDimension(scrw: Int, scrh: Int, magn: Float,) {
|
||||||
@@ -56,8 +57,8 @@ class TerrarumScreenSize(scrw: Int = defaultW, scrh: Int = defaultH) {
|
|||||||
|
|
||||||
this.magn = magn
|
this.magn = magn
|
||||||
|
|
||||||
windowW = (scrw * magn).ceilInt() and 0x7FFFFFFE
|
windowW = (scrw * magn).ceilToInt() and 0x7FFFFFFE
|
||||||
windowH = (scrh * magn).ceilInt() and 0x7FFFFFFE
|
windowH = (scrh * magn).ceilToInt() and 0x7FFFFFFE
|
||||||
|
|
||||||
|
|
||||||
printdbg(this, "Window dim: $windowW x $windowH, called by:")
|
printdbg(this, "Window dim: $windowW x $windowH, called by:")
|
||||||
|
|||||||
@@ -166,7 +166,7 @@ class UIItemInventoryCatBar(
|
|||||||
// set up underlined indicator
|
// set up underlined indicator
|
||||||
init {
|
init {
|
||||||
// procedurally generate texture
|
// procedurally generate texture
|
||||||
val pixmap = Pixmap(catIcons.tileW + buttonGapSize.floorInt(), 1, Pixmap.Format.RGBA8888)
|
val pixmap = Pixmap(catIcons.tileW + buttonGapSize.floorToInt(), 1, Pixmap.Format.RGBA8888)
|
||||||
for (x in 0 until pixmap.width.plus(1).ushr(1)) { // eqv. of ceiling the half-int
|
for (x in 0 until pixmap.width.plus(1).ushr(1)) { // eqv. of ceiling the half-int
|
||||||
val col = /*if (x == 0)*/ /*0xffffff_80.toInt()*/
|
val col = /*if (x == 0)*/ /*0xffffff_80.toInt()*/
|
||||||
/*else if (x == 1)*/ /*0xffffff_c0.toInt()*/
|
/*else if (x == 1)*/ /*0xffffff_c0.toInt()*/
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ object BlockPropUtil {
|
|||||||
return when (prop.dynamicLuminosityFunction) {
|
return when (prop.dynamicLuminosityFunction) {
|
||||||
1 -> getTorchFlicker(prop)
|
1 -> getTorchFlicker(prop)
|
||||||
2 -> (INGAME.world).globalLight.cpy() // current global light
|
2 -> (INGAME.world).globalLight.cpy() // current global light
|
||||||
3 -> WeatherMixer.getGlobalLightOfTime(INGAME.world, WorldTime.DAY_LENGTH / 2).cpy() // daylight at noon
|
3 -> WeatherMixer.getGlobalLightOfTimeOfNoon().cpy() // daylight at noon
|
||||||
4 -> getSlowBreath(prop)
|
4 -> getSlowBreath(prop)
|
||||||
5 -> getPulsate(prop)
|
5 -> getPulsate(prop)
|
||||||
else -> prop.baseLumCol
|
else -> prop.baseLumCol
|
||||||
|
|||||||
@@ -19,11 +19,12 @@ import net.torvald.terrarum.toInt
|
|||||||
import java.util.concurrent.Callable
|
import java.util.concurrent.Callable
|
||||||
import java.util.concurrent.atomic.AtomicInteger
|
import java.util.concurrent.atomic.AtomicInteger
|
||||||
import kotlin.math.absoluteValue
|
import kotlin.math.absoluteValue
|
||||||
|
import kotlin.math.max
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
object MinimapComposer : Disposable {
|
object MinimapComposer : Disposable {
|
||||||
|
|
||||||
private val threadExecutor = ThreadExecutor(maxOf(1, App.THREAD_COUNT.times(2).div(3)))
|
private val threadExecutor = ThreadExecutor(max(1, App.THREAD_COUNT.times(2).div(3)))
|
||||||
|
|
||||||
const val SQUARE_SIZE = 13 // preferably in odd number
|
const val SQUARE_SIZE = 13 // preferably in odd number
|
||||||
|
|
||||||
|
|||||||
99
src/net/torvald/terrarum/clut/GenerateSkyboxTextureAtlas.kt
Normal file
99
src/net/torvald/terrarum/clut/GenerateSkyboxTextureAtlas.kt
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
package net.torvald.terrarum.clut
|
||||||
|
|
||||||
|
import net.torvald.colourutil.CIEXYZ
|
||||||
|
import net.torvald.colourutil.toColor
|
||||||
|
import net.torvald.colourutil.toRGB
|
||||||
|
import net.torvald.parametricsky.ArHosekSkyModel
|
||||||
|
import net.torvald.terrarum.abs
|
||||||
|
import net.torvald.terrarum.clut.Skybox.coerceInSmoothly
|
||||||
|
import net.torvald.terrarum.clut.Skybox.mapCircle
|
||||||
|
import net.torvald.terrarum.clut.Skybox.scaleToFit
|
||||||
|
import net.torvald.terrarum.modulebasegame.worldgenerator.HALF_PI
|
||||||
|
import net.torvald.terrarum.serialise.toLittle
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2023-08-01.
|
||||||
|
*/
|
||||||
|
fun main() {
|
||||||
|
// y: increasing turbidity (1.0 .. 10.0, in steps of 0.333)
|
||||||
|
// x: elevations (-75 .. 75 in steps of 1, then albedo of [0.1, 0.3, 0.5, 0.7, 0.9])
|
||||||
|
val texh = Skybox.gradSize * Skybox.turbCnt
|
||||||
|
val texw = Skybox.elevCnt * Skybox.albedoCnt
|
||||||
|
val TGA_HEADER_SIZE = 18
|
||||||
|
|
||||||
|
val bytes = ByteArray(TGA_HEADER_SIZE + texw * texh * 4 + 26)
|
||||||
|
// write header
|
||||||
|
byteArrayOf(
|
||||||
|
0, // ID field
|
||||||
|
0, // colour map (none)
|
||||||
|
2, // colour type (unmapped RGB)
|
||||||
|
0,0,0,0,0, // colour map spec (empty)
|
||||||
|
0,0, // x origin (0)
|
||||||
|
0,0, // y origin (0)
|
||||||
|
(texw and 255).toByte(),(texw.ushr(8) and 255).toByte(), // width
|
||||||
|
(texh and 255).toByte(),(texh.ushr(8) and 255).toByte(), // height
|
||||||
|
32, // bits-per-pixel (8bpp RGBA)
|
||||||
|
8 // image descriptor
|
||||||
|
).forEachIndexed { i,b -> bytes[i] = b }
|
||||||
|
// write footer
|
||||||
|
"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000TRUEVISION-XFILE\u002E\u0000".forEachIndexed { i, c -> bytes[18 + texw * texh * 4 + i] =
|
||||||
|
c.code.toByte()
|
||||||
|
}
|
||||||
|
|
||||||
|
println("Generating texture atlas ($texw x $texh)...")
|
||||||
|
|
||||||
|
// write pixels
|
||||||
|
for (albedo0 in 0 until Skybox.albedoCnt) {
|
||||||
|
val albedo = Skybox.albedos[albedo0]
|
||||||
|
println("Albedo=$albedo")
|
||||||
|
for (turb0 in 0 until Skybox.turbCnt) {
|
||||||
|
val turbidity = Skybox.turbiditiesD[turb0]
|
||||||
|
println("....... Turbidity=$turbidity")
|
||||||
|
for (elev0 in 0 until Skybox.elevCnt) {
|
||||||
|
val elevationDeg = Skybox.elevationsD[elev0]
|
||||||
|
val elevationRad = Math.toRadians(elevationDeg)
|
||||||
|
// println("... Elevation: $elevationDeg")
|
||||||
|
|
||||||
|
val state = ArHosekSkyModel.arhosek_xyz_skymodelstate_alloc_init(turbidity, albedo, elevationRad.abs())
|
||||||
|
|
||||||
|
for (yp in 0 until Skybox.gradSize) {
|
||||||
|
val yi = yp - 3
|
||||||
|
val xf = -elevationDeg / 90.0
|
||||||
|
var yf = (yi / 58.0).coerceIn(0.0, 1.0).mapCircle().coerceInSmoothly(0.0, 0.95)
|
||||||
|
|
||||||
|
// experiments visualisation: https://www.desmos.com/calculator/5crifaekwa
|
||||||
|
// if (elevationDeg < 0) yf *= 1.0 - pow(xf, 0.333)
|
||||||
|
// if (elevationDeg < 0) yf *= -2.0 * asin(xf - 1.0) / PI
|
||||||
|
if (elevationDeg < 0) yf *= Skybox.superellipsoidDecay(1.0 / 3.0, xf)
|
||||||
|
val theta = yf * HALF_PI
|
||||||
|
// vertical angle, where 0 is zenith, ±90 is ground (which is odd)
|
||||||
|
|
||||||
|
// println("$yp\t$theta")
|
||||||
|
|
||||||
|
val xyz = CIEXYZ(
|
||||||
|
ArHosekSkyModel.arhosek_tristim_skymodel_radiance(state, theta, HALF_PI, 0).toFloat(),
|
||||||
|
ArHosekSkyModel.arhosek_tristim_skymodel_radiance(state, theta, HALF_PI, 1).toFloat(),
|
||||||
|
ArHosekSkyModel.arhosek_tristim_skymodel_radiance(state, theta, HALF_PI, 2).toFloat()
|
||||||
|
)
|
||||||
|
val xyz2 = xyz.scaleToFit(elevationDeg)
|
||||||
|
val rgb = xyz2.toRGB().toColor()
|
||||||
|
val colour = rgb.toIntBits().toLittle()
|
||||||
|
|
||||||
|
val imgOffX = (albedo0 * Skybox.elevCnt + elev0)
|
||||||
|
val imgOffY = texh - 1 - (Skybox.gradSize * turb0 + yp)
|
||||||
|
val fileOffset = TGA_HEADER_SIZE + 4 * (imgOffY * texw + imgOffX)
|
||||||
|
for (i in 0..3) {
|
||||||
|
bytes[fileOffset + i] = colour[bytesLut[i]]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println("Atlas generation done!")
|
||||||
|
|
||||||
|
File("./assets/mods/basegame/weathers/main_skybox.tga").writeBytes(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val bytesLut = arrayOf(2,1,0,3,2,1,0,3) // For some reason BGRA order is what makes it work
|
||||||
240
src/net/torvald/terrarum/clut/Skybox.kt
Normal file
240
src/net/torvald/terrarum/clut/Skybox.kt
Normal file
@@ -0,0 +1,240 @@
|
|||||||
|
package net.torvald.terrarum.clut
|
||||||
|
|
||||||
|
import com.badlogic.gdx.Gdx
|
||||||
|
import com.badlogic.gdx.graphics.Pixmap
|
||||||
|
import com.badlogic.gdx.graphics.Texture
|
||||||
|
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
||||||
|
import com.badlogic.gdx.utils.Disposable
|
||||||
|
import com.jme3.math.FastMath
|
||||||
|
import net.torvald.colourutil.CIEXYZ
|
||||||
|
import net.torvald.colourutil.toColor
|
||||||
|
import net.torvald.colourutil.toRGB
|
||||||
|
import net.torvald.parametricsky.ArHosekSkyModel
|
||||||
|
import net.torvald.terrarum.App
|
||||||
|
import net.torvald.terrarum.App.printdbg
|
||||||
|
import net.torvald.terrarum.abs
|
||||||
|
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
||||||
|
import kotlin.math.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2023-07-09.
|
||||||
|
*/
|
||||||
|
object Skybox : Disposable {
|
||||||
|
|
||||||
|
private const val HALF_PI = 1.5707963267948966
|
||||||
|
private const val PI = 3.141592653589793
|
||||||
|
private const val TWO_PI = 6.283185307179586
|
||||||
|
|
||||||
|
const val gradSize = 64
|
||||||
|
|
||||||
|
private lateinit var gradTexBinLowAlbedo: Array<TextureRegion>
|
||||||
|
private lateinit var gradTexBinHighAlbedo: Array<TextureRegion>
|
||||||
|
|
||||||
|
private lateinit var tex: Texture
|
||||||
|
private lateinit var texRegions: TextureRegionPack
|
||||||
|
private lateinit var texStripRegions: TextureRegionPack
|
||||||
|
|
||||||
|
fun loadlut() {
|
||||||
|
tex = Texture(Gdx.files.internal("assets/clut/skybox.png"))
|
||||||
|
tex.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear)
|
||||||
|
texRegions = TextureRegionPack(tex, 2, gradSize - 2, 0, 2, 0, 1)
|
||||||
|
texStripRegions = TextureRegionPack(tex, elevCnt, gradSize - 2, 0, 2, 0, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// use internal LUT
|
||||||
|
/*operator fun get(elevationDeg: Double, turbidity: Double, albedo: Double): TextureRegion {
|
||||||
|
val elev = elevationDeg.coerceIn(-elevBias, elevBias).times(2.0).roundToInt().plus(150)
|
||||||
|
val turb = turbidity.coerceIn(1.0, 10.0).minus(1.0).times(turbDivisor).roundToInt()
|
||||||
|
val alb = albedo.coerceIn(0.1, 0.9).minus(0.1).times(turbDivisor).roundToInt()
|
||||||
|
return gradTexBinLowAlbedo[elev * turbCnt + turb]
|
||||||
|
}*/
|
||||||
|
|
||||||
|
// use external LUT
|
||||||
|
operator fun get(elevationDeg: Double, turbidity: Double, albedo: Double): TextureRegion {
|
||||||
|
val elev = elevationDeg.coerceIn(-elevMax, elevMax).roundToInt().plus(elevMax).roundToInt()
|
||||||
|
val turb = turbidity.coerceIn(1.0, 10.0).minus(1.0).times(turbDivisor).roundToInt()
|
||||||
|
val alb = albedo.coerceIn(0.1, 0.9).minus(0.1).times(turbDivisor).roundToInt()
|
||||||
|
//printdbg(this, "elev $elevationDeg->$elev; turb $turbidity->$turb; alb $albedo->$alb")
|
||||||
|
return texRegions.get(alb * elevCnt + elev, turb)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getUV(elevationDeg: Double, turbidity: Double, albedo: Double): Pair<Texture, FloatArray> {
|
||||||
|
val turb = turbidity.coerceIn(1.0, 10.0).minus(1.0).times(turbDivisor).roundToInt()
|
||||||
|
val alb = albedo.coerceIn(0.1, 0.9).minus(0.1).times(turbDivisor).roundToInt()
|
||||||
|
val region = texStripRegions.get(alb, turb)
|
||||||
|
|
||||||
|
val elev = elevationDeg.coerceIn(-elevMax, elevMax).plus(elevMax).div(elevations.last.toDouble()).div(albedoCnt).times((elevCnt - 1.0) / elevCnt)
|
||||||
|
|
||||||
|
val u = region.u + (0.5f / tex.width) + elev.toFloat() // because of the nature of bilinear interpolation, half pixels from the edges must be discarded
|
||||||
|
|
||||||
|
return tex to floatArrayOf(
|
||||||
|
u,
|
||||||
|
region.v,
|
||||||
|
u,
|
||||||
|
region.v2
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Float.scaleFun() =
|
||||||
|
(1f - 1f / 2f.pow(this/6f)) * 0.97f
|
||||||
|
|
||||||
|
internal fun CIEXYZ.scaleToFit(elevationDeg: Double): CIEXYZ {
|
||||||
|
return if (elevationDeg >= 0) {
|
||||||
|
CIEXYZ(
|
||||||
|
this.X.scaleFun(),
|
||||||
|
this.Y.scaleFun(),
|
||||||
|
this.Z.scaleFun(),
|
||||||
|
this.alpha
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
val deg1 = (-elevationDeg / elevMax).pow(0.93).times(-elevMax)
|
||||||
|
val elevation1 = -deg1
|
||||||
|
val elevation2 = -deg1 / 28.5
|
||||||
|
val scale = (1f - (1f - 1f / 1.8.pow(elevation1)) * 0.97f).toFloat()
|
||||||
|
val scale2 = (1.0 - (elevation2.pow(E) / E.pow(elevation2))*0.8).toFloat()
|
||||||
|
CIEXYZ(
|
||||||
|
this.X.scaleFun() * scale * scale2,
|
||||||
|
this.Y.scaleFun() * scale * scale2,
|
||||||
|
this.Z.scaleFun() * scale * scale2,
|
||||||
|
this.alpha
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val elevations = (0..150)
|
||||||
|
val elevMax = elevations.last / 2.0
|
||||||
|
val elevationsD = elevations.map { -elevMax + it } // -75, -74, -73, ..., 74, 75 // (specifically using whole number of angles because angle units any finer than 1.0 would make "hack" sunsut happen too fast)
|
||||||
|
val turbidities = (0..45) // 1, 1.2, 1.4, 1.6, ..., 10.0
|
||||||
|
val turbDivisor = 5.0
|
||||||
|
val turbiditiesD = turbidities.map { 1.0 + it / turbDivisor }
|
||||||
|
val albedos = arrayOf(0.1, 0.3, 0.5, 0.7, 0.9)
|
||||||
|
val elevCnt = elevations.count()
|
||||||
|
val turbCnt = turbidities.count()
|
||||||
|
val albedoCnt = albedos.size
|
||||||
|
val albedoLow = 0.1
|
||||||
|
val albedoHight = 0.8 // for theoretical "winter wonderland"?
|
||||||
|
val gamma = HALF_PI
|
||||||
|
|
||||||
|
internal fun Double.mapCircle() = sin(HALF_PI * this)
|
||||||
|
|
||||||
|
internal fun initiate() {
|
||||||
|
printdbg(this, "Initialising skybox model")
|
||||||
|
|
||||||
|
gradTexBinLowAlbedo = getTexturmaps(albedoLow)
|
||||||
|
gradTexBinHighAlbedo = getTexturmaps(albedoHight)
|
||||||
|
|
||||||
|
App.disposables.add(this)
|
||||||
|
|
||||||
|
printdbg(this, "Skybox model generated!")
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See https://www.desmos.com/calculator/lcvvsju3p1 for mathematical definition
|
||||||
|
* @param p decay point. 0.0..1.0
|
||||||
|
* @param q polynomial degree. 2+. Larger value means sharper transition around the point p
|
||||||
|
* @param x the 'x' value of the function, as in `y=f(x)`. 0.0..1.0
|
||||||
|
*/
|
||||||
|
internal fun polynomialDecay(p: Double, q: Int, x: Double): Double {
|
||||||
|
val sign = if (q % 2 == 1) -1 else 1
|
||||||
|
val a1 = -1.0 / p
|
||||||
|
val a2 = 1.0 / (1.0 - p)
|
||||||
|
val q = q.toDouble()
|
||||||
|
return if (x < p)
|
||||||
|
sign * a1.pow(q - 1.0) * x.pow(q) + 1.0
|
||||||
|
else
|
||||||
|
sign * a2.pow(q - 1.0) * (x - 1.0).pow(q)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun polynomialDecay2(p: Double, q: Int, x: Double): Double {
|
||||||
|
val sign = if (q % 2 == 1) 1 else -1
|
||||||
|
val a1 = -1.0 / p
|
||||||
|
val a2 = 1.0 / (1.0 - p)
|
||||||
|
val q = q.toDouble()
|
||||||
|
return if (x < p)
|
||||||
|
sign * a1.pow(q - 1.0) * x.pow(q)
|
||||||
|
else
|
||||||
|
sign * a2.pow(q - 1.0) * (x - 1.0).pow(q) + 1.0
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun superellipsoidDecay(p: Double, x: Double): Double {
|
||||||
|
return 1.0 - (1.0 - (1.0 - x).pow(1.0 / p)).pow(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun Double.coerceInSmoothly(low: Double, high: Double): Double {
|
||||||
|
val x = this.coerceIn(low, high)
|
||||||
|
val x2 = ((x - low) * (high - low).pow(-1.0))
|
||||||
|
// return FastMath.interpolateLinear(polynomialDecay2(0.5, 2, x2), low, high)
|
||||||
|
return FastMath.interpolateLinear(smoothLinear(0.2, x2), low, high)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To get the idea what the fuck is going on here, please refer to https://www.desmos.com/calculator/snqglcu2wl
|
||||||
|
*/
|
||||||
|
internal fun smoothLinear(p: Double, x0: Double): Double {
|
||||||
|
val x = x0 - 0.5
|
||||||
|
val p1 = sqrt(1.0 - 2.0 * p)
|
||||||
|
val t = 0.5 * p1
|
||||||
|
val y0 = if (x < -t)
|
||||||
|
(1.0 / p) * (x + 0.5).pow(2) - 0.5
|
||||||
|
else if (x > t)
|
||||||
|
-(1.0 / p) * (x - 0.5).pow(2) + 0.5
|
||||||
|
else
|
||||||
|
x * 2.0 / (1.0 + p1)
|
||||||
|
|
||||||
|
return y0 + 0.5
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getTexturmaps(albedo: Double): Array<TextureRegion> {
|
||||||
|
return Array(elevCnt * turbCnt) {
|
||||||
|
|
||||||
|
val elevationDeg = elevationsD[it / turbCnt]
|
||||||
|
val elevationRad = Math.toRadians(elevationDeg)
|
||||||
|
val turbidity = turbiditiesD[it % turbCnt]
|
||||||
|
|
||||||
|
val state = ArHosekSkyModel.arhosek_xyz_skymodelstate_alloc_init(turbidity, albedo, elevationRad.abs())
|
||||||
|
val pixmap = Pixmap(1, gradSize, Pixmap.Format.RGBA8888)
|
||||||
|
|
||||||
|
// printdbg(this, "elev $elevationDeg turb $turbidity")
|
||||||
|
|
||||||
|
for (yp in 0 until gradSize) {
|
||||||
|
val yi = yp - 3
|
||||||
|
val xf = -elevationDeg / 90.0
|
||||||
|
var yf = (yi / 58.0).coerceIn(0.0, 1.0).mapCircle().coerceInSmoothly(0.0, 0.95)
|
||||||
|
|
||||||
|
// experiments visualisation: https://www.desmos.com/calculator/5crifaekwa
|
||||||
|
// if (elevationDeg < 0) yf *= 1.0 - pow(xf, 0.333)
|
||||||
|
// if (elevationDeg < 0) yf *= -2.0 * asin(xf - 1.0) / PI
|
||||||
|
if (elevationDeg < 0) yf *= superellipsoidDecay(1.0 / 3.0, xf)
|
||||||
|
val theta = yf * HALF_PI
|
||||||
|
// vertical angle, where 0 is zenith, ±90 is ground (which is odd)
|
||||||
|
|
||||||
|
// println("$yp\t$theta")
|
||||||
|
|
||||||
|
val xyz = CIEXYZ(
|
||||||
|
ArHosekSkyModel.arhosek_tristim_skymodel_radiance(state, theta, gamma, 0).toFloat(),
|
||||||
|
ArHosekSkyModel.arhosek_tristim_skymodel_radiance(state, theta, gamma, 1).toFloat(),
|
||||||
|
ArHosekSkyModel.arhosek_tristim_skymodel_radiance(state, theta, gamma, 2).toFloat()
|
||||||
|
)
|
||||||
|
val xyz2 = xyz.scaleToFit(elevationDeg)
|
||||||
|
val rgb = xyz2.toRGB().toColor()
|
||||||
|
|
||||||
|
// pixmap.setColor(if (yp in 17 until 17 + 94) Color.LIME else Color.CORAL)
|
||||||
|
pixmap.setColor(rgb)
|
||||||
|
pixmap.drawPixel(0, yp)
|
||||||
|
}
|
||||||
|
|
||||||
|
val texture = Texture(pixmap).also {
|
||||||
|
it.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear)
|
||||||
|
}
|
||||||
|
pixmap.dispose()
|
||||||
|
TextureRegion(texture)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun dispose() {
|
||||||
|
if (Skybox::gradTexBinLowAlbedo.isInitialized) gradTexBinLowAlbedo.forEach { it.texture.dispose() }
|
||||||
|
if (Skybox::gradTexBinHighAlbedo.isInitialized) gradTexBinHighAlbedo.forEach { it.texture.dispose() }
|
||||||
|
if (Skybox::tex.isInitialized) tex.dispose()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -30,7 +30,7 @@ internal object SetGlobalLightOverride : ConsoleCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (args.size == 2 && args[1].trim().toLowerCase() == "none") {
|
else if (args.size == 2 && args[1].trim().lowercase() == "none") {
|
||||||
WeatherMixer.globalLightOverridden = false
|
WeatherMixer.globalLightOverridden = false
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
|||||||
import org.dyn4j.geometry.Vector2
|
import org.dyn4j.geometry.Vector2
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.math.absoluteValue
|
import kotlin.math.absoluteValue
|
||||||
|
import kotlin.math.max
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
|
|
||||||
@@ -442,7 +443,7 @@ open class ActorWithBody : Actor {
|
|||||||
@Transient val feetPosPoint: Point2d = Point2d(0.0,0.0)
|
@Transient val feetPosPoint: Point2d = Point2d(0.0,0.0)
|
||||||
//get() = Point2d(hitbox.centeredX, hitbox.endY)
|
//get() = Point2d(hitbox.centeredX, hitbox.endY)
|
||||||
@Transient val feetPosTile: Point2i = Point2i(0,0)
|
@Transient val feetPosTile: Point2i = Point2i(0,0)
|
||||||
//get() = Point2i(hIntTilewiseHitbox.centeredX.floorInt(), hIntTilewiseHitbox.endY.floorInt())
|
//get() = Point2i(hIntTilewiseHitbox.centeredX.floorToInt(), hIntTilewiseHitbox.endY.floorToInt())
|
||||||
|
|
||||||
override fun run() = update(App.UPDATE_RATE)
|
override fun run() = update(App.UPDATE_RATE)
|
||||||
|
|
||||||
@@ -474,23 +475,23 @@ open class ActorWithBody : Actor {
|
|||||||
hitbox.reassign(newHitbox)
|
hitbox.reassign(newHitbox)
|
||||||
|
|
||||||
hIntTilewiseHitbox.setFromTwoPoints(
|
hIntTilewiseHitbox.setFromTwoPoints(
|
||||||
hitbox.startX.plus(PHYS_EPSILON_DIST).div(TILE_SIZE).floor() + 0.5,
|
hitbox.startX.plus(PHYS_EPSILON_DIST).div(TILE_SIZE).floorToDouble() + 0.5,
|
||||||
hitbox.startY.plus(PHYS_EPSILON_DIST).div(TILE_SIZE).floor() + 0.5,
|
hitbox.startY.plus(PHYS_EPSILON_DIST).div(TILE_SIZE).floorToDouble() + 0.5,
|
||||||
hitbox.endX.plus(PHYS_EPSILON_DIST).div(TILE_SIZE).floor() + 0.5,
|
hitbox.endX.plus(PHYS_EPSILON_DIST).div(TILE_SIZE).floorToDouble() + 0.5,
|
||||||
hitbox.endY.plus(PHYS_EPSILON_DIST).div(TILE_SIZE).floor() + 0.5
|
hitbox.endY.plus(PHYS_EPSILON_DIST).div(TILE_SIZE).floorToDouble() + 0.5
|
||||||
)
|
)
|
||||||
intTilewiseHitbox.setFromTwoPoints(
|
intTilewiseHitbox.setFromTwoPoints(
|
||||||
hitbox.startX.div(TILE_SIZE).floor(),
|
hitbox.startX.div(TILE_SIZE).floorToDouble(),
|
||||||
hitbox.startY.div(TILE_SIZE).floor(),
|
hitbox.startY.div(TILE_SIZE).floorToDouble(),
|
||||||
hitbox.endX.minus(PHYS_EPSILON_DIST).div(TILE_SIZE).floor(),
|
hitbox.endX.minus(PHYS_EPSILON_DIST).div(TILE_SIZE).floorToDouble(),
|
||||||
hitbox.endY.minus(PHYS_EPSILON_DIST).div(TILE_SIZE).floor()
|
hitbox.endY.minus(PHYS_EPSILON_DIST).div(TILE_SIZE).floorToDouble()
|
||||||
)
|
)
|
||||||
|
|
||||||
centrePosVector.set(hitbox.centeredX, hitbox.centeredY)
|
centrePosVector.set(hitbox.centeredX, hitbox.centeredY)
|
||||||
centrePosPoint.set(hitbox.centeredX, hitbox.centeredY)
|
centrePosPoint.set(hitbox.centeredX, hitbox.centeredY)
|
||||||
feetPosVector.set(hitbox.centeredX, hitbox.endY)
|
feetPosVector.set(hitbox.centeredX, hitbox.endY)
|
||||||
feetPosPoint.set(hitbox.centeredX, hitbox.endY)
|
feetPosPoint.set(hitbox.centeredX, hitbox.endY)
|
||||||
feetPosTile.set(hIntTilewiseHitbox.centeredX.floorInt(), hIntTilewiseHitbox.endY.floorInt())
|
feetPosTile.set(hIntTilewiseHitbox.centeredX.floorToInt(), hIntTilewiseHitbox.endY.floorToInt())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun update(delta: Float) {
|
override fun update(delta: Float) {
|
||||||
@@ -618,23 +619,23 @@ open class ActorWithBody : Actor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
hIntTilewiseHitbox.setFromTwoPoints(
|
hIntTilewiseHitbox.setFromTwoPoints(
|
||||||
hitbox.startX.plus(PHYS_EPSILON_DIST).div(TILE_SIZE).floor() + 0.5,
|
hitbox.startX.plus(PHYS_EPSILON_DIST).div(TILE_SIZE).floorToDouble() + 0.5,
|
||||||
hitbox.startY.plus(PHYS_EPSILON_DIST).div(TILE_SIZE).floor() + 0.5,
|
hitbox.startY.plus(PHYS_EPSILON_DIST).div(TILE_SIZE).floorToDouble() + 0.5,
|
||||||
hitbox.endX.plus(PHYS_EPSILON_DIST).div(TILE_SIZE).floor() + 0.5,
|
hitbox.endX.plus(PHYS_EPSILON_DIST).div(TILE_SIZE).floorToDouble() + 0.5,
|
||||||
hitbox.endY.plus(PHYS_EPSILON_DIST).div(TILE_SIZE).floor() + 0.5
|
hitbox.endY.plus(PHYS_EPSILON_DIST).div(TILE_SIZE).floorToDouble() + 0.5
|
||||||
)
|
)
|
||||||
intTilewiseHitbox.setFromTwoPoints(
|
intTilewiseHitbox.setFromTwoPoints(
|
||||||
hitbox.startX.div(TILE_SIZE).floor(),
|
hitbox.startX.div(TILE_SIZE).floorToDouble(),
|
||||||
hitbox.startY.div(TILE_SIZE).floor(),
|
hitbox.startY.div(TILE_SIZE).floorToDouble(),
|
||||||
hitbox.endX.minus(PHYS_EPSILON_DIST).div(TILE_SIZE).floor(),
|
hitbox.endX.minus(PHYS_EPSILON_DIST).div(TILE_SIZE).floorToDouble(),
|
||||||
hitbox.endY.minus(PHYS_EPSILON_DIST).div(TILE_SIZE).floor()
|
hitbox.endY.minus(PHYS_EPSILON_DIST).div(TILE_SIZE).floorToDouble()
|
||||||
)
|
)
|
||||||
|
|
||||||
centrePosVector.set(hitbox.centeredX, hitbox.centeredY)
|
centrePosVector.set(hitbox.centeredX, hitbox.centeredY)
|
||||||
centrePosPoint.set(hitbox.centeredX, hitbox.centeredY)
|
centrePosPoint.set(hitbox.centeredX, hitbox.centeredY)
|
||||||
feetPosVector.set(hitbox.centeredX, hitbox.endY)
|
feetPosVector.set(hitbox.centeredX, hitbox.endY)
|
||||||
feetPosPoint.set(hitbox.centeredX, hitbox.endY)
|
feetPosPoint.set(hitbox.centeredX, hitbox.endY)
|
||||||
feetPosTile.set(hIntTilewiseHitbox.centeredX.floorInt(), hIntTilewiseHitbox.endY.floorInt())
|
feetPosTile.set(hIntTilewiseHitbox.centeredX.floorToInt(), hIntTilewiseHitbox.endY.floorToInt())
|
||||||
|
|
||||||
|
|
||||||
if (mouseUp && this.tooltipText != null) INGAME.setTooltipMessage(this.tooltipText)
|
if (mouseUp && this.tooltipText != null) INGAME.setTooltipMessage(this.tooltipText)
|
||||||
@@ -746,23 +747,23 @@ open class ActorWithBody : Actor {
|
|||||||
fun BlockAddress.isFeetTile(hitbox: Hitbox): Boolean {
|
fun BlockAddress.isFeetTile(hitbox: Hitbox): Boolean {
|
||||||
val (x, y) = LandUtil.resolveBlockAddr(world!!, this)
|
val (x, y) = LandUtil.resolveBlockAddr(world!!, this)
|
||||||
val newTilewiseHitbox = Hitbox.fromTwoPoints(
|
val newTilewiseHitbox = Hitbox.fromTwoPoints(
|
||||||
hitbox.startX.div(TILE_SIZE).floor(),
|
hitbox.startX.div(TILE_SIZE).floorToDouble(),
|
||||||
hitbox.startY.div(TILE_SIZE).floor(),
|
hitbox.startY.div(TILE_SIZE).floorToDouble(),
|
||||||
hitbox.endX.minus(PHYS_EPSILON_DIST).div(TILE_SIZE).floor(),
|
hitbox.endX.minus(PHYS_EPSILON_DIST).div(TILE_SIZE).floorToDouble(),
|
||||||
hitbox.endY.minus(PHYS_EPSILON_DIST).div(TILE_SIZE).floor(),
|
hitbox.endY.minus(PHYS_EPSILON_DIST).div(TILE_SIZE).floorToDouble(),
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
|
|
||||||
// offset 1 pixel to the down so that friction would work
|
// offset 1 pixel to the down so that friction would work
|
||||||
val yMatch = if (gravitation.y >= 0.0)
|
val yMatch = if (gravitation.y >= 0.0)
|
||||||
hitbox.endY.plus(A_PIXEL).div(TILE_SIZE).floorInt()
|
hitbox.endY.plus(A_PIXEL).div(TILE_SIZE).floorToInt()
|
||||||
else
|
else
|
||||||
hitbox.startY.minus(A_PIXEL).div(TILE_SIZE).floorInt()
|
hitbox.startY.minus(A_PIXEL).div(TILE_SIZE).floorToInt()
|
||||||
return y == yMatch && // copied from forEachFeetTileNum
|
return y == yMatch && // copied from forEachFeetTileNum
|
||||||
(x in newTilewiseHitbox.startX.toInt()..newTilewiseHitbox.endX.toInt()) // copied from forEachOccupyingTilePos
|
(x in newTilewiseHitbox.startX.toInt()..newTilewiseHitbox.endX.toInt()) // copied from forEachOccupyingTilePos
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Double.modTile() = this.div(TILE_SIZE).floorInt().times(TILE_SIZE)
|
fun Double.modTile() = this.div(TILE_SIZE).floorToInt().times(TILE_SIZE)
|
||||||
fun Double.modTileDelta() = this - this.modTile()
|
fun Double.modTileDelta() = this - this.modTile()
|
||||||
|
|
||||||
|
|
||||||
@@ -776,7 +777,7 @@ open class ActorWithBody : Actor {
|
|||||||
// the job of the ccd is that the "next hitbox" would not dig into the terrain greater than the tile size,
|
// the job of the ccd is that the "next hitbox" would not dig into the terrain greater than the tile size,
|
||||||
// in which the modTileDelta returns a wrong value
|
// in which the modTileDelta returns a wrong value
|
||||||
val vectorSum = (externalV + controllerV)
|
val vectorSum = (externalV + controllerV)
|
||||||
val ccdSteps = (vectorSum.magnitude / TILE_SIZE).floorInt().coerceIn(2, 16) // adaptive
|
val ccdSteps = (vectorSum.magnitude / TILE_SIZE).floorToInt().coerceIn(2, 16) // adaptive
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -906,15 +907,15 @@ open class ActorWithBody : Actor {
|
|||||||
|
|
||||||
// points to the EDGE of the tile in world dimension (don't use this directly to get tilewise coord!!)
|
// points to the EDGE of the tile in world dimension (don't use this directly to get tilewise coord!!)
|
||||||
val offendingTileWorldX = if (selfCollisionStatus in listOf(6, 12))
|
val offendingTileWorldX = if (selfCollisionStatus in listOf(6, 12))
|
||||||
newHitbox.endX.div(TILE_SIZE).floor() * TILE_SIZE - PHYS_EPSILON_DIST
|
newHitbox.endX.div(TILE_SIZE).floorToDouble() * TILE_SIZE - PHYS_EPSILON_DIST
|
||||||
else
|
else
|
||||||
newHitbox.startX.div(TILE_SIZE).ceil() * TILE_SIZE
|
newHitbox.startX.div(TILE_SIZE).ceilToDouble() * TILE_SIZE
|
||||||
|
|
||||||
// points to the EDGE of the tile in world dimension (don't use this directly to get tilewise coord!!)
|
// points to the EDGE of the tile in world dimension (don't use this directly to get tilewise coord!!)
|
||||||
val offendingTileWorldY = if (selfCollisionStatus in listOf(3, 6))
|
val offendingTileWorldY = if (selfCollisionStatus in listOf(3, 6))
|
||||||
newHitbox.endY.div(TILE_SIZE).floor() * TILE_SIZE - PHYS_EPSILON_DIST
|
newHitbox.endY.div(TILE_SIZE).floorToDouble() * TILE_SIZE - PHYS_EPSILON_DIST
|
||||||
else
|
else
|
||||||
newHitbox.startY.div(TILE_SIZE).ceil() * TILE_SIZE
|
newHitbox.startY.div(TILE_SIZE).ceilToDouble() * TILE_SIZE
|
||||||
|
|
||||||
val offendingHitboxPointX = if (selfCollisionStatus in listOf(6, 12))
|
val offendingHitboxPointX = if (selfCollisionStatus in listOf(6, 12))
|
||||||
newHitbox.endX
|
newHitbox.endX
|
||||||
@@ -1136,10 +1137,10 @@ open class ActorWithBody : Actor {
|
|||||||
val y2 = hitbox.endY - A_PIXEL
|
val y2 = hitbox.endY - A_PIXEL
|
||||||
// this commands and the commands on isWalled WILL NOT match (1 px gap on endX/Y). THIS IS INTENTIONAL!
|
// this commands and the commands on isWalled WILL NOT match (1 px gap on endX/Y). THIS IS INTENTIONAL!
|
||||||
|
|
||||||
val txStart = x1.plus(HALF_PIXEL).floorInt()
|
val txStart = x1.plus(HALF_PIXEL).floorToInt()
|
||||||
val txEnd = x2.plus(HALF_PIXEL).floorInt()
|
val txEnd = x2.plus(HALF_PIXEL).floorToInt()
|
||||||
val tyStart = y1.plus(HALF_PIXEL).floorInt()
|
val tyStart = y1.plus(HALF_PIXEL).floorToInt()
|
||||||
val tyEnd = y2.plus(HALF_PIXEL).floorInt()
|
val tyEnd = y2.plus(HALF_PIXEL).floorToInt()
|
||||||
|
|
||||||
return isCollidingInternalStairs(txStart, tyStart, txEnd, tyEnd, feet).first > 0
|
return isCollidingInternalStairs(txStart, tyStart, txEnd, tyEnd, feet).first > 0
|
||||||
}
|
}
|
||||||
@@ -1203,10 +1204,10 @@ open class ActorWithBody : Actor {
|
|||||||
}
|
}
|
||||||
else throw IllegalArgumentException()
|
else throw IllegalArgumentException()
|
||||||
|
|
||||||
val txStart = x1.plus(HALF_PIXEL).floorInt()
|
val txStart = x1.plus(HALF_PIXEL).floorToInt()
|
||||||
val txEnd = x2.plus(HALF_PIXEL).floorInt()
|
val txEnd = x2.plus(HALF_PIXEL).floorToInt()
|
||||||
val tyStart = y1.plus(HALF_PIXEL).floorInt()
|
val tyStart = y1.plus(HALF_PIXEL).floorToInt()
|
||||||
val tyEnd = y2.plus(HALF_PIXEL).floorInt()
|
val tyEnd = y2.plus(HALF_PIXEL).floorToInt()
|
||||||
|
|
||||||
return isCollidingInternalStairs(txStart, tyStart, txEnd, tyEnd, option == COLLIDING_BOTTOM).first == 2
|
return isCollidingInternalStairs(txStart, tyStart, txEnd, tyEnd, option == COLLIDING_BOTTOM).first == 2
|
||||||
}
|
}
|
||||||
@@ -1258,27 +1259,27 @@ open class ActorWithBody : Actor {
|
|||||||
y2 = hitbox.endY - A_PIXEL
|
y2 = hitbox.endY - A_PIXEL
|
||||||
}
|
}
|
||||||
else if (option == COLLIDING_ALLSIDE) {
|
else if (option == COLLIDING_ALLSIDE) {
|
||||||
return maxOf(maxOf(isWalledStairs(hitbox, COLLIDING_LEFT).first,
|
return max(max(isWalledStairs(hitbox, COLLIDING_LEFT).first,
|
||||||
isWalledStairs(hitbox, COLLIDING_RIGHT).first),
|
isWalledStairs(hitbox, COLLIDING_RIGHT).first),
|
||||||
maxOf(isWalledStairs(hitbox, COLLIDING_BOTTOM).first,
|
max(isWalledStairs(hitbox, COLLIDING_BOTTOM).first,
|
||||||
isWalledStairs(hitbox, COLLIDING_TOP).first)) to 0
|
isWalledStairs(hitbox, COLLIDING_TOP).first)) to 0
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (option == COLLIDING_LR) {
|
else if (option == COLLIDING_LR) {
|
||||||
val v1 = isWalledStairs(hitbox, COLLIDING_LEFT)
|
val v1 = isWalledStairs(hitbox, COLLIDING_LEFT)
|
||||||
val v2 = isWalledStairs(hitbox, COLLIDING_RIGHT)
|
val v2 = isWalledStairs(hitbox, COLLIDING_RIGHT)
|
||||||
return maxOf(v1.first, v2.first) to maxOf(v2.first, v2.second)
|
return max(v1.first, v2.first) to max(v2.first, v2.second)
|
||||||
}
|
}
|
||||||
else if (option == COLLIDING_UD) {
|
else if (option == COLLIDING_UD) {
|
||||||
return maxOf(isWalledStairs(hitbox, COLLIDING_BOTTOM).first,
|
return max(isWalledStairs(hitbox, COLLIDING_BOTTOM).first,
|
||||||
isWalledStairs(hitbox, COLLIDING_TOP).first) to 0
|
isWalledStairs(hitbox, COLLIDING_TOP).first) to 0
|
||||||
}
|
}
|
||||||
else throw IllegalArgumentException("$option")
|
else throw IllegalArgumentException("$option")
|
||||||
|
|
||||||
val pxStart = x1.plus(0.5f).floorInt()
|
val pxStart = x1.plus(0.5f).floorToInt()
|
||||||
val pxEnd = x2.plus(0.5f).floorInt()
|
val pxEnd = x2.plus(0.5f).floorToInt()
|
||||||
val pyStart = y1.plus(0.5f).floorInt()
|
val pyStart = y1.plus(0.5f).floorToInt()
|
||||||
val pyEnd = y2.plus(0.5f).floorInt()
|
val pyEnd = y2.plus(0.5f).floorToInt()
|
||||||
|
|
||||||
return isCollidingInternalStairs(pxStart, pyStart, pxEnd, pyEnd, gravitation.y >= 0.0 && option == COLLIDING_BOTTOM || gravitation.y < 0.0 && option == COLLIDING_TOP)
|
return isCollidingInternalStairs(pxStart, pyStart, pxEnd, pyEnd, gravitation.y >= 0.0 && option == COLLIDING_BOTTOM || gravitation.y < 0.0 && option == COLLIDING_TOP)
|
||||||
}
|
}
|
||||||
@@ -1890,10 +1891,10 @@ open class ActorWithBody : Actor {
|
|||||||
|
|
||||||
|
|
||||||
val newTilewiseHitbox = Hitbox.fromTwoPoints(
|
val newTilewiseHitbox = Hitbox.fromTwoPoints(
|
||||||
hitbox.startX.div(TILE_SIZE).floor(),
|
hitbox.startX.div(TILE_SIZE).floorToDouble(),
|
||||||
hitbox.startY.div(TILE_SIZE).floor(),
|
hitbox.startY.div(TILE_SIZE).floorToDouble(),
|
||||||
hitbox.endX.minus(PHYS_EPSILON_DIST).div(TILE_SIZE).floor(),
|
hitbox.endX.minus(PHYS_EPSILON_DIST).div(TILE_SIZE).floorToDouble(),
|
||||||
hitbox.endY.minus(PHYS_EPSILON_DIST).div(TILE_SIZE).floor(),
|
hitbox.endY.minus(PHYS_EPSILON_DIST).div(TILE_SIZE).floorToDouble(),
|
||||||
true
|
true
|
||||||
) // NOT the same as intTilewiseHitbox !!
|
) // NOT the same as intTilewiseHitbox !!
|
||||||
|
|
||||||
@@ -1914,7 +1915,7 @@ open class ActorWithBody : Actor {
|
|||||||
val tiles = ArrayList<ItemID?>()
|
val tiles = ArrayList<ItemID?>()
|
||||||
|
|
||||||
// offset 1 pixel to the down so that friction would work
|
// offset 1 pixel to the down so that friction would work
|
||||||
val y = hitbox.endY.plus(1.0).div(TILE_SIZE).floorInt()
|
val y = hitbox.endY.plus(1.0).div(TILE_SIZE).floorToInt()
|
||||||
|
|
||||||
for (x in hIntTilewiseHitbox.startX.toInt()..hIntTilewiseHitbox.endX.toInt()) {
|
for (x in hIntTilewiseHitbox.startX.toInt()..hIntTilewiseHitbox.endX.toInt()) {
|
||||||
tiles.add(world!!.getTileFromTerrain(x, y))
|
tiles.add(world!!.getTileFromTerrain(x, y))
|
||||||
@@ -1930,7 +1931,7 @@ open class ActorWithBody : Actor {
|
|||||||
val tileProps = ArrayList<BlockProp?>()
|
val tileProps = ArrayList<BlockProp?>()
|
||||||
|
|
||||||
// offset 1 pixel to the down so that friction would work
|
// offset 1 pixel to the down so that friction would work
|
||||||
val y = hitbox.endY.plus(1.0).div(TILE_SIZE).floorInt()
|
val y = hitbox.endY.plus(1.0).div(TILE_SIZE).floorToInt()
|
||||||
|
|
||||||
for (x in hIntTilewiseHitbox.startX.toInt()..hIntTilewiseHitbox.endX.toInt()) {
|
for (x in hIntTilewiseHitbox.startX.toInt()..hIntTilewiseHitbox.endX.toInt()) {
|
||||||
tileProps.add(BlockCodex[world!!.getTileFromTerrain(x, y)])
|
tileProps.add(BlockCodex[world!!.getTileFromTerrain(x, y)])
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import net.torvald.terrarum.ItemCodex
|
|||||||
import net.torvald.terrarum.Terrarum
|
import net.torvald.terrarum.Terrarum
|
||||||
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
|
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
|
||||||
import net.torvald.terrarum.controller.TerrarumController
|
import net.torvald.terrarum.controller.TerrarumController
|
||||||
import net.torvald.terrarum.floorInt
|
import net.torvald.terrarum.floorToInt
|
||||||
import net.torvald.terrarum.gameactors.AVKey
|
import net.torvald.terrarum.gameactors.AVKey
|
||||||
import net.torvald.terrarum.gameitems.GameItem
|
import net.torvald.terrarum.gameitems.GameItem
|
||||||
import net.torvald.terrarum.gameworld.fmod
|
import net.torvald.terrarum.gameworld.fmod
|
||||||
@@ -42,10 +42,10 @@ class IngameController(val terrarumIngame: TerrarumIngame) : InputAdapter() {
|
|||||||
get() = WorldCamera.y + Gdx.input.y / (terrarumIngame.screenZoom)
|
get() = WorldCamera.y + Gdx.input.y / (terrarumIngame.screenZoom)
|
||||||
/** currently pointing tile coordinate */
|
/** currently pointing tile coordinate */
|
||||||
val mouseTileX: Int
|
val mouseTileX: Int
|
||||||
get() = (mouseX / TILE_SIZE).floorInt()
|
get() = (mouseX / TILE_SIZE).floorToInt()
|
||||||
/** currently pointing tile coordinate */
|
/** currently pointing tile coordinate */
|
||||||
val mouseTileY: Int
|
val mouseTileY: Int
|
||||||
get() = (mouseY / TILE_SIZE).floorInt()
|
get() = (mouseY / TILE_SIZE).floorToInt()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import net.torvald.terrarum.savegame.ByteArray64
|
|||||||
import net.torvald.terrarum.utils.HashArray
|
import net.torvald.terrarum.utils.HashArray
|
||||||
import net.torvald.terrarum.utils.ZipCodedStr
|
import net.torvald.terrarum.utils.ZipCodedStr
|
||||||
import org.dyn4j.geometry.Vector2
|
import org.dyn4j.geometry.Vector2
|
||||||
|
import kotlin.math.min
|
||||||
|
|
||||||
typealias ItemID = String
|
typealias ItemID = String
|
||||||
|
|
||||||
@@ -388,7 +389,7 @@ fun mouseInInteractableRange(actor: ActorWithBody, action: () -> Long): Long {
|
|||||||
val mousePos2 = Vector2(Terrarum.mouseX + INGAME.world.width * TILE_SIZED, Terrarum.mouseY)
|
val mousePos2 = Vector2(Terrarum.mouseX + INGAME.world.width * TILE_SIZED, Terrarum.mouseY)
|
||||||
val mousePos3 = Vector2(Terrarum.mouseX - INGAME.world.width * TILE_SIZED, Terrarum.mouseY)
|
val mousePos3 = Vector2(Terrarum.mouseX - INGAME.world.width * TILE_SIZED, Terrarum.mouseY)
|
||||||
val actorPos = actor.centrePosVector
|
val actorPos = actor.centrePosVector
|
||||||
val dist = minOf(actorPos.distanceSquared(mousePos1), actorPos.distanceSquared(mousePos2), actorPos.distanceSquared(mousePos3))
|
val dist = min(min(actorPos.distanceSquared(mousePos1), actorPos.distanceSquared(mousePos2)), actorPos.distanceSquared(mousePos3))
|
||||||
val distMax = actor.actorValue.getAsDouble(AVKey.REACH)!! * (actor.actorValue.getAsDouble(AVKey.REACHBUFF) ?: 1.0) * actor.scale // perform some error checking here
|
val distMax = actor.actorValue.getAsDouble(AVKey.REACH)!! * (actor.actorValue.getAsDouble(AVKey.REACHBUFF) ?: 1.0) * actor.scale // perform some error checking here
|
||||||
if (dist <= distMax.sqr()) return action() else return -1
|
if (dist <= distMax.sqr()) return action() else return -1
|
||||||
}
|
}
|
||||||
@@ -409,13 +410,13 @@ fun mouseInInteractableRangeTools(actor: ActorWithBody, item: GameItem?, reachMu
|
|||||||
val mousePos2 = Vector2(Terrarum.mouseX + INGAME.world.width * TILE_SIZED, Terrarum.mouseY)
|
val mousePos2 = Vector2(Terrarum.mouseX + INGAME.world.width * TILE_SIZED, Terrarum.mouseY)
|
||||||
val mousePos3 = Vector2(Terrarum.mouseX - INGAME.world.width * TILE_SIZED, Terrarum.mouseY)
|
val mousePos3 = Vector2(Terrarum.mouseX - INGAME.world.width * TILE_SIZED, Terrarum.mouseY)
|
||||||
val actorPos = actor.centrePosVector
|
val actorPos = actor.centrePosVector
|
||||||
val dist = minOf(actorPos.distanceSquared(mousePos1), actorPos.distanceSquared(mousePos2), actorPos.distanceSquared(mousePos3))
|
val dist = min(min(actorPos.distanceSquared(mousePos1), actorPos.distanceSquared(mousePos2)), actorPos.distanceSquared(mousePos3))
|
||||||
|
|
||||||
val reachBonus = (actor.actorValue.getAsDouble(AVKey.REACHBUFF) ?: 1.0) * actor.scale
|
val reachBonus = (actor.actorValue.getAsDouble(AVKey.REACHBUFF) ?: 1.0) * actor.scale
|
||||||
val distMax = actor.actorValue.getAsDouble(AVKey.REACH)!! * reachBonus // perform some error checking here
|
val distMax = actor.actorValue.getAsDouble(AVKey.REACH)!! * reachBonus // perform some error checking here
|
||||||
val toolDistMax = (TILE_SIZED * reachMultiplierInTiles(item?.material?.toolReach ?: Int.MAX_VALUE)) * reachBonus
|
val toolDistMax = (TILE_SIZED * reachMultiplierInTiles(item?.material?.toolReach ?: Int.MAX_VALUE)) * reachBonus
|
||||||
|
|
||||||
if (dist <= minOf(toolDistMax, distMax).sqr()) return action() else return false
|
if (dist <= min(toolDistMax, distMax).sqr()) return action() else return false
|
||||||
}
|
}
|
||||||
//fun IntRange.pickRandom() = HQRNG().nextInt(this.last - this.first + 1) + this.first // count() on 200 million entries? Se on vitun hyvää idea
|
//fun IntRange.pickRandom() = HQRNG().nextInt(this.last - this.first + 1) + this.first // count() on 200 million entries? Se on vitun hyvää idea
|
||||||
//fun IntArray.pickRandom(): Int = this[HQRNG().nextInt(this.size)]
|
//fun IntArray.pickRandom(): Int = this[HQRNG().nextInt(this.size)]
|
||||||
|
|||||||
@@ -46,12 +46,12 @@ open class ParticleBase(renderOrder: Actor.RenderOrder, val despawnUponCollision
|
|||||||
if (velocity.isZero ||
|
if (velocity.isZero ||
|
||||||
// simple stuck check
|
// simple stuck check
|
||||||
BlockCodex[(INGAME.world).getTileFromTerrain(
|
BlockCodex[(INGAME.world).getTileFromTerrain(
|
||||||
hitbox.centeredX.div(TerrarumAppConfiguration.TILE_SIZE).floorInt(),
|
hitbox.centeredX.div(TerrarumAppConfiguration.TILE_SIZE).floorToInt(),
|
||||||
hitbox.startY.div(TerrarumAppConfiguration.TILE_SIZE).floorInt()
|
hitbox.startY.div(TerrarumAppConfiguration.TILE_SIZE).floorToInt()
|
||||||
)].isSolid ||
|
)].isSolid ||
|
||||||
BlockCodex[(INGAME.world).getTileFromTerrain(
|
BlockCodex[(INGAME.world).getTileFromTerrain(
|
||||||
hitbox.centeredX.div(TerrarumAppConfiguration.TILE_SIZE).floorInt(),
|
hitbox.centeredX.div(TerrarumAppConfiguration.TILE_SIZE).floorToInt(),
|
||||||
hitbox.endY.div(TerrarumAppConfiguration.TILE_SIZE).floorInt()
|
hitbox.endY.div(TerrarumAppConfiguration.TILE_SIZE).floorToInt()
|
||||||
)].isSolid) {
|
)].isSolid) {
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
|||||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame.Companion.inUpdateRange
|
import net.torvald.terrarum.modulebasegame.TerrarumIngame.Companion.inUpdateRange
|
||||||
import net.torvald.terrarum.modulebasegame.gameactors.*
|
import net.torvald.terrarum.modulebasegame.gameactors.*
|
||||||
import org.dyn4j.geometry.Vector2
|
import org.dyn4j.geometry.Vector2
|
||||||
|
import kotlin.math.min
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -120,10 +121,10 @@ object WorldSimulator {
|
|||||||
|
|
||||||
// kill grasses surrounded by dirts in cruciform formation
|
// kill grasses surrounded by dirts in cruciform formation
|
||||||
// NOPE this part would not work; environment-depending degrassing must be done by the "grass spread simulator"
|
// NOPE this part would not work; environment-depending degrassing must be done by the "grass spread simulator"
|
||||||
/*val for_y_start = (WorldCamera.y.toFloat() / TILE_SIZE).floorInt()
|
/*val for_y_start = (WorldCamera.y.toFloat() / TILE_SIZE).floorToInt()
|
||||||
val for_y_end = for_y_start + BlocksDrawer.tilesInVertical - 1
|
val for_y_end = for_y_start + BlocksDrawer.tilesInVertical - 1
|
||||||
|
|
||||||
val for_x_start = (WorldCamera.x.toFloat() / TILE_SIZE).floorInt()
|
val for_x_start = (WorldCamera.x.toFloat() / TILE_SIZE).floorToInt()
|
||||||
val for_x_end = for_x_start + BlocksDrawer.tilesInHorizontal - 1
|
val for_x_end = for_x_start + BlocksDrawer.tilesInHorizontal - 1
|
||||||
for (y in for_y_start..for_y_end) {
|
for (y in for_y_start..for_y_end) {
|
||||||
for (x in for_x_start..for_x_end) {
|
for (x in for_x_start..for_x_end) {
|
||||||
@@ -354,7 +355,7 @@ object WorldSimulator {
|
|||||||
if (flow > minFlow) {
|
if (flow > minFlow) {
|
||||||
flow *= 0.5f // leads to smoother flow
|
flow *= 0.5f // leads to smoother flow
|
||||||
}
|
}
|
||||||
flow = flow.coerceIn(0f, minOf(maxSpeed, remainingMass))
|
flow = flow.coerceIn(0f, min(maxSpeed, remainingMass))
|
||||||
|
|
||||||
fluidNewMap[y][x] -= flow
|
fluidNewMap[y][x] -= flow
|
||||||
fluidNewMap[y + 1][x] += flow
|
fluidNewMap[y + 1][x] += flow
|
||||||
@@ -404,7 +405,7 @@ object WorldSimulator {
|
|||||||
if (flow > minFlow) {
|
if (flow > minFlow) {
|
||||||
flow *= 0.5f
|
flow *= 0.5f
|
||||||
}
|
}
|
||||||
flow = flow.coerceIn(0f, minOf(maxSpeed, remainingMass))
|
flow = flow.coerceIn(0f, min(maxSpeed, remainingMass))
|
||||||
|
|
||||||
fluidNewMap[y][x] -= flow
|
fluidNewMap[y][x] -= flow
|
||||||
fluidNewMap[y - 1][x] += flow
|
fluidNewMap[y - 1][x] += flow
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
package net.torvald.terrarum.gameworld
|
package net.torvald.terrarum.gameworld
|
||||||
|
|
||||||
|
import net.torvald.terrarum.modulebasegame.worldgenerator.TWO_PI
|
||||||
|
import kotlin.math.cos
|
||||||
|
import kotlin.math.sin
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Please also see:
|
* Please also see:
|
||||||
@@ -115,11 +119,38 @@ class WorldTime(initTime: Long = 0L) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline val moonPhase: Double
|
inline val moonPhase: Double
|
||||||
get() = (TIME_T.plus(1700000L) % LUNAR_CYCLE).toDouble() / LUNAR_CYCLE
|
get() = (TIME_T.plus(700000L) % LUNAR_CYCLE).toDouble() / LUNAR_CYCLE
|
||||||
|
|
||||||
|
fun getSolarElevationAt(ordinalDay: Int, second: Int): Double {
|
||||||
|
val TIME_T = DAY_LENGTH * ordinalDay + second
|
||||||
|
|
||||||
|
val x = (TIME_T % YEAR_SECONDS).toDouble() / DAY_LENGTH + 15 // decimal days. One full day = 1.0
|
||||||
|
// 51.56 and 23.44 will make yearly min/max elevation to be 75deg
|
||||||
|
val d = -23.44 * cos(TWO_PI * x / YEAR_DAYS)
|
||||||
|
return -51.56 * cos(TWO_PI * x) + d
|
||||||
|
}
|
||||||
|
|
||||||
|
val solarElevationDeg: Double
|
||||||
|
get() {
|
||||||
|
val x = (TIME_T % YEAR_SECONDS).toDouble() / DAY_LENGTH + 15 // decimal days. One full day = 1.0
|
||||||
|
// 51.56 and 23.44 will make yearly min/max elevation to be 75deg
|
||||||
|
val d = -23.44 * cos(TWO_PI * x / YEAR_DAYS)
|
||||||
|
val p = -51.56 * cos(TWO_PI * x)
|
||||||
|
return d + p
|
||||||
|
}
|
||||||
|
val solarElevationRad: Double
|
||||||
|
get() = Math.toRadians(solarElevationDeg)
|
||||||
|
|
||||||
|
val axialTiltDeg: Double
|
||||||
|
get() {
|
||||||
|
val x = (TIME_T % YEAR_SECONDS).toDouble() / DAY_LENGTH + 15 // decimal days. One full day = 1.0
|
||||||
|
return -23.44 * cos(TWO_PI * x / YEAR_DAYS)
|
||||||
|
}
|
||||||
|
|
||||||
@Transient private var realSecAcc: Double = 0.0
|
@Transient private var realSecAcc: Double = 0.0
|
||||||
@Transient private val REAL_SEC_TO_GAME_SECS = 1.0 / GAME_MIN_TO_REAL_SEC // how slow is real-life clock (second-wise) relative to the ingame one
|
@Transient private val REAL_SEC_TO_GAME_SECS = 1.0 / GAME_MIN_TO_REAL_SEC // how slow is real-life clock (second-wise) relative to the ingame one
|
||||||
|
|
||||||
|
// NOTE: ingame calendars (the fixture with GUI) should use symbols AND fullnames; the watch already uses shot daynames
|
||||||
val DAY_NAMES = arrayOf(//daynames are taken from Nynorsk (å -> o)
|
val DAY_NAMES = arrayOf(//daynames are taken from Nynorsk (å -> o)
|
||||||
"Mondag", "Tysdag", "Midtveke" //middle-week
|
"Mondag", "Tysdag", "Midtveke" //middle-week
|
||||||
, "Torsdag", "Fredag", "Laurdag", "Sundag", "Verddag" //From Norsk word 'verd'
|
, "Torsdag", "Fredag", "Laurdag", "Sundag", "Verddag" //From Norsk word 'verd'
|
||||||
@@ -138,19 +169,21 @@ class WorldTime(initTime: Long = 0L) {
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
/** Each day is displayed as 24 hours, but in real-life clock it's 22 mins long */
|
/** Each day is displayed as 24 hours, but in real-life clock it's 22 mins long */
|
||||||
val DAY_LENGTH = 86400 //must be the multiple of 3600
|
const val DAY_LENGTH = 86400 //must be the multiple of 3600
|
||||||
|
|
||||||
val HOUR_SEC: Int = 3600
|
const val HOUR_SEC: Int = 3600
|
||||||
val MINUTE_SEC: Int = 60
|
const val MINUTE_SEC: Int = 60
|
||||||
val HOUR_MIN: Int = 60
|
const val HOUR_MIN: Int = 60
|
||||||
val GAME_MIN_TO_REAL_SEC: Double = 720.0 / 11.0
|
const val GAME_MIN_TO_REAL_SEC: Double = 720.0 / 11.0
|
||||||
val HOURS_PER_DAY = DAY_LENGTH / HOUR_SEC
|
const val HOURS_PER_DAY = DAY_LENGTH / HOUR_SEC
|
||||||
|
|
||||||
val YEAR_DAYS: Int = 120
|
const val YEAR_DAYS: Int = 120
|
||||||
|
|
||||||
val MONTH_LENGTH = 30 // ingame calendar specific
|
const val MONTH_LENGTH = 30 // ingame calendar specific
|
||||||
|
|
||||||
val EPOCH_YEAR = 125
|
const val EPOCH_YEAR = 125
|
||||||
|
|
||||||
|
val YEAR_SECONDS = DAY_LENGTH * YEAR_DAYS
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse a time in the format of "8h30" (hour and minute) or "39882" (second) and return a time of day, in seconds
|
* Parse a time in the format of "8h30" (hour and minute) or "39882" (second) and return a time of day, in seconds
|
||||||
@@ -169,6 +202,7 @@ class WorldTime(initTime: Long = 0L) {
|
|||||||
|
|
||||||
|
|
||||||
val LUNAR_CYCLE: Int = 29 * DAY_LENGTH + 12 * HOUR_SEC + 44 * MINUTE_SEC + 3 // 29 days, 12 hours, 44 minutes, and 3 seconds in-game calendar
|
val LUNAR_CYCLE: Int = 29 * DAY_LENGTH + 12 * HOUR_SEC + 44 * MINUTE_SEC + 3 // 29 days, 12 hours, 44 minutes, and 3 seconds in-game calendar
|
||||||
|
const val DIURNAL_MOTION_LENGTH = 86636f
|
||||||
}
|
}
|
||||||
|
|
||||||
fun update(delta: Float) {
|
fun update(delta: Float) {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import com.badlogic.gdx.graphics.Color
|
|||||||
import com.badlogic.gdx.graphics.g2d.Batch
|
import com.badlogic.gdx.graphics.g2d.Batch
|
||||||
import com.badlogic.gdx.graphics.g2d.BitmapFont
|
import com.badlogic.gdx.graphics.g2d.BitmapFont
|
||||||
import com.badlogic.gdx.graphics.g2d.GlyphLayout
|
import com.badlogic.gdx.graphics.g2d.GlyphLayout
|
||||||
import net.torvald.terrarum.round
|
import net.torvald.terrarum.roundToFloat
|
||||||
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -41,8 +41,8 @@ object TinyAlphNum : BitmapFont() {
|
|||||||
colMain = batch.color.cpy()
|
colMain = batch.color.cpy()
|
||||||
colShadow = colMain.cpy().mul(0.5f, 0.5f, 0.5f, 1f)
|
colShadow = colMain.cpy().mul(0.5f, 0.5f, 0.5f, 1f)
|
||||||
|
|
||||||
val x = x.round()
|
val x = x.roundToFloat()
|
||||||
val y = y.round()
|
val y = y.roundToFloat()
|
||||||
|
|
||||||
var charsPrinted = 0
|
var charsPrinted = 0
|
||||||
text.forEachIndexed { index, c ->
|
text.forEachIndexed { index, c ->
|
||||||
@@ -56,13 +56,13 @@ object TinyAlphNum : BitmapFont() {
|
|||||||
}
|
}
|
||||||
else if (c in 0.toChar()..255.toChar()) {
|
else if (c in 0.toChar()..255.toChar()) {
|
||||||
batch.color = colShadow
|
batch.color = colShadow
|
||||||
batch.draw(fontSheet.get(c.toInt() % 16, c.toInt() / 16), x + charsPrinted * W + 1, y)
|
batch.draw(fontSheet.get(c.code % 16, c.code / 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.code % 16, c.code / 16), x + charsPrinted * W, y + 1)
|
||||||
batch.draw(fontSheet.get(c.toInt() % 16, c.toInt() / 16), x + charsPrinted * W + 1, y + 1)
|
batch.draw(fontSheet.get(c.code % 16, c.code / 16), x + charsPrinted * W + 1, y + 1)
|
||||||
|
|
||||||
|
|
||||||
batch.color = colMain
|
batch.color = colMain
|
||||||
batch.draw(fontSheet.get(c.toInt() % 16, c.toInt() / 16), x + charsPrinted * W, y)
|
batch.draw(fontSheet.get(c.code % 16, c.code / 16), x + charsPrinted * W, y)
|
||||||
|
|
||||||
charsPrinted += 1
|
charsPrinted += 1
|
||||||
}
|
}
|
||||||
@@ -80,8 +80,8 @@ object TinyAlphNum : BitmapFont() {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
private fun isColourCodeHigh(c: Char) = c.toInt() in 0b110110_1111000000..0b110110_1111111111
|
private fun isColourCodeHigh(c: Char) = c.code in 0b110110_1111000000..0b110110_1111111111
|
||||||
private fun isColourCodeLow(c: Char) = c.toInt() in 0b110111_0000000000..0b110111_1111111111
|
private fun isColourCodeLow(c: Char) = c.code in 0b110111_0000000000..0b110111_1111111111
|
||||||
|
|
||||||
private fun getColour(charHigh: Char, charLow: Char): Color { // input: 0x10ARGB, out: RGBA8888
|
private fun getColour(charHigh: Char, charLow: Char): Color { // input: 0x10ARGB, out: RGBA8888
|
||||||
val codePoint = Character.toCodePoint(charHigh, charLow)
|
val codePoint = Character.toCodePoint(charHigh, charLow)
|
||||||
|
|||||||
@@ -55,14 +55,14 @@ class ChunkLoadingLoadScreen(screenToBeLoaded: IngameInstance, private val world
|
|||||||
|
|
||||||
App.batch.inUse { val it = it as FlippingSpriteBatch
|
App.batch.inUse { val it = it as FlippingSpriteBatch
|
||||||
it.color = Color.WHITE
|
it.color = Color.WHITE
|
||||||
val previewX = (drawWidth - previewWidth).div(2f).round()
|
val previewX = (drawWidth - previewWidth).div(2f).roundToFloat()
|
||||||
val previewY = (App.scr.height - previewHeight.times(1.5f)).div(2f).round()
|
val previewY = (App.scr.height - previewHeight.times(1.5f)).div(2f).roundToFloat()
|
||||||
Toolkit.drawBoxBorder(it, previewX.toInt() - 1, previewY.toInt() - 1, previewWidth + 2, previewHeight + 2)
|
Toolkit.drawBoxBorder(it, previewX.toInt() - 1, previewY.toInt() - 1, previewWidth + 2, previewHeight + 2)
|
||||||
it.drawFlipped(previewTexture, previewX, previewY)
|
it.drawFlipped(previewTexture, previewX, previewY)
|
||||||
val text = messages.getHeadElem() ?: ""
|
val text = messages.getHeadElem() ?: ""
|
||||||
App.fontGame.draw(it,
|
App.fontGame.draw(it,
|
||||||
text,
|
text,
|
||||||
(drawWidth - App.fontGame.getWidth(text)).div(2f).round(),
|
(drawWidth - App.fontGame.getWidth(text)).div(2f).roundToFloat(),
|
||||||
previewY + previewHeight + 98 - App.fontGame.lineHeight
|
previewY + previewHeight + 98 - App.fontGame.lineHeight
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -680,7 +680,7 @@ object IngameRenderer : Disposable {
|
|||||||
* Camera will be moved so that (newX, newY) would be sit on the top-left edge.
|
* Camera will be moved so that (newX, newY) would be sit on the top-left edge.
|
||||||
*/
|
*/
|
||||||
private fun setCameraPosition(newX: Float, newY: Float) {
|
private fun setCameraPosition(newX: Float, newY: Float) {
|
||||||
camera.position.set((-newX + App.scr.halfw).round(), (-newY + App.scr.halfh).round(), 0f)
|
camera.position.set((-newX + App.scr.halfw).roundToFloat(), (-newY + App.scr.halfh).roundToFloat(), 0f)
|
||||||
camera.update()
|
camera.update()
|
||||||
batch.projectionMatrix = camera.combined
|
batch.projectionMatrix = camera.combined
|
||||||
}
|
}
|
||||||
@@ -862,27 +862,27 @@ object IngameRenderer : Disposable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun dispose() {
|
override fun dispose() {
|
||||||
try { blurWriteQuad.dispose() } catch (e: UninitializedPropertyAccessException) {}
|
if (::blurWriteQuad.isInitialized) blurWriteQuad.tryDispose()
|
||||||
try { blurWriteQuad2.dispose() } catch (e: UninitializedPropertyAccessException) {}
|
if (::blurWriteQuad2.isInitialized) blurWriteQuad2.tryDispose()
|
||||||
//try { blurWriteQuad4.dispose() } catch (e: UninitializedPropertyAccessException) {}
|
//if (::blurWriteQuad4.isInitialized) blurWriteQuad4.tryDispose()
|
||||||
|
|
||||||
try { fboRGB.dispose() } catch (e: UninitializedPropertyAccessException) {}
|
if (::fboRGB.isInitialized) fboRGB.tryDispose()
|
||||||
try { fboA.dispose() } catch (e: UninitializedPropertyAccessException) {}
|
if (::fboA.isInitialized) fboA.tryDispose()
|
||||||
try { fboRGB_lightMixed.dispose() } catch (e: UninitializedPropertyAccessException) {}
|
if (::fboRGB_lightMixed.isInitialized) fboRGB_lightMixed.tryDispose()
|
||||||
try { fboA_lightMixed.dispose() } catch (e: UninitializedPropertyAccessException) {}
|
if (::fboA_lightMixed.isInitialized) fboA_lightMixed.tryDispose()
|
||||||
try { fboMixedOut.dispose() } catch (e: UninitializedPropertyAccessException) {}
|
if (::fboMixedOut.isInitialized) fboMixedOut.tryDispose()
|
||||||
try { lightmapFbo.dispose() } catch (e: UninitializedPropertyAccessException) {}
|
if (::lightmapFbo.isInitialized) lightmapFbo.tryDispose()
|
||||||
|
|
||||||
try { blurtex0.dispose() } catch (e: GdxRuntimeException) {}
|
blurtex0.tryDispose()
|
||||||
|
|
||||||
try { fboBlurHalf.dispose() } catch (e: UninitializedPropertyAccessException) {}
|
if (::fboBlurHalf.isInitialized) fboBlurHalf.tryDispose()
|
||||||
//try { fboBlurQuarter.dispose() } catch (e: UninitializedPropertyAccessException) {}
|
//if (::fboBlurQuarter.isInitialized) fboBlurQuarter.tryDispose()
|
||||||
|
|
||||||
LightmapRenderer.dispose()
|
LightmapRenderer.dispose()
|
||||||
BlocksDrawer.dispose()
|
BlocksDrawer.dispose()
|
||||||
WeatherMixer.dispose()
|
WeatherMixer.dispose()
|
||||||
|
|
||||||
try { batch.dispose() } catch (e: UninitializedPropertyAccessException) {}
|
if (::batch.isInitialized) batch.tryDispose()
|
||||||
|
|
||||||
|
|
||||||
shaderBlur.dispose()
|
shaderBlur.dispose()
|
||||||
@@ -896,10 +896,7 @@ object IngameRenderer : Disposable {
|
|||||||
shaderForActors.dispose()
|
shaderForActors.dispose()
|
||||||
shaderDemultiply.dispose()
|
shaderDemultiply.dispose()
|
||||||
|
|
||||||
try { fboRGBexport.dispose() }
|
if (::fboRGBexport.isInitialized) fboRGBexport.tryDispose()
|
||||||
catch (e: GdxRuntimeException) {}
|
|
||||||
catch (e: UninitializedPropertyAccessException) {}
|
|
||||||
catch (e: Throwable) { e.printStackTrace(System.out) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun worldCamToRenderPos(): Pair<Float, Float> {
|
private fun worldCamToRenderPos(): Pair<Float, Float> {
|
||||||
|
|||||||
@@ -56,7 +56,10 @@ import net.torvald.terrarum.worlddrawer.WorldCamera
|
|||||||
import net.torvald.unicode.EMDASH
|
import net.torvald.unicode.EMDASH
|
||||||
import net.torvald.util.CircularArray
|
import net.torvald.util.CircularArray
|
||||||
import org.khelekore.prtree.PRTree
|
import org.khelekore.prtree.PRTree
|
||||||
|
import java.io.File
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import java.util.logging.Level
|
||||||
|
import kotlin.math.min
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
|
|
||||||
@@ -93,7 +96,7 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
companion object {
|
companion object {
|
||||||
/** Sets camera position so that (0,0) would be top-left of the screen, (width, height) be bottom-right. */
|
/** Sets camera position so that (0,0) would be top-left of the screen, (width, height) be bottom-right. */
|
||||||
fun setCameraPosition(batch: SpriteBatch, camera: Camera, newX: Float, newY: Float) {
|
fun setCameraPosition(batch: SpriteBatch, camera: Camera, newX: Float, newY: Float) {
|
||||||
camera.position.set((-newX + App.scr.halfw).round(), (-newY + App.scr.halfh).round(), 0f)
|
camera.position.set((-newX + App.scr.halfw).roundToFloat(), (-newY + App.scr.halfh).roundToFloat(), 0f)
|
||||||
camera.update()
|
camera.update()
|
||||||
batch.projectionMatrix = camera.combined
|
batch.projectionMatrix = camera.combined
|
||||||
}
|
}
|
||||||
@@ -109,20 +112,20 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
val ACTOR_UPDATE_RANGE = 4096
|
val ACTOR_UPDATE_RANGE = 4096
|
||||||
|
|
||||||
fun distToActorSqr(world: GameWorld, a: ActorWithBody, p: ActorWithBody) =
|
fun distToActorSqr(world: GameWorld, a: ActorWithBody, p: ActorWithBody) =
|
||||||
minOf(// take min of normal position and wrapped (x < 0) position
|
min(// take min of normal position and wrapped (x < 0) position
|
||||||
(a.hitbox.centeredX - p.hitbox.centeredX).sqr() +
|
min((a.hitbox.centeredX - p.hitbox.centeredX).sqr() +
|
||||||
(a.hitbox.centeredY - p.hitbox.centeredY).sqr(),
|
(a.hitbox.centeredY - p.hitbox.centeredY).sqr(),
|
||||||
((a.hitbox.centeredX + world.width * TILE_SIZE) - p.hitbox.centeredX).sqr() +
|
((a.hitbox.centeredX + world.width * TILE_SIZE) - p.hitbox.centeredX).sqr() +
|
||||||
(a.hitbox.centeredY - p.hitbox.centeredY).sqr(),
|
(a.hitbox.centeredY - p.hitbox.centeredY).sqr()),
|
||||||
((a.hitbox.centeredX - world.width * TILE_SIZE) - p.hitbox.centeredX).sqr() +
|
((a.hitbox.centeredX - world.width * TILE_SIZE) - p.hitbox.centeredX).sqr() +
|
||||||
(a.hitbox.centeredY - p.hitbox.centeredY).sqr()
|
(a.hitbox.centeredY - p.hitbox.centeredY).sqr()
|
||||||
)
|
)
|
||||||
fun distToCameraSqr(world: GameWorld, a: ActorWithBody) =
|
fun distToCameraSqr(world: GameWorld, a: ActorWithBody) =
|
||||||
minOf(
|
min(
|
||||||
(a.hitbox.centeredX - WorldCamera.xCentre).sqr() +
|
min((a.hitbox.centeredX - WorldCamera.xCentre).sqr() +
|
||||||
(a.hitbox.centeredY - WorldCamera.yCentre).sqr(),
|
(a.hitbox.centeredY - WorldCamera.yCentre).sqr(),
|
||||||
((a.hitbox.centeredX + world.width * TILE_SIZE) - WorldCamera.xCentre).sqr() +
|
((a.hitbox.centeredX + world.width * TILE_SIZE) - WorldCamera.xCentre).sqr() +
|
||||||
(a.hitbox.centeredY - WorldCamera.yCentre).sqr(),
|
(a.hitbox.centeredY - WorldCamera.yCentre).sqr()),
|
||||||
((a.hitbox.centeredX - world.width * TILE_SIZE) - WorldCamera.xCentre).sqr() +
|
((a.hitbox.centeredX - world.width * TILE_SIZE) - WorldCamera.xCentre).sqr() +
|
||||||
(a.hitbox.centeredY - WorldCamera.yCentre).sqr()
|
(a.hitbox.centeredY - WorldCamera.yCentre).sqr()
|
||||||
)
|
)
|
||||||
@@ -399,15 +402,11 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
|
|
||||||
worldDisk = VDUtil.createNewDisk(
|
worldDisk = VDUtil.createNewDisk(
|
||||||
1L shl 60,
|
1L shl 60,
|
||||||
savegameNickname,
|
worldName,
|
||||||
Common.CHARSET
|
Common.CHARSET
|
||||||
)
|
)
|
||||||
|
|
||||||
playerDisk = VDUtil.createNewDisk(
|
playerDisk = VDUtil.readDiskArchive(App.savegamePlayers[actorGamer.uuid]!!.loadable().diskFile, Level.INFO)
|
||||||
1L shl 60,
|
|
||||||
actorGamer.actorValue.getAsString(AVKey.NAME) ?: "",
|
|
||||||
Common.CHARSET
|
|
||||||
)
|
|
||||||
|
|
||||||
// go to spawn position
|
// go to spawn position
|
||||||
printdbg(this, "World Spawn position: (${world.spawnX}, ${world.spawnY})")
|
printdbg(this, "World Spawn position: (${world.spawnX}, ${world.spawnY})")
|
||||||
@@ -434,6 +433,9 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
|
|
||||||
makeSavegameBackupCopy(getWorldSaveFiledesc(worldSavefileName)) // don't put it on the postInit() or render(); must be called using callback
|
makeSavegameBackupCopy(getWorldSaveFiledesc(worldSavefileName)) // don't put it on the postInit() or render(); must be called using callback
|
||||||
uiAutosaveNotifier.setAsClose()
|
uiAutosaveNotifier.setAsClose()
|
||||||
|
|
||||||
|
App.savegameWorlds[world.worldIndex] = SavegameCollection.collectFromBaseFilename(File(worldsDir), worldSavefileName)
|
||||||
|
App.savegameWorldsName[world.worldIndex] = worldName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -475,7 +477,7 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
|
|
||||||
historicalFigureIDBucket = ArrayList<Int>()
|
historicalFigureIDBucket = ArrayList<Int>()
|
||||||
|
|
||||||
savegameNickname = worldParams.savegameName
|
worldName = worldParams.savegameName
|
||||||
|
|
||||||
|
|
||||||
world.worldCreator = UUID.fromString(player.uuid.toString())
|
world.worldCreator = UUID.fromString(player.uuid.toString())
|
||||||
@@ -488,6 +490,8 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
forceAddActor(player)
|
forceAddActor(player)
|
||||||
|
|
||||||
WeatherMixer.internalReset()
|
WeatherMixer.internalReset()
|
||||||
|
|
||||||
|
UILoadGovernor.worldUUID = world.worldIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
KeyToggler.forceSet(Input.Keys.Q, false)
|
KeyToggler.forceSet(Input.Keys.Q, false)
|
||||||
@@ -1032,10 +1036,10 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
} }
|
} }
|
||||||
|
|
||||||
private fun fillUpWiresBuffer() {
|
private fun fillUpWiresBuffer() {
|
||||||
val for_y_start = (WorldCamera.y.toFloat() / TILE_SIZE).floorInt() - LIGHTMAP_OVERRENDER
|
val for_y_start = (WorldCamera.y.toFloat() / TILE_SIZE).floorToInt() - LIGHTMAP_OVERRENDER
|
||||||
val for_y_end = for_y_start + BlocksDrawer.tilesInVertical + 2*LIGHTMAP_OVERRENDER
|
val for_y_end = for_y_start + BlocksDrawer.tilesInVertical + 2*LIGHTMAP_OVERRENDER
|
||||||
|
|
||||||
val for_x_start = (WorldCamera.x.toFloat() / TILE_SIZE).floorInt() - LIGHTMAP_OVERRENDER
|
val for_x_start = (WorldCamera.x.toFloat() / TILE_SIZE).floorToInt() - LIGHTMAP_OVERRENDER
|
||||||
val for_x_end = for_x_start + BlocksDrawer.tilesInHorizontal + 2*LIGHTMAP_OVERRENDER
|
val for_x_end = for_x_start + BlocksDrawer.tilesInHorizontal + 2*LIGHTMAP_OVERRENDER
|
||||||
|
|
||||||
var wiringCounter = 0
|
var wiringCounter = 0
|
||||||
@@ -1418,7 +1422,7 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
// }
|
// }
|
||||||
// else, punch a block
|
// else, punch a block
|
||||||
else if (canAttackOrDig) {
|
else if (canAttackOrDig) {
|
||||||
val punchBlockSize = punchSize.div(TILE_SIZED).floorInt()
|
val punchBlockSize = punchSize.div(TILE_SIZED).floorToInt()
|
||||||
if (punchBlockSize > 0) {
|
if (punchBlockSize > 0) {
|
||||||
PickaxeCore.startPrimaryUse(actor, delta, null, Terrarum.mouseTileX, Terrarum.mouseTileY, 1.0 / punchBlockSize, punchBlockSize, punchBlockSize)
|
PickaxeCore.startPrimaryUse(actor, delta, null, Terrarum.mouseTileX, Terrarum.mouseTileY, 1.0 / punchBlockSize, punchBlockSize, punchBlockSize)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import net.torvald.terrarum.gameworld.GameWorld
|
|||||||
import net.torvald.terrarum.gameworld.WorldTime
|
import net.torvald.terrarum.gameworld.WorldTime
|
||||||
import net.torvald.terrarum.gameworld.fmod
|
import net.torvald.terrarum.gameworld.fmod
|
||||||
import net.torvald.terrarum.langpack.Lang
|
import net.torvald.terrarum.langpack.Lang
|
||||||
|
import net.torvald.terrarum.clut.Skybox
|
||||||
import net.torvald.terrarum.modulebasegame.ui.UILoadGovernor
|
import net.torvald.terrarum.modulebasegame.ui.UILoadGovernor
|
||||||
import net.torvald.terrarum.modulebasegame.ui.UIRemoCon
|
import net.torvald.terrarum.modulebasegame.ui.UIRemoCon
|
||||||
import net.torvald.terrarum.modulebasegame.ui.UITitleRemoConYaml
|
import net.torvald.terrarum.modulebasegame.ui.UITitleRemoConYaml
|
||||||
@@ -74,7 +75,7 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
val ww = TILE_SIZEF * demoWorld.width
|
val ww = TILE_SIZEF * demoWorld.width
|
||||||
val x = px % ww
|
val x = px % ww
|
||||||
|
|
||||||
val indexThis = ((x / ww * cameraNodes.size).floorInt())
|
val indexThis = ((x / ww * cameraNodes.size).floorToInt())
|
||||||
val xwstart: Double = indexThis.toDouble() / cameraNodes.size * ww
|
val xwstart: Double = indexThis.toDouble() / cameraNodes.size * ww
|
||||||
val xwend: Double = ((indexThis + 1).toDouble() / cameraNodes.size) * ww
|
val xwend: Double = ((indexThis + 1).toDouble() / cameraNodes.size) * ww
|
||||||
val xw: Double = xwend - xwstart
|
val xw: Double = xwend - xwstart
|
||||||
@@ -175,13 +176,13 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// set time to summer
|
// set initial time to summer
|
||||||
demoWorld.worldTime.addTime(WorldTime.DAY_LENGTH * 32)
|
demoWorld.worldTime.addTime(WorldTime.DAY_LENGTH * 32)
|
||||||
|
|
||||||
// construct camera nodes
|
// construct camera nodes
|
||||||
val nodeCount = demoWorld.width / cameraNodeWidth
|
val nodeCount = demoWorld.width / cameraNodeWidth
|
||||||
cameraNodes = kotlin.FloatArray(nodeCount) {
|
cameraNodes = kotlin.FloatArray(nodeCount) {
|
||||||
val tileXPos = (demoWorld.width.toFloat() * it / nodeCount).floorInt()
|
val tileXPos = (demoWorld.width.toFloat() * it / nodeCount).floorToInt()
|
||||||
var travelDownCounter = 0
|
var travelDownCounter = 0
|
||||||
while (travelDownCounter < demoWorld.height &&
|
while (travelDownCounter < demoWorld.height &&
|
||||||
!BlockCodex[demoWorld.getTileFromTerrain(tileXPos, travelDownCounter)].isSolid
|
!BlockCodex[demoWorld.getTileFromTerrain(tileXPos, travelDownCounter)].isSolid
|
||||||
@@ -193,13 +194,14 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
}
|
}
|
||||||
// apply gaussian blur to the camera nodes
|
// apply gaussian blur to the camera nodes
|
||||||
for (i in cameraNodes.indices) {
|
for (i in cameraNodes.indices) {
|
||||||
val offM2 = cameraNodes[(i-2) fmod cameraNodes.size] * 1f
|
// val offM2 = cameraNodes[(i-2) fmod cameraNodes.size] * 1f
|
||||||
val offM1 = cameraNodes[(i-1) fmod cameraNodes.size] * 4f
|
val offM1 = cameraNodes[(i-1) fmod cameraNodes.size] * 1f
|
||||||
val off0 = cameraNodes[i] * 6f
|
val off0 = cameraNodes[i] * 2f
|
||||||
val off1 = cameraNodes[(i+1) fmod cameraNodes.size] * 4f
|
val off1 = cameraNodes[(i+1) fmod cameraNodes.size] * 1f
|
||||||
val off2 = cameraNodes[(i+2) fmod cameraNodes.size] * 1f
|
// val off2 = cameraNodes[(i+2) fmod cameraNodes.size] * 1f
|
||||||
|
|
||||||
cameraNodes[i] = (offM2 + offM1 + off0 + off1 + off2) / 16f
|
// cameraNodes[i] = (offM2 + offM1 + off0 + off1 + off2) / 16f
|
||||||
|
cameraNodes[i] = (offM1 + off0 + off1) / 4f
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -239,6 +241,8 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
uiContainer.add(uiRemoCon)
|
uiContainer.add(uiRemoCon)
|
||||||
|
|
||||||
CommandDict // invoke
|
CommandDict // invoke
|
||||||
|
Skybox.loadlut() // invoke
|
||||||
|
// Skybox.initiate() // invoke the lengthy calculation
|
||||||
// TODO add console here
|
// TODO add console here
|
||||||
|
|
||||||
|
|
||||||
@@ -283,9 +287,9 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
private val updateScreen = { delta: Float ->
|
private val updateScreen = { delta: Float ->
|
||||||
// TODO: desynched weather and time-of-day change
|
// TODO: desynched weather and time-of-day change
|
||||||
|
|
||||||
val forcedTime = 39693
|
val forcedTime = 32880 // 9h08m
|
||||||
// demoWorld.globalLight = WeatherMixer.globalLightNow
|
demoWorld.globalLight = WeatherMixer.globalLightNow
|
||||||
demoWorld.globalLight = WeatherMixer.getGlobalLightOfTime(demoWorld, forcedTime)
|
// demoWorld.globalLight = WeatherMixer.getGlobalLightOfTimeOfNoon()
|
||||||
demoWorld.updateWorldTime(delta)
|
demoWorld.updateWorldTime(delta)
|
||||||
// WeatherMixer.update(delta, cameraPlayer, demoWorld)
|
// WeatherMixer.update(delta, cameraPlayer, demoWorld)
|
||||||
WeatherMixer.forceTimeAt = forcedTime
|
WeatherMixer.forceTimeAt = forcedTime
|
||||||
|
|||||||
@@ -70,14 +70,14 @@ class WorldgenLoadScreen(screenToBeLoaded: IngameInstance, private val worldwidt
|
|||||||
|
|
||||||
App.batch.inUse { val it = it as FlippingSpriteBatch
|
App.batch.inUse { val it = it as FlippingSpriteBatch
|
||||||
it.color = Color.WHITE
|
it.color = Color.WHITE
|
||||||
val previewX = (drawWidth - previewWidth).div(2f).round()
|
val previewX = (drawWidth - previewWidth).div(2f).roundToFloat()
|
||||||
val previewY = (App.scr.height - previewHeight.times(1.5f)).div(2f).round()
|
val previewY = (App.scr.height - previewHeight.times(1.5f)).div(2f).roundToFloat()
|
||||||
Toolkit.drawBoxBorder(it, previewX.toInt()-1, previewY.toInt()-1, previewWidth+2, previewHeight+2)
|
Toolkit.drawBoxBorder(it, previewX.toInt()-1, previewY.toInt()-1, previewWidth+2, previewHeight+2)
|
||||||
it.drawFlipped(previewTexture, previewX, previewY)
|
it.drawFlipped(previewTexture, previewX, previewY)
|
||||||
val text = messages.getHeadElem() ?: ""
|
val text = messages.getHeadElem() ?: ""
|
||||||
App.fontGame.draw(it,
|
App.fontGame.draw(it,
|
||||||
text,
|
text,
|
||||||
(drawWidth - App.fontGame.getWidth(text)).div(2f).round(),
|
(drawWidth - App.fontGame.getWidth(text)).div(2f).roundToFloat(),
|
||||||
previewY + previewHeight + 98 - App.fontGame.lineHeight
|
previewY + previewHeight + 98 - App.fontGame.lineHeight
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
48
src/net/torvald/terrarum/modulebasegame/console/SetSol.kt
Normal file
48
src/net/torvald/terrarum/modulebasegame/console/SetSol.kt
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
package net.torvald.terrarum.modulebasegame.console
|
||||||
|
|
||||||
|
import net.torvald.reflection.extortField
|
||||||
|
import net.torvald.terrarum.INGAME
|
||||||
|
import net.torvald.terrarum.console.ConsoleCommand
|
||||||
|
import net.torvald.terrarum.console.Echo
|
||||||
|
import net.torvald.terrarum.gameactors.ActorWithBody
|
||||||
|
import net.torvald.terrarum.weather.WeatherMixer
|
||||||
|
import net.torvald.terrarum.worlddrawer.LightmapRenderer
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2023-07-25.
|
||||||
|
*/
|
||||||
|
internal object SetSol : ConsoleCommand {
|
||||||
|
override fun execute(args: Array<String>) {
|
||||||
|
if (args.size == 2) {
|
||||||
|
if (args[1].trim().lowercase() == "none") {
|
||||||
|
WeatherMixer.forceSolarElev = null
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
try {
|
||||||
|
val solarAngle = args[1].toDouble().coerceIn(-75.0..75.0)
|
||||||
|
WeatherMixer.forceSolarElev = solarAngle
|
||||||
|
LightmapRenderer.recalculate(
|
||||||
|
INGAME.extortField<ArrayList<ActorWithBody>>("visibleActorsRenderBehind")!! +
|
||||||
|
INGAME.extortField<ArrayList<ActorWithBody>>("visibleActorsRenderMiddle")!! +
|
||||||
|
INGAME.extortField<ArrayList<ActorWithBody>>("visibleActorsRenderMidTop")!! +
|
||||||
|
INGAME.extortField<ArrayList<ActorWithBody>>("visibleActorsRenderFront")!! +
|
||||||
|
INGAME.extortField<ArrayList<ActorWithBody>>("visibleActorsRenderOverlay")!!
|
||||||
|
)
|
||||||
|
}
|
||||||
|
catch (e: NumberFormatException) {
|
||||||
|
Echo("Wrong number input.")
|
||||||
|
}
|
||||||
|
catch (e1: IllegalArgumentException) {
|
||||||
|
Echo("Range: -75.0-75.0")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printUsage()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun printUsage() {
|
||||||
|
Echo("usage: setsol <-75.0..75.0 or 'none'>")
|
||||||
|
}
|
||||||
|
}
|
||||||
37
src/net/torvald/terrarum/modulebasegame/console/SetTurb.kt
Normal file
37
src/net/torvald/terrarum/modulebasegame/console/SetTurb.kt
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
package net.torvald.terrarum.modulebasegame.console
|
||||||
|
|
||||||
|
import net.torvald.terrarum.console.ConsoleCommand
|
||||||
|
import net.torvald.terrarum.console.Echo
|
||||||
|
import net.torvald.terrarum.weather.WeatherMixer
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2023-07-25.
|
||||||
|
*/
|
||||||
|
object SetTurb : ConsoleCommand {
|
||||||
|
override fun execute(args: Array<String>) {
|
||||||
|
if (args.size == 2) {
|
||||||
|
if (args[1].trim().lowercase() == "none") {
|
||||||
|
WeatherMixer.forceTurbidity = null
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
try {
|
||||||
|
val turbidity = args[1].toDouble().coerceIn(1.0..10.0)
|
||||||
|
WeatherMixer.forceTurbidity = turbidity
|
||||||
|
}
|
||||||
|
catch (e: NumberFormatException) {
|
||||||
|
Echo("Wrong number input.")
|
||||||
|
}
|
||||||
|
catch (e1: IllegalArgumentException) {
|
||||||
|
Echo("Range: 1.0-10.0")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printUsage()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun printUsage() {
|
||||||
|
Echo("usage: setturb <1.0..10.0 or 'none'>")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -292,8 +292,8 @@ open class ActorHumanoid : ActorWithBody, Controllable, Pocketed, Factionable, L
|
|||||||
val occupyingTileHasPlatform = bodyTiles.filterNotNull().any { it.isPlatform }
|
val occupyingTileHasPlatform = bodyTiles.filterNotNull().any { it.isPlatform }
|
||||||
val feetTileHasPlatform = feetTiles.filterNotNull().any { it.isPlatform }
|
val feetTileHasPlatform = feetTiles.filterNotNull().any { it.isPlatform }
|
||||||
val feetTileIsAllPlatform = feetTiles.filterNotNull().all { it.isPlatform }
|
val feetTileIsAllPlatform = feetTiles.filterNotNull().all { it.isPlatform }
|
||||||
if (isDownDown && feetTileIsAllPlatform && (controllerV?.y ?: 0.0) >= 0.0 ||
|
if (isDownDown && feetTileIsAllPlatform && (controllerV?.y ?: 0.0) >= 0.0) {// ||
|
||||||
occupyingTileHasPlatform && !feetTileHasPlatform) { // FIXME this does not account for reverse gravity
|
// occupyingTileHasPlatform && !feetTileHasPlatform) { // FIXME commenting this out enables platform-ladder but falldown gets slowed down if the body passes thru the platform but I think this behav might be beneficial for player?
|
||||||
downDownVirtually = true
|
downDownVirtually = true
|
||||||
}
|
}
|
||||||
if (downDownVirtually && !occupyingTileHasPlatform && !feetTileIsAllPlatform) {
|
if (downDownVirtually && !occupyingTileHasPlatform && !feetTileIsAllPlatform) {
|
||||||
@@ -545,7 +545,7 @@ open class ActorHumanoid : ActorWithBody, Controllable, Pocketed, Factionable, L
|
|||||||
|
|
||||||
if (hasPlatformOnTheFeet) {
|
if (hasPlatformOnTheFeet) {
|
||||||
// equation copied verbatim from the ActorWthBody.forEachFeetTile
|
// equation copied verbatim from the ActorWthBody.forEachFeetTile
|
||||||
val y = hitbox.endY.plus(1.0).div(TerrarumAppConfiguration.TILE_SIZE).floorInt()
|
val y = hitbox.endY.plus(1.0).div(TerrarumAppConfiguration.TILE_SIZE).floorToInt()
|
||||||
var wxStart = hIntTilewiseHitbox.startX.toInt()
|
var wxStart = hIntTilewiseHitbox.startX.toInt()
|
||||||
var wxEnd = wxStart
|
var wxEnd = wxStart
|
||||||
// scan to the left
|
// scan to the left
|
||||||
|
|||||||
@@ -69,8 +69,8 @@ internal class FixtureTapestry : FixtureBase {
|
|||||||
Pixmap(ModMgr.getGdxFilesFromEveryMod("tapestries/common/canvas.tga").last().second)
|
Pixmap(ModMgr.getGdxFilesFromEveryMod("tapestries/common/canvas.tga").last().second)
|
||||||
} as Pixmap
|
} as Pixmap
|
||||||
|
|
||||||
tilewiseHitboxWidth = pixmap.width.div(TILE_SIZEF).ceilInt()
|
tilewiseHitboxWidth = pixmap.width.div(TILE_SIZEF).ceilToInt()
|
||||||
tilewiseHitboxHeight = pixmap.height.div(TILE_SIZEF).ceilInt()
|
tilewiseHitboxHeight = pixmap.height.div(TILE_SIZEF).ceilToInt()
|
||||||
|
|
||||||
// blend canvas texture
|
// blend canvas texture
|
||||||
for (y in 0 until pixmap.height) { for (x in 0 until pixmap.width) {
|
for (y in 0 until pixmap.height) { for (x in 0 until pixmap.width) {
|
||||||
|
|||||||
@@ -77,11 +77,11 @@ class FixtureWorldPortal : Electric {
|
|||||||
// load existing
|
// load existing
|
||||||
val jobAfterSave: () -> Unit
|
val jobAfterSave: () -> Unit
|
||||||
if (it.worldDiskToLoad != null) {
|
if (it.worldDiskToLoad != null) {
|
||||||
UILoadGovernor.worldDisk = it.worldDiskToLoad
|
|
||||||
UILoadGovernor.playerDisk = App.savegamePlayers[player.uuid]!!.files[0]
|
|
||||||
jobAfterSave = {
|
jobAfterSave = {
|
||||||
UILoadGovernor.playerDisk!!.rebuild()
|
LoadSavegame(
|
||||||
LoadSavegame(UILoadGovernor.playerDisk!!, UILoadGovernor.worldDisk!!)
|
App.savegamePlayers[player.uuid]!!.files[0],
|
||||||
|
it.worldDiskToLoad
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// create new
|
// create new
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
package net.torvald.terrarum.modulebasegame.gameactors.physicssolver
|
package net.torvald.terrarum.modulebasegame.gameactors.physicssolver
|
||||||
|
|
||||||
import net.torvald.terrarum.Terrarum
|
import net.torvald.terrarum.Terrarum
|
||||||
|
import net.torvald.terrarum.abs
|
||||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||||
import net.torvald.terrarum.gameactors.ActorWithBody
|
import net.torvald.terrarum.gameactors.ActorWithBody
|
||||||
|
import net.torvald.terrarum.sqr
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -202,9 +204,6 @@ object CollisionSolver {
|
|||||||
return (t_ax.sqr() + t_ay.sqr()) < actor_dist_t_sqr
|
return (t_ax.sqr() + t_ay.sqr()) < actor_dist_t_sqr
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Double.abs() = if (this < 0) -this else this
|
|
||||||
fun Double.sqr() = this * this
|
|
||||||
|
|
||||||
data class CollisionMarkings(
|
data class CollisionMarkings(
|
||||||
val pos: Double,
|
val pos: Double,
|
||||||
val kind: Int,
|
val kind: Int,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import net.torvald.random.HQRNG
|
|||||||
import net.torvald.terrarum.gameitems.GameItem
|
import net.torvald.terrarum.gameitems.GameItem
|
||||||
import net.torvald.terrarum.gameitems.ItemID
|
import net.torvald.terrarum.gameitems.ItemID
|
||||||
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
|
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
|
||||||
|
import kotlin.math.max
|
||||||
import kotlin.math.pow
|
import kotlin.math.pow
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -21,7 +22,7 @@ object WeaponMeleeCore {
|
|||||||
private fun getAttackMomentum(weapon: WeaponMeleeBase, actor: ActorHumanoid) =
|
private fun getAttackMomentum(weapon: WeaponMeleeBase, actor: ActorHumanoid) =
|
||||||
weapon.mass * weapon.material.density * weapon.velocityMod * actor.scale.pow(SQRT2) // TODO multiply racial strength from RaceCodex
|
weapon.mass * weapon.material.density * weapon.velocityMod * actor.scale.pow(SQRT2) // TODO multiply racial strength from RaceCodex
|
||||||
fun getAttackPower(weapon: WeaponMeleeBase, actor: ActorHumanoid, actee: ActorHumanoid) =
|
fun getAttackPower(weapon: WeaponMeleeBase, actor: ActorHumanoid, actee: ActorHumanoid) =
|
||||||
getAttackMomentum(weapon, actor) * randomise() * maxOf(1.0, (actee.hitbox.endY - actor.hitbox.startY) / actee.hitbox.height)
|
getAttackMomentum(weapon, actor) * randomise() * max(1.0, (actee.hitbox.endY - actor.hitbox.startY) / actee.hitbox.height)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package net.torvald.terrarum.modulebasegame.magiccontroller
|
|||||||
|
|
||||||
import net.torvald.terrarum.gameactors.AVKey
|
import net.torvald.terrarum.gameactors.AVKey
|
||||||
import net.torvald.terrarum.gameactors.Actor
|
import net.torvald.terrarum.gameactors.Actor
|
||||||
|
import kotlin.math.min
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "Data Type" describing magical force
|
* "Data Type" describing magical force
|
||||||
@@ -33,13 +34,13 @@ class TheMagicLanguage(vm: TheMagicMachine) {
|
|||||||
if (power >= 0) {
|
if (power >= 0) {
|
||||||
// pour out positive power without inversion; result is positive power
|
// pour out positive power without inversion; result is positive power
|
||||||
if (value >= 0) {
|
if (value >= 0) {
|
||||||
val value = minOf(power, value)
|
val value = min(power, value)
|
||||||
other.pourIn(value)
|
other.pourIn(value)
|
||||||
power -= value
|
power -= value
|
||||||
}
|
}
|
||||||
// pour out positive power with inversion; result is negative power
|
// pour out positive power with inversion; result is negative power
|
||||||
else {
|
else {
|
||||||
val value = minOf(-power, value)
|
val value = min(-power, value)
|
||||||
other.pourIn(value)
|
other.pourIn(value)
|
||||||
power += value
|
power += value
|
||||||
}
|
}
|
||||||
@@ -47,12 +48,12 @@ class TheMagicLanguage(vm: TheMagicMachine) {
|
|||||||
else {
|
else {
|
||||||
// pour out negative power without inversion; result is negative power
|
// pour out negative power without inversion; result is negative power
|
||||||
if (value < 0) {
|
if (value < 0) {
|
||||||
val value = minOf(power, value)
|
val value = min(power, value)
|
||||||
other.pourIn(-value)
|
other.pourIn(-value)
|
||||||
}
|
}
|
||||||
// pour out negative power with inversion; result is positive power
|
// pour out negative power with inversion; result is positive power
|
||||||
else {
|
else {
|
||||||
val value = minOf(-power, value)
|
val value = min(-power, value)
|
||||||
other.pourIn(-value)
|
other.pourIn(-value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user