219 Commits

Author SHA1 Message Date
Kolyah35
7418263193 .h -> .hpp everything 2026-03-28 01:08:50 +03:00
Kolyah35
7d3257669a pragma once everywhere 2026-03-28 00:00:19 +03:00
Kolyah35
a45c01d013 server compilable 2026-03-26 03:55:28 +03:00
Kolyah35
cbd81b47ce ADD: EpikIzCool to credits 2026-03-24 17:32:52 +03:00
Kolyah35
c146791845 Merge pull request 'Fix Whool and block variations n slabs n stuff' (#13) from EpikIzCool/minecraft-pe-0.6.1:main into main
Reviewed-on: https://192.168.0.2:3000/Kolyah35/minecraft-pe-0.6.1/pulls/13
2026-03-24 16:31:46 +02:00
EpikIzCool
a7c75d2ad2 Touch thingie 2026-03-24 00:29:52 +02:00
EpikIzCool
468ae4a211 Whool Fix part 1 2026-03-24 00:24:16 +02:00
mschiller890
9405e8daad FIXED: Scrolling with mouse wheel improved 2026-03-22 18:38:14 +01:00
mschiller890
bef09a3305 FIXED: sprinting now works when flying 2026-03-22 14:51:22 +01:00
Kolyah35
82f827af29 Merge remote-tracking branch 'refs/remotes/origin/main' 2026-03-22 02:12:46 +03:00
Kolyah35
4f8b18b735 FIX: Now we're using useTouchsceen() right way!!!! 2026-03-22 02:12:04 +03:00
InviseDivine
2acb57d051 revert all sht 2026-03-21 19:19:07 +02:00
InviseDivine
5251085752 i broke all 2026-03-21 19:09:11 +02:00
InviseDivine
a16f76f2b6 idk??? 2026-03-21 19:05:00 +02:00
InviseDivine
b088f39e52 emm 2026-03-21 18:54:51 +02:00
InviseDivine
13c624e07e hmmmmmmmmmm 2026-03-21 18:54:04 +02:00
InviseDivine
2bfa8f11f1 hmm 2026-03-21 18:39:08 +02:00
InviseDivine
98a05e5aa3 FIX: Keyboard on android 2026-03-21 18:25:42 +02:00
InviseDivine
3f6d9cdcb8 FIX: Armor display 2026-03-21 18:10:46 +02:00
InviseDivine
39186069cf Merge branch 'main' of https://gitea.sffempire.ru/Kolyah35/minecraft-pe-0.6.1 2026-03-21 16:22:50 +02:00
InviseDivine
b94c16b22a FIX: Bow release 2026-03-21 16:22:50 +02:00
Kolyah35
91ce365a26 Merge remote-tracking branch 'refs/remotes/origin/main' 2026-03-21 17:20:18 +03:00
Kolyah35
f114536463 FIX: improve web port 2026-03-21 17:19:46 +03:00
InviseDivine
6e0615c0bc FEAT: Auto jump in settings (again) 2026-03-21 16:03:51 +02:00
InviseDivine
fd3ee23e4e Merge branch 'main' of https://gitea.sffempire.ru/Kolyah35/minecraft-pe-0.6.1 2026-03-21 15:44:06 +02:00
InviseDivine
e9766ed2a1 FEAT: Option button in PauseScreen 2026-03-21 15:44:05 +02:00
Kolyah35
298451c290 USE_LIBPNG when compile web 2026-03-21 15:28:50 +03:00
Kolyah35
668fc9d16f oh i forgot data 2026-03-21 15:25:18 +03:00
Kolyah35
5717aeab24 ADD: Web action 2026-03-21 15:23:37 +03:00
Kolyah35
9af1496b9d FIX: windows CI build 2026-03-21 15:04:50 +03:00
InviseDivine
6bfae5a14e Merge branch 'main' of https://gitea.sffempire.ru/Kolyah35/minecraft-pe-0.6.1 2026-03-21 13:43:29 +02:00
InviseDivine
4034cf243d FIX: glfw crash when closing the game 2026-03-21 13:43:28 +02:00
Kolyah35
b6e7414f04 Merge pull request 'fix msvc build & mingw build' (#10) from evildebugger/minecraft-pe-0.6.1:main into main
Reviewed-on: https://192.168.0.2:3000/Kolyah35/minecraft-pe-0.6.1/pulls/10
2026-03-21 12:48:51 +02:00
66hh
83f3284827 fix msvc build & mingw build
1. Include unified header files using lowercase filenames
2. Change special characters to escape sequences to solve encoding issues
2026-03-21 18:32:09 +08:00
Kolyah35
3dab395af3 fix workflow and im done 2026-03-21 02:45:06 +03:00
Kolyah35
011c8f7123 fix mingw build 2026-03-21 02:35:04 +03:00
Kolyah35
f69c009da9 replace pwd with workspace 2026-03-21 01:38:17 +03:00
Kolyah35
b66b4a2dc2 wtf im dumb 2026-03-21 01:35:40 +03:00
Kolyah35
7037b2b5f2 create build dir 2026-03-21 01:33:57 +03:00
Kolyah35
d54e39b332 -_- 2026-03-21 01:32:47 +03:00
Kolyah35
f96ba8bb33 ubuntu 22.04 2026-03-21 01:31:42 +03:00
Kolyah35
f0e1980f59 i dont like xwin anymore 2026-03-21 01:31:35 +03:00
mschiller890
52f607b126 Made some changes to the GUI scale slider.
Should be waaaaaaay better now
2026-03-20 23:20:37 +01:00
Kolyah35
84a956531c and here 2026-03-21 00:56:21 +03:00
Kolyah35
c4f5f22f24 disable module scan 2026-03-21 00:51:35 +03:00
Kolyah35
7867aea042 bruh 2026-03-21 00:43:57 +03:00
Kolyah35
a90e1463ee maybe try geode msvc sdk 2026-03-21 00:41:19 +03:00
Kolyah35
59e820e27f setup ninja 2026-03-21 00:33:59 +03:00
Kolyah35
1199f53632 -_- 2026-03-21 00:28:07 +03:00
Kolyah35
dc0e2c192b oh i forgot headers 2026-03-21 00:23:56 +03:00
Kolyah35
6ef9efa434 maybe ninja? 2026-03-21 00:17:53 +03:00
Kolyah35
72e6537dc5 Merge remote-tracking branch 'refs/remotes/origin/main' 2026-03-21 00:15:24 +03:00
Kolyah35
0e2e7694d3 oops 2026-03-21 00:12:51 +03:00
InviseDivine
45f04ca07b readme fix 2026-03-20 23:08:24 +02:00
InviseDivine
42e7a3da90 Merge branch 'main' of https://gitea.sffempire.ru/Kolyah35/minecraft-pe-0.6.1 2026-03-20 23:00:36 +02:00
InviseDivine
0edee15930 FEAT:Raspberry PI cursor in tweaks 2026-03-20 22:59:52 +02:00
mschiller890
753fdbe701 FIXED: support 64x32 + 64x64 skins with fallback for failed skin URL 2026-03-20 21:47:53 +01:00
mschiller890
ac60559a22 FIXED: Saving works on Android now!
I honestly changed too much stuff trying to pinpoint a fix. I might be stupid.
I have no idea what I did that fixed this.
2026-03-20 21:11:17 +01:00
Kolyah35
be6fa57a10 trying to speed up windows build 2026-03-20 23:07:27 +03:00
Kolyah35
68f5bc3a0a why zip only files inside data??? 2026-03-20 22:56:00 +03:00
Kolyah35
0a24a51663 uuuh 2026-03-20 22:43:49 +03:00
Kolyah35
96b17e9c8a tring to pack data with desktop releases 2026-03-20 22:26:26 +03:00
Kolyah35
c08c4d270d specify targets for linux 2026-03-20 22:17:20 +03:00
Kolyah35
8cd74922bf maybe remove that subdir from path? 2026-03-20 22:10:50 +03:00
Kolyah35
b2707cc35d yeah fix shit 2026-03-20 22:03:41 +03:00
Kolyah35
1ff91505d8 FIX: ndk and tools caching 2026-03-20 21:57:57 +03:00
Kolyah35
b909f3c576 EnumOption 2026-03-20 21:53:10 +03:00
Kolyah35
8d1c4f1c4e aaah who did revert my cmake changes 2026-03-20 21:50:45 +03:00
Kolyah35
bc5cbe6b73 Merge remote-tracking branch 'refs/remotes/origin/main' 2026-03-20 21:47:46 +03:00
Kolyah35
cda2534c1e ADD: pause and chat btn 2026-03-20 21:46:43 +03:00
mschiller890
c54bdfdcff Target SDK lowered for compatibility
Setting it to 36 broke some permission things
Still seems like the game can't write anywhere even with r/w permissions...
2026-03-20 19:07:25 +01:00
InviseDivine
d5b2c59ebf FIX: Cmake 2026-03-20 19:14:18 +02:00
Kolyah35
5d415dcca1 Merge remote-tracking branch 'refs/remotes/origin/main' 2026-03-20 19:57:24 +03:00
Kolyah35
a317bf66af FIX: Increased save time 2026-03-20 19:57:00 +03:00
InviseDivine
cb28b78776 Merge branch 'main' of https://gitea.sffempire.ru/Kolyah35/minecraft-pe-0.6.1 2026-03-20 18:43:33 +02:00
InviseDivine
6a77ae3c64 FIX: Skins loading 2026-03-20 18:41:28 +02:00
mschiller890
c5fb648df7 FIXED: Android controls no longer tiny 2026-03-20 13:19:57 +01:00
mschiller890
a51f47a108 FIXED: Android 32bit build issues, expanded supported SDKs 2026-03-20 12:57:55 +01:00
mschiller890
017d908c54 armeabi-v7a building should work now.
./build.sh --abi arm64-v8a
./build.sh --abi armeabi-v7a

arm64-v8a is default.
2026-03-20 09:31:34 +01:00
mschiller890
70a45fb446 fixed apk not getting packaged 2026-03-20 09:35:47 +02:00
mschiller890
e0dac8a95c maybe manual caching will be better 2026-03-19 21:37:50 +02:00
mschiller890
1cd73cfc1e hmmmmmmmmmmmmmmmmmmmm... 2026-03-19 21:30:33 +02:00
mschiller890
c1fe428aa3 where are you hiding, r14b NDK 2026-03-19 21:25:44 +02:00
mschiller890
24d3b9488d improve Android build job with cached NDK script 2026-03-19 21:20:15 +02:00
mschiller890
f3f0918e77 SHITSHITSHIT 2026-03-19 20:39:30 +02:00
mschiller890
e190335abe Hopefully added Android building to the workflow
please work
2026-03-19 20:36:41 +02:00
InviseDivine
402b053432 wtf 2026-03-19 20:02:15 +02:00
Kolyah35
0964e3ea4b fix release att 1 2026-03-19 20:57:01 +03:00
Kolyah35
0dc8deac93 fuck i dumbass 2026-03-19 20:32:22 +03:00
Kolyah35
13280cb8a7 fix artifacts att 3 2026-03-19 20:16:04 +03:00
Kolyah35
11117cd4f6 fix artifacts att 2 2026-03-19 19:46:58 +03:00
Kolyah35
78d218ccb1 fix build att 6 2026-03-19 19:31:52 +03:00
Kolyah35
a72c2c4094 FIX: windows build ig 2026-03-19 19:12:00 +03:00
Kolyah35
193f63893d REMOVE: png server dependency 2026-03-19 19:09:40 +03:00
Kolyah35
bb181ca838 AAAAH 2026-03-19 18:59:05 +03:00
Kolyah35
eadbe78f6b -_- 2026-03-19 18:58:00 +03:00
Kolyah35
bfc796b59f oh fu 2026-03-19 18:55:17 +03:00
Kolyah35
04d892c926 ADD: github actions 2026-03-19 18:53:13 +03:00
Kolyah35
e469e03366 REMOVE: all build actions 2026-03-19 17:58:48 +03:00
Kolyah35
ca2af5edb4 ADD: fire (and reduce options writings) 2026-03-19 17:55:22 +03:00
Kolyah35
e49f58bc89 Merge remote-tracking branch 'refs/remotes/origin/main' 2026-03-19 02:27:04 +03:00
Kolyah35
e9914e3fbd ADD: WebASM port (no sound/no network) 2026-03-19 02:26:34 +03:00
InviseDivine
157ef5ff05 FIX: Settings save when leave on escape 2026-03-18 22:50:35 +02:00
Kolyah35
4769d4ae72 minor changes 2026-03-17 23:08:56 +03:00
Kolyah35
d15051aab6 Merge remote-tracking branch 'refs/remotes/origin/main' 2026-03-17 22:50:18 +03:00
Kolyah35
5ff8b54c4f REMOVE: User class 2026-03-17 22:49:59 +03:00
mschiller890
48e3b11c4e can i get a better error please??? 2026-03-17 21:44:23 +02:00
Kolyah35
2c132d5bc7 cache ndk to avoid downloading and extracting :v 2026-03-17 21:59:19 +03:00
Kolyah35
e0a39fb6c1 Merge remote-tracking branch 'refs/remotes/origin/main' 2026-03-17 21:59:16 +03:00
Kolyah35
ccac464750 just a comment 2026-03-17 21:53:15 +03:00
mschiller890
11e986bcf2 FIXED: Android build issues, added building to Andr from Linux
I really hope this didnt break anything
Im proud of the bash script
2026-03-17 19:01:27 +01:00
Kolyah35
9d831bdb25 trying to up android build 2026-03-17 00:58:22 +03:00
Kolyah35
7e86e34189 Merge remote-tracking branch 'refs/remotes/origin/main' 2026-03-17 00:40:49 +03:00
Kolyah35
1ca46fab32 some fixes 2026-03-17 00:40:32 +03:00
InviseDivine
7877301d7f Update .github/workflows/cmake-multiplatform.yml 2026-03-16 23:24:18 +02:00
Kolyah35
b8df42d9bd trying to up actions 2026-03-17 00:20:56 +03:00
InviseDivine
cdada510a0 readme upd 2026-03-16 23:18:44 +02:00
deepfriedwaffles
f3e94f697f Added *.xcuserstate wildcsrd to Xcode ignores 2026-03-16 17:02:34 -04:00
Kolyah35
aaad53761e Merge remote-tracking branch 'refs/remotes/origin/main' 2026-03-16 23:18:53 +03:00
Kolyah35
183487853c hopefully fixed blackscreen 🙏 2026-03-16 23:16:16 +03:00
mschiller890
2bc3be3153 FIXED: chat history clears on disconnect 2026-03-16 19:05:55 +01:00
Michal Schiller
997c3f2ebe Added a list of players when in multiplayer (tab list) 2026-03-16 13:34:42 +01:00
Michal Schiller
d3cf64cfdc FIXED: Skins work on Linux
There's still one more issue to this:
other peoples skins in multiplayer show corrupted.
2026-03-16 09:00:36 +01:00
Michal Schiller
babd7b4d96 i fucking FLIPPED the cape textures and fixed issues with options
were the options working for everyone else? am i stupid
2026-03-16 05:19:10 +01:00
InviseDivine
725353eb74 NO_SOUND Define 2026-03-15 22:59:43 +02:00
InviseDivine
c52f5a4393 Merge branch 'main' of https://gitea.sffempire.ru/Kolyah35/minecraft-pe-0.6.1 2026-03-15 22:01:17 +02:00
InviseDivine
df99a29258 FEAT: ifdef CHEATS (temp solution) 2026-03-15 22:01:15 +02:00
InviseDivine
76a5e19e9b Update build instruction 2026-03-15 21:47:57 +02:00
Kolyah35
c7d6289781 FIX: compilation on arm 2026-03-15 21:59:23 +03:00
Kolyah35
a50877af9e ADD: lastip 2026-03-15 20:54:28 +03:00
Kolyah35
fadcf3a7d0 FIX: i fucking wrote profiler just to find that sleep function takes SECONDS arg 😭😭😭😭😭😭😭😭😭😭 2026-03-15 20:35:02 +03:00
Kolyah35
b0fa2b820c REMOVE: debug feature 2026-03-15 18:32:41 +03:00
InviseDivine
c03f535c7e FIX: Nether reactor (by @bravelycowering) 2026-03-14 20:42:38 +02:00
InviseDivine
03ff7b118e settings names fixed 2026-03-14 20:24:28 +02:00
Kolyah35
1f5e1244f2 Merge pull request 'start menu screen overhaul' (#3) from freetolga/minecraft-pe-0.6.1:start-screen-overhaul into main
Reviewed-on: https://192.168.0.2:3000/Kolyah35/minecraft-pe-0.6.1/pulls/3
2026-03-14 17:21:58 +02:00
Kolyah35
0aa94bc56f REMOVE: AI useless code 2026-03-14 18:15:08 +03:00
freetolga
5f612652d9 start menu screen overhaul 2026-03-14 17:57:55 +03:00
Kolyah35
bf1a6d79b4 Merge remote-tracking branch 'refs/remotes/origin/main' 2026-03-14 14:52:59 +03:00
Kolyah35
e49fe348e3 FIX: override warnings 2026-03-14 14:51:42 +03:00
Kolyah35
bb95e75c47 Merge remote-tracking branch 'refs/remotes/origin/main' 2026-03-14 14:51:25 +03:00
mschiller890
4e179a47b6 Make chat show full history when opened 2026-03-14 12:22:14 +01:00
Kolyah35
badd59b644 FIX: Rewrite options 2026-03-14 14:13:49 +03:00
mschiller890
76839dfbaa Android build issues fixed
(except i fixed the wrong stuff first...)
2026-03-14 00:34:44 +01:00
mschiller890
9fd54afd61 Fixed creative mode instant mining 2026-03-14 00:08:58 +01:00
mschiller890
eb8caa887e Merge branch 'main' of https://gitea.sffempire.ru/Kolyah35/minecraft-pe-0.6.1 2026-03-13 23:56:58 +01:00
mschiller890
97daa795fb Added capes (needs improvement) 2026-03-13 23:56:49 +01:00
InviseDivine
754329fc49 Merge branch 'main' of https://gitea.sffempire.ru/Kolyah35/minecraft-pe-0.6.1 2026-03-13 23:23:26 +02:00
InviseDivine
5385342272 sprint on ctrl 2026-03-13 23:23:25 +02:00
mschiller890
0db3a547c7 Merge branch 'main' of https://gitea.sffempire.ru/Kolyah35/minecraft-pe-0.6.1 2026-03-13 22:15:41 +01:00
mschiller890
94f4317b71 Restore cave generation + adjust ore spawn rates 2026-03-13 22:15:30 +01:00
InviseDivine
bf2248063d FEAT: F1 (but why jump doesnt work wtf) 2026-03-13 22:21:53 +02:00
InviseDivine
13dcf593d8 fck 2026-03-13 19:09:12 +02:00
InviseDivine
b547286e53 Merge branch 'main' of https://gitea.sffempire.ru/Kolyah35/minecraft-pe-0.6.1 2026-03-13 19:08:27 +02:00
InviseDivine
ce5307aa30 FEAT: Tweaks in options 2026-03-13 19:08:27 +02:00
mschiller890
85224c42b7 Skin layers added 2026-03-13 16:56:27 +01:00
mschiller890
450f0d9ec2 Merge branch 'main' of https://gitea.sffempire.ru/Kolyah35/minecraft-pe-0.6.1 2026-03-13 16:26:28 +01:00
mschiller890
12d5835711 Watch out! Skins! 2026-03-13 16:26:19 +01:00
InviseDivine
969d6b3ee7 Forgot about view bobick 2026-03-13 17:12:55 +02:00
InviseDivine
b0de432339 FIX: Settings save 2026-03-13 17:09:39 +02:00
InviseDivine
6f7812293e settings almost fixed 2026-03-13 15:57:16 +02:00
mschiller890
37e28d0fcc added a username label to the title screen 2026-03-13 13:22:47 +01:00
mschiller890
954ec6e505 Game now actually pauses when in a local world and when the server is set to be invisible. 2026-03-13 11:25:20 +01:00
mschiller890
b1cd6c6581 Added a dummy cheats toggle to the world creation screen. 2026-03-13 11:04:58 +01:00
mschiller890
248e9cb69a removed survival kit thing, go mining 2026-03-13 09:22:38 +01:00
mschiller890
caedc293eb Merge branch 'main' of https://gitea.sffempire.ru/Kolyah35/minecraft-pe-0.6.1 2026-03-13 08:23:20 +01:00
mschiller890
2e9a9b810c Limit username to 12 chars and adjusted the Done button to go more with the rest of the games UI. 2026-03-13 08:22:54 +01:00
mschiller890
ce4c3e9d93 Update README.md 2026-03-13 09:05:59 +02:00
mschiller890
470509ee52 Add "Quit Game" button 2026-03-12 21:42:20 +01:00
mschiller890
0ea8b87970 Prevent duplicate world IDs by loading existing level list before generating a unique name 2026-03-12 21:31:01 +01:00
mschiller890
b4f54083dc Fixed door destroy logic 2026-03-12 19:17:32 +01:00
Michal Schiller
f17a11c670 Added mouse wheel support to the world selection screen. 2026-03-12 11:02:06 +01:00
mschiller890
adb23d18c6 Update README.md 2026-03-11 20:41:15 +02:00
mschiller890
4b6039d8a4 Added JoinByIPScreen.cpp to the source list 2026-03-11 20:16:35 +02:00
mschiller890
1e908423d5 Replaced std::stoi(port) with atoi(port.c_str()) call because of Android NDK 2026-03-11 20:15:15 +02:00
InviseDivine
4bd3821ff6 Update project/dedicated_server/CMakeLists.txt
change to yours
2026-03-11 19:55:38 +02:00
InviseDivine
28a49debcf Merge branch 'main' of https://gitea.sffempire.ru/Kolyah35/minecraft-pe-0.6.1 2026-03-11 19:52:59 +02:00
InviseDivine
d2a5f4755c remove std stoi 2026-03-11 19:52:25 +02:00
mschiller890
7f3af5c98a Implemented openURL for android and updated init logic 2026-03-11 19:40:13 +02:00
mschiller890
d82d19be68 Updated the Discord link (and removed color tags cuz they were messing up the URL) 2026-03-11 19:38:53 +02:00
mschiller890
33590751c5 Added openURL(String) helper 2026-03-11 19:37:10 +02:00
mschiller890
a80d2ee847 Fix NPE in MainActivity.onDialogCompleted by guarding showSoftInput call with null focus check 2026-03-11 19:10:08 +02:00
InviseDivine
8875342557 Join by ip screen 2026-03-11 19:04:54 +02:00
InviseDivine
933ef9c988 Update README.md 2026-03-11 15:54:33 +02:00
mschiller890
09d28be195 Updated Android build version from 0.4.0 to 0.6.1-alpha-<build> 2026-03-11 12:49:04 +02:00
mschiller890
ffd9dda611 Upload files to "project/android" 2026-03-11 12:47:57 +02:00
mschiller890
6ed2d40edc Update build.ps1 2026-03-11 12:46:16 +02:00
mschiller890
ce6a987651 Game now asks for storage permission during runtime 2026-03-11 12:31:51 +02:00
mschiller890
23cdc15285 Bumped minSdk to 24 2026-03-11 12:27:36 +02:00
mschiller890
904bf68cd6 Bumped minSdk to 24 2026-03-11 12:27:11 +02:00
mschiller890
e529bd5d64 Fixed Done button not working and backspace on Android 2026-03-11 12:21:09 +02:00
mschiller890
099b560273 oopsie 2026-03-11 12:19:48 +02:00
mschiller890
2d70b68b73 Fixed Done button not working and backspace on Android 2026-03-11 11:03:06 +02:00
mschiller890
01f78eabc7 Upload files to "src" 2026-03-11 11:01:29 +02:00
Kolyah35
99164a781d whoops 2026-03-11 02:30:38 +03:00
Kolyah35
d25a04f154 REMOVE: license verification and BuyGame btns/screens 2026-03-11 00:39:27 +03:00
Kolyah35
3c71139a7c FIX: human readable world date 2026-03-10 23:58:20 +03:00
Kolyah35
9991ba312d FIX: improve textbox 2026-03-10 23:36:12 +03:00
Kolyah35
11d5551d02 Merge remote-tracking branch 'refs/remotes/origin/main' 2026-03-10 23:27:15 +03:00
Kolyah35
d0939875fc FIX: improve create world screen 2026-03-10 23:26:02 +03:00
InviseDivine
da1906f94b Fix: linux open links 2026-03-10 22:14:39 +02:00
InviseDivine
04f13ab4a7 Fix: gui, block destroy
Feat: speed up on left mouse button in credits
2026-03-10 22:06:28 +02:00
InviseDivine
2d17f9d152 Ported to textfield 2026-03-10 21:37:12 +02:00
Kolyah35
ae84705332 Merge pull request 'A lot of stuff.' (#1) from mschiller890/minecraft-pe-0.6.1:alotofstuff into main
Reviewed-on: https://192.168.0.2:3000/Kolyah35/minecraft-pe-0.6.1/pulls/1
2026-03-10 21:07:27 +02:00
mschiller890
12b30c245a Update README.md 2026-03-10 21:00:09 +02:00
mschiller890
7345f68aee Update README.md 2026-03-10 20:59:27 +02:00
mschiller890
311e97bd77 Update README.md 2026-03-10 20:40:41 +02:00
mschiller890
6d43273b18 Update README.md 2026-03-10 20:36:33 +02:00
Michal Schiller
2fc323639a Fixes and enhancements from my MCPE repository. (https://github.com/mschiller890/mcpe64) 2026-03-10 19:31:40 +01:00
Kolyah35
0c97ceb340 TextBox / removed BuyButton / impoved CreateWorldScreen 2026-03-10 02:51:32 +03:00
InviseDivine
65d25748db no sound define 2026-03-09 21:15:55 +02:00
InviseDivine
8a53d3432d Fix: Creative mode flying and cheats enabled 2026-03-09 20:40:07 +02:00
InviseDivine
5311b134ac Fix: Block destroy 2026-03-09 19:14:38 +02:00
InviseDivine
310ff754ee Update README.md 2026-03-09 16:14:47 +02:00
InviseDivine
416253ebc7 Обновить README.md 2026-03-09 15:14:42 +02:00
InviseDivine
0370944cf6 Fix: block building 2026-03-09 15:05:44 +02:00
InviseDivine
6c22f3bc25 Fix: Sounds (now properly) 2026-03-09 14:11:28 +02:00
InviseDivine
d0f6a9b805 Fix: Sounds
Problem: its not working xD
2026-03-09 13:24:11 +02:00
InviseDivine
d0995643a5 Fix: line changing on signs, game launch on AMD gpus, mouse sensitivity
Feat: inv slots changing on keyboard
2026-03-06 22:48:59 +02:00
Kolyah35
f82021117c FIX: MSVC compile and item gui on desktop 2026-03-05 18:01:42 +03:00
990 changed files with 99500 additions and 97593 deletions

27
.github/actions/setup-cache/action.yml vendored Normal file
View File

@@ -0,0 +1,27 @@
name: Setup cache
description: Sets up sccache, CPM cache, etc.
inputs:
host:
description: 'Host platform: win or linux'
required: true
target:
description: 'Target platform: win, linux'
required: true
runs:
using: "composite"
steps:
- name: Setup sccache
uses: hendrikmuhs/ccache-action@v1.2.13
with:
variant: sccache
key: ${{ inputs.target }}-v1
- name: Setup CPM Cache
uses: actions/cache@v4
with:
path: cpm-cache
key: cpm-${{ inputs.target }}-v1-${{ hashFiles('**/CMakeLists.txt', '**/*.cmake') }}
restore-keys: |
cpm-${{ inputs.target }}-v1-

17
.github/actions/setup-ninja/action.yml vendored Normal file
View File

@@ -0,0 +1,17 @@
name: Setup Ninja
description: Sets up Ninja
inputs:
host:
description: 'Host platform: win, mac or linux'
required: true
runs:
using: "composite"
steps:
- name: Setup
shell: bash
run: |
curl -L https://github.com/ninja-build/ninja/releases/latest/download/ninja-${{ inputs.host }}.zip -o ninja.zip
7z x ninja.zip -o"$GITHUB_WORKSPACE/ninja"
echo "$GITHUB_WORKSPACE/ninja" >> $GITHUB_PATH

343
.github/workflows/build.yml vendored Normal file
View File

@@ -0,0 +1,343 @@
name: Build Game
on:
workflow_dispatch:
pull_request:
push:
branches:
- '**' # every branch
- '!no-build-**' # unless marked as no-build
env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: Release
CPM_SOURCE_CACHE: ${{ github.workspace }}/cpm-cache
permissions:
contents: write
jobs:
build-windows:
name: Build Windows
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: Setup caches
uses: ./.github/actions/setup-cache
with:
host: linux
target: win
- name: Setup Ninja
uses: ./.github/actions/setup-ninja
with:
host: linux
- name: Download llvm-mingw
run: |
curl -L https://github.com/mstorsjo/llvm-mingw/releases/download/20260311/llvm-mingw-20260311-msvcrt-ubuntu-22.04-x86_64.tar.xz -o llvm-mingw.tar.xz
tar -xf llvm-mingw.tar.xz
mv llvm-mingw-* llvm-mingw
- name: Create Build Environment
# Some projects don't allow in-source building, so create a separate build directory
# We'll use this as our working directory for all subsequent commands
run: cmake -E make_directory ${{github.workspace}}/build
- name: Configure CMake
working-directory: ${{github.workspace}}/build
run: |
cmake $GITHUB_WORKSPACE \
-G Ninja \
-DCMAKE_SYSTEM_NAME=Windows \
-DCMAKE_C_COMPILER=$GITHUB_WORKSPACE/llvm-mingw/bin/x86_64-w64-mingw32-clang \
-DCMAKE_CXX_COMPILER=$GITHUB_WORKSPACE/llvm-mingw/bin/x86_64-w64-mingw32-clang++ \
-DCMAKE_RC_COMPILER=$GITHUB_WORKSPACE/llvm-mingw/bin/x86_64-w64-mingw32-windres \
-DALSOFT_BACKEND_PIPEWIRE=OFF \
-DCMAKE_BUILD_TYPE=$BUILD_TYPE
- name: Build
working-directory: ${{github.workspace}}/build
run: cmake --build . --config $BUILD_TYPE --target MinecraftPE --parallel
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: mcpe-windows
path: |
${{github.workspace}}/build/MinecraftPE.exe
${{github.workspace}}/build/libpng16.dll
${{github.workspace}}/build/OpenAL32.dll
${{github.workspace}}/build/libz.dll
build-linux:
name: Build Linux
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup caches
uses: ./.github/actions/setup-cache
with:
host: linux
target: linux
- name: Create Build Environment
# Some projects don't allow in-source building, so create a separate build directory
# We'll use this as our working directory for all subsequent commands
run: cmake -E make_directory ${{github.workspace}}/build
- name: Setup Environment
run: |
sudo apt-get update -qq
sudo apt-get install gcc-multilib
sudo apt-get install -y --no-install-recommends build-essential libgl-dev libwayland-dev xorg-dev libxkbcommon-dev
- name: Configure CMake
# Use a bash shell so we can use the same syntax for environment variable
# access regardless of the host operating system
shell: bash
working-directory: ${{github.workspace}}/build
run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE
- name: Build
working-directory: ${{github.workspace}}/build
shell: bash
run: |
cmake --build . --config $BUILD_TYPE --target MinecraftPE --parallel
cmake --build . --config $BUILD_TYPE --target MinecraftPE-server --parallel
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: mcpe-linux
path: |
${{github.workspace}}/build/MinecraftPE
${{github.workspace}}/build/MinecraftPE-server
build-android: # pray to god
name: Build Android (${{ matrix.abi }})
runs-on: ubuntu-latest
strategy:
# keep going with the other ABI if one fails so you at least get something useful
fail-fast: false
matrix:
abi: [ arm64-v8a, armeabi-v7a ]
env:
ANDROID_SDK_ROOT: ${{ github.workspace }}/android-sdk
ANDROID_NDK_PATH: ${{ github.workspace }}/android-ndk-r14b
ANDROID_PLATFORM_API: 36
ANDROID_BUILD_TOOLS_VERSION: 36.0.0
ADB: /bin/true
# build.sh reads MATRIX_ABI to decide which ABI to build when no --abi flag is passed
MATRIX_ABI: ${{ matrix.abi }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Cache Android command-line tools
id: cache-android-tools
uses: actions/cache@v3
with:
path: ${{ env.ANDROID_SDK_ROOT }}
key: android-cmdline-tools-v36
- name: Setup Android command line tools
if: steps.cache-android-tools.outputs.cache-hit != 'true'
run: |
if [ ! -d "$ANDROID_SDK_ROOT/cmdline-tools/latest" ]; then
mkdir -p "$ANDROID_SDK_ROOT/cmdline-tools"
curl -o cmdline-tools.zip -L "https://dl.google.com/android/repository/commandlinetools-linux-9477386_latest.zip"
unzip -q cmdline-tools.zip -d "$ANDROID_SDK_ROOT/cmdline-tools"
mv "$ANDROID_SDK_ROOT/cmdline-tools/cmdline-tools" "$ANDROID_SDK_ROOT/cmdline-tools/latest"
fi
yes | "$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager" --sdk_root="$ANDROID_SDK_ROOT" "platform-tools" "platforms;android-${ANDROID_PLATFORM_API}" "build-tools;${ANDROID_BUILD_TOOLS_VERSION}"
- name: Cache Android NDK r14b
id: cache-android-ndk
uses: actions/cache@v3
with:
path: ${{ github.workspace }}/android-ndk-r14b
key: android-ndk-r14b
- name: Install Android NDK r14b
if: steps.cache-android-ndk.outputs.cache-hit != 'true'
run: |
if [ ! -d "$ANDROID_NDK_PATH" ]; then
curl -L -o ndk.zip "https://dl.google.com/android/repository/android-ndk-r14b-linux-x86_64.zip"
unzip -q ndk.zip -d "$GITHUB_WORKSPACE"
fi
- name: Install system prerequisites
run: |
sudo apt-get update -qq
sudo apt-get install -y --no-install-recommends wget unzip curl git python3 libncurses6 libtinfo6
if ! ldconfig -p | grep -q "libncurses.so.5"; then
sudo ln -sf /lib/x86_64-linux-gnu/libncurses.so.6 /usr/lib/x86_64-linux-gnu/libncurses.so.5 || true
fi
if ! ldconfig -p | grep -q "libtinfo.so.5"; then
sudo ln -sf /lib/x86_64-linux-gnu/libtinfo.so.6 /usr/lib/x86_64-linux-gnu/libtinfo.so.5 || true
fi
- name: Setup Java 25
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 25
- name: Validate environment
run: |
echo "ANDROID_SDK_ROOT=$ANDROID_SDK_ROOT"
echo "ANDROID_NDK_PATH=$ANDROID_NDK_PATH"
echo "JAVA_HOME=$JAVA_HOME"
echo "MATRIX_ABI=$MATRIX_ABI"
$ANDROID_SDK_ROOT/platform-tools/adb version || true
java -version
javac -version
- name: Run Android build script
run: |
chmod +x ./build.sh
./build.sh
- name: Upload APK
uses: actions/upload-artifact@v4
with:
# artifact name is ABI-specific so both matrix legs can upload without clobbering each other
name: minecraftpe-apk-${{ matrix.abi }}
path: ${{ github.workspace }}/build-apk/minecraftpe-*-debug.apk
build-web:
name: Build Web
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup caches
uses: ./.github/actions/setup-cache
with:
host: linux
target: linux
- name: Setup Ninja
uses: ./.github/actions/setup-ninja
with:
host: linux
- name: Setup emsdk
uses: mymindstorm/setup-emsdk@v14
with:
version: 5.0.3
actions-cache-folder: 'emsdk-cache'
- name: Create Build Environment
# Some projects don't allow in-source building, so create a separate build directory
# We'll use this as our working directory for all subsequent commands
run: cmake -E make_directory ${{github.workspace}}/build
- name: Configure CMake
# Use a bash shell so we can use the same syntax for environment variable
# access regardless of the host operating system
shell: bash
working-directory: ${{github.workspace}}/build
run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -G Ninja -DCMAKE_TOOLCHAIN_FILE="$GITHUB_WORKSPACE/emsdk-cache/emsdk-main/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake"
- name: Build
working-directory: ${{github.workspace}}/build
run: cmake --build . --config $BUILD_TYPE --target MinecraftPE --parallel
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: mcpe-web
path: |
${{github.workspace}}/build/MinecraftPE.js
${{github.workspace}}/build/MinecraftPE.wasm
${{github.workspace}}/build/MinecraftPE.data
publish:
name: Publish
runs-on: ubuntu-latest
needs: [ build-windows, build-linux, build-android, build-web ]
if: github.ref == 'refs/heads/main'
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Declare Version Variables
id: ref
run: |
echo "version=$(cat VERSION | xargs)" >> $GITHUB_OUTPUT
echo "hash=$(git rev-parse --short "$GITHUB_SHA")" >> $GITHUB_OUTPUT
- name: Download Artifacts
uses: actions/download-artifact@v4
- name: Zip Windows Artifacts
uses: vimtor/action-zip@v1.2
with:
files: mcpe-windows/MinecraftPE.exe mcpe-windows/libpng16.dll mcpe-windows/OpenAL32.dll mcpe-windows/libz.dll
dest: minecraftpe-${{ steps.ref.outputs.hash }}-windows.zip
- name: Zip Linux Artifacts
uses: vimtor/action-zip@v1.2
with:
files: mcpe-linux/MinecraftPE
dest: minecraftpe-${{ steps.ref.outputs.hash }}-linux.zip
- name: Zip Linux Server Artifacts
uses: vimtor/action-zip@v1.2
with:
files: mcpe-linux/MinecraftPE-server
dest: minecraftpe-server-${{ steps.ref.outputs.hash }}.zip
- name: Zip Android arm64-v8a Artifact
uses: vimtor/action-zip@v1.2
with:
files: minecraftpe-apk-arm64-v8a/minecraftpe-v8a-debug.apk
dest: minecraftpe-${{ steps.ref.outputs.hash }}-android-arm64-v8a.zip
- name: Zip Android armeabi-v7a Artifact
uses: vimtor/action-zip@v1.2
with:
files: minecraftpe-apk-armeabi-v7a/minecraftpe-v7a-debug.apk
dest: minecraftpe-${{ steps.ref.outputs.hash }}-android-armeabi-v7a.zip
- name: Zip Web Artifact
uses: vimtor/action-zip@v1.2
with:
files: mcpe-web/MinecraftPE.js mcpe-web/MinecraftPE.wasm mcpe-web/MinecraftPE.data misc/web/index.html
dest: minecraftpe-${{ steps.ref.outputs.hash }}-web.zip
- name: Zip Data
uses: vimtor/action-zip@v1.2
with:
files: data
recursive: false
dest: data.zip
- name: Update Development Release
uses: andelf/nightly-release@main
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: dev
name: 'Development Release'
body: |
MinecraftPE development release for commit ${{ github.sha }}.
files: |
./data.zip
./minecraftpe-${{ steps.ref.outputs.hash }}-windows.zip
./minecraftpe-${{ steps.ref.outputs.hash }}-linux.zip
./minecraftpe-server-${{ steps.ref.outputs.hash }}.zip
./minecraftpe-${{ steps.ref.outputs.hash }}-android-arm64-v8a.zip
./minecraftpe-${{ steps.ref.outputs.hash }}-android-armeabi-v7a.zip
./minecraftpe-${{ steps.ref.outputs.hash }}-web.zip

201
.gitignore vendored
View File

@@ -1,3 +1,202 @@
# Build output
build/
linux-build/
out/
bin/
lib/
build-apk/
cmake-build-*/
CMakeFiles/
CMakeCache.txt
cmake_install.cmake
Makefile
# Compiled object files
*.o
*.obj
*.a
*.lib
*.so
*.dylib
*.dll
*.exe
*.out
# CMake generated
install_manifest.txt
compile_commands.json
CTestTestfile.cmake
_CPack_Packages/
*.cbp
# Visual Studio
*.sdf
*.suo
*.user
*.userosscache
*.sln.docstates
*.VC.db
*.VC.opendb
.vs/
ipch/
x64/
x86/
Debug/
Release/
RelWithDebInfo/
MinSizeRel/
# Xcode
*.xcworkspace
xcuserdata/
*.xccheckout
*.xcuserstate
*.moved-aside
DerivedData/
*.hmap
*.ipa
*.dSYM.zip
*.dSYM
# Android
*.apk
*.aab
*.ap_
local.properties
.gradle/
project/.gradle/
project/android/bin/
project/android/gen/
project/android/obj/
project/android_java/bin/
project/android_java/gen/
project/android_java/obj/
project/android/libs/*.so
# macOS
.DS_Store
.AppleDouble
.LSOverride
._*
# Windows
Thumbs.db
ehthumbs.db
Desktop.ini
$RECYCLE.BIN/
# Linux
*~
.nfs*
# CLion / JetBrains
.idea/
*.iml
*.ipr
*.iws
# Eclipse CDT
.project
.cproject
.settings/
# Logs
*.log
# Ninja
.ninja_deps
.ninja_log
build.ninja
# VS Code
.vscode/
*.code-workspace
# Visual Studio additional
*.ncb
*.aps
*.pdb
*.ilk
*.exp
*.iobj
*.ipdb
*.tlog
*.lastbuildstate
*.pch
*.ipch
*.VC.db-shm
*.VC.db-wal
*.svclog
*.vcxproj.user
# CMake generated project files
ALL_BUILD.vcxproj
ALL_BUILD.vcxproj.filters
INSTALL.vcxproj
INSTALL.vcxproj.filters
PACKAGE.vcxproj
PACKAGE.vcxproj.filters
ZERO_CHECK.vcxproj
ZERO_CHECK.vcxproj.filters
MinecraftPE.vcxproj
MinecraftPE.vcxproj.filters
MinecraftPE.sln
CPackConfig.cmake
CPackSourceConfig.cmake
cpm-package-lock.cmake
MinecraftPE.dir/
_deps/
# Test / coverage
Testing/
CTestResults/
*.gcno
*.gcda
*.gcov
coverage/
lcov.info
# Precompiled headers
*.gch
# Compiler / linker intermediates
*.map
*.res
*.d
# Patch / diff leftovers
*.orig
*.rej
*.patch
# Backup / temp
*.bak
*.swp
*.swo
*.tmp
*~.nib
# Tags
tags
TAGS
.tags
ctags
# macOS extra
.Spotlight-V100
.Trashes
.fseventsd
Icon\r
# Windows extra
*.lnk
[Dd]esktop.ini
# User / local config
options.txt
local.cmake
games/
# Dependency cache
vcpkg_installed/
.cache/
conan/

View File

@@ -5,9 +5,77 @@ include(cmake/CPM.cmake)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
set(CMAKE_CXX_FLAGS "-Wno-c++11-narrowing -Wno-invalid-source-encoding -Wno-reserved-user-defined-literal")
set(CMAKE_POLICY_VERSION_MINIMUM 3.10)
include(cmake/EnumOption.cmake)
if(EMSCRIPTEN)
# When configuring web builds with "emcmake cmake -B build -S .", set PLATFORM to Web by default
set(PLATFORM Web CACHE STRING "Platform to build for.")
endif()
enum_option(PLATFORM "Desktop;Web" "Platform to build for.")
find_package(Threads REQUIRED)
find_package(OpenSSL)
if (${PLATFORM} STREQUAL "Desktop")
set(PLATFORM_CPP "PLATFORM_DESKTOP")
if (MINGW)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libstdc++ -static-libgcc")
endif()
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-c++11-narrowing -Wno-narrowing -Wno-invalid-source-encoding -Wno-reserved-user-defined-literal")
endif()
if (WIN32)
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
include_directories(misc/windows)
set(EXTRA_LIBS ws2_32 winhttp)
elseif(UNIX)
find_library(pthread NAMES pthread)
set(EXTRA_LIBS pthread m)
endif()
include_directories("glad/include")
elseif (${PLATFORM} STREQUAL "Web")
set(PLATFORM_CPP "PLATFORM_WEB")
set(EXTRA_LIBS "idbfs.js")
endif()
# I totally shocked
if(${PLATFORM} MATCHES "Web")
set(PNG_LIB png)
set(AL_LIBTYPE "STATIC")
add_library(zlib INTERFACE IMPORTED)
set_target_properties(zlib PROPERTIES
INTERFACE_LINK_OPTIONS "-sUSE_ZLIB=1"
)
add_library(png INTERFACE IMPORTED)
set_target_properties(png PROPERTIES
INTERFACE_COMPILE_OPTIONS "-sUSE_LIBPNG=1"
INTERFACE_LINK_OPTIONS "-sUSE_LIBPNG=1"
)
add_library(glfw INTERFACE IMPORTED)
set_target_properties(glfw PROPERTIES
INTERFACE_LINK_OPTIONS "-sUSE_GLFW=3"
)
else()
set(PNG_LIB png_shared)
set(AL_LIBTYPE "SHARED")
CPMAddPackage(
NAME "zlib"
GIT_REPOSITORY "https://github.com/madler/zlib"
GIT_TAG "v1.3.2"
)
CPMAddPackage("gh:madler/zlib@1.3.2")
CPMAddPackage(
NAME "libpng"
GIT_REPOSITORY "https://github.com/pnggroup/libpng.git"
@@ -17,9 +85,20 @@ CPMAddPackage(
"ZLIB_INCLUDE_DIRS ${zlib_SOURCE_DIR}"
"PNG_TOOLS OFF"
"PNG_TESTS OFF"
"BUILD_SHARED_LIBS ON"
)
CPMAddPackage(
NAME "glfw"
GIT_REPOSITORY "https://github.com/glfw/glfw.git"
GIT_TAG "3.4"
EXCLUDE_FROM_ALL TRUE
OPTIONS
"GLFW_BUILD_EXAMPLES OFF"
"GLFW_BUILD_TESTS OFF"
"GLFW_BUILD_DOCS OFF"
)
endif()
CPMAddPackage(
NAME "openal"
GIT_REPOSITORY "https://github.com/kcat/openal-soft.git"
@@ -28,21 +107,116 @@ CPMAddPackage(
"ALSOFT_EXAMPLES OFF"
"ALSOFT_TESTS OFF"
"ALSOFT_UTILS OFF"
"BUILD_SHARED_LIBS ON"
"LIBTYPE ${AL_LIBTYPE}"
"ALSOFT_ENABLE_MODULES OFF"
"ALSOFT_STATIC_STDCXX ON"
"ALSOFT_STATIC_LIBGCC ON"
)
CPMAddPackage(
NAME "glfw"
GIT_REPOSITORY "https://github.com/glfw/glfw.git"
GIT_TAG "3.4"
OPTIONS
"GLFW_BUILD_EXAMPLES OFF"
"GLFW_BUILD_TESTS OFF"
"GLFW_BUILD_DOCS OFF"
"BUILD_SHARED_LIBS ON"
# TODO: Clear this paths with *
file(GLOB SERVER_SOURCES
"project/lib_projects/raknet/jni/RaknetSources/*.cpp"
"src/Performance.cpp"
"src/SharedConstants.cpp"
"src/Minecraft.cpp"
"src/MinecraftServer.cpp"
"src/App.cpp"
"src/IPlatform.cpp"
# "src/client/IConfigListener.cpp"
# "src/client/Minecraft.cpp"
# "src/client/OptionStrings.cpp"
# "src/client/Option.cpp"
# "src/client/Options.cpp"
# "src/client/OptionsFile.cpp"
# "src/client/ServerProfiler.cpp"
# "src/client/gamemode/CreativeMode.cpp"
# "src/client/gamemode/GameMode.cpp"
# "src/client/gamemode/SurvivalMode.cpp"
# "src/client/player/LocalPlayer.cpp"
# "src/client/player/RemotePlayer.cpp"
# "src/client/player/input/KeyboardInput.cpp"
"src/gamemode/*.cpp"
"src/locale/I18n.cpp"
"src/main_dedicated.cpp"
"src/nbt/Tag.cpp"
"src/network/NetEventCallback.cpp"
"src/network/Packet.cpp"
"src/network/RakNetInstance.cpp"
"src/network/ServerSideNetworkHandler.cpp"
"src/network/command/CommandServer.cpp"
"src/platform/CThread.cpp"
"src/platform/HttpClient.cpp"
"src/platform/PngLoader.cpp"
"src/platform/time.cpp"
"src/platform/server/PlatformServer.cpp"
"src/server/ArgumentsSettings.cpp"
"src/server/ServerLevel.cpp"
"src/server/ServerPlayer.cpp"
"src/util/DataIO.cpp"
"src/util/Mth.cpp"
"src/util/PerfTimer.cpp"
"src/util/StringUtils.cpp"
"src/world/Direction.cpp"
"src/world/entity/*.cpp"
"src/world/entity/ai/control/MoveControl.cpp"
"src/world/entity/animal/*.cpp"
"src/world/entity/item/*.cpp"
"src/world/entity/monster/*.cpp"
"src/world/entity/player/Inventory.cpp"
"src/world/entity/player/Player.cpp"
"src/world/entity/projectile/Arrow.cpp"
"src/world/entity/projectile/Throwable.cpp"
"src/world/food/SimpleFoodData.cpp"
"src/world/inventory/*.cpp"
"src/world/item/*.cpp"
"src/world/item/crafting/*.cpp"
"src/world/level/*.cpp"
"src/world/level/biome/Biome.cpp"
"src/world/level/biome/BiomeSource.cpp"
"src/world/level/chunk/LevelChunk.cpp"
"src/world/level/dimension/Dimension.cpp"
"src/world/level/levelgen/*.cpp"
"src/world/level/levelgen/feature/Feature.cpp"
"src/world/level/levelgen/synth/*.cpp"
"src/world/level/material/Material.cpp"
"src/world/level/pathfinder/Path.cpp"
"src/world/level/storage/*.cpp"
"src/world/level/tile/*.cpp"
"src/world/level/tile/entity/*.cpp"
"src/world/phys/HitResult.cpp"
)
file(GLOB SOURCES
file(GLOB CLIENT_SOURCES
"src/client/*.cpp"
"src/client/gamemode/*.cpp"
@@ -118,34 +292,32 @@ file(GLOB SOURCES
"src/SharedConstants.cpp"
"src/main.cpp"
"src/NinecraftApp.cpp"
"src/AppPlatform_glfw.cpp"
"src/main.cpp"
)
if(NOT DEFINED PLATFORM)
set(PLATFORM "PLATFORM_GLFW")
if (${PLATFORM} STREQUAL "Desktop")
list(APPEND CLIENT_SOURCES glad/src/glad.c)
endif()
# Server
if(UNIX)
add_executable("${PROJECT_NAME}-server" ${SERVER_SOURCES})
if(PLATFORM STREQUAL "PLATFORM_WIN32")
list(APPEND SOURCES "src/AppPlatform_win32.cpp")
endif()
target_compile_definitions("${PROJECT_NAME}-server" PUBLIC "STANDALONE_SERVER" "SERVER_PROFILER")
if(PLATFORM STREQUAL "PLATFORM_GLFW")
list(APPEND SOURCES "src/AppPlatform_glfw.cpp")
endif()
add_executable(${PROJECT_NAME}
${SOURCES}
"glad/src/glad.c"
target_include_directories("${PROJECT_NAME}-server" PUBLIC
"${CMAKE_SOURCE_DIR}/src/"
"project/lib_projects/raknet/jni/RaknetSources"
)
if(WIN32)
set(EXTRA_LIBS "ws2_32")
target_compile_definitions(${PROJECT_NAME} PUBLIC "_CRT_SECURE_NO_WARNINGS")
target_link_libraries("${PROJECT_NAME}-server" ${CMAKE_THREAD_LIBS_INIT})
endif()
if(PLATFORM STREQUAL "PLATFORM_WIN32" OR PLATFORM STREQUAL "PLATFORM_GLFW")
target_compile_definitions(${PROJECT_NAME} PUBLIC "PLATFORM_DESKTOP")
endif()
add_executable(${PROJECT_NAME} ${CLIENT_SOURCES})
target_compile_definitions(${PROJECT_NAME} PUBLIC ${PLATFORM_CPP})
target_include_directories(${PROJECT_NAME} PUBLIC
"${CMAKE_SOURCE_DIR}/glad/include/"
@@ -155,8 +327,57 @@ target_include_directories(${PROJECT_NAME} PUBLIC
"lib/include"
)
target_compile_definitions(${PROJECT_NAME} PUBLIC "OPENGL_ES" "NO_EGL" ${PLATFORM})
target_link_libraries(${PROJECT_NAME} zlib png_shared alsoft.common OpenAL::OpenAL glfw ${EXTRA_LIBS})
if(${PLATFORM} MATCHES "Web")
set(CMAKE_CXX_STANDARD 11)
# uuuh i hate it
set(EM_FLAGS "-pthread -sUSE_PTHREADS=1 -sUSE_LIBPNG=1 -sSHARED_MEMORY=1")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EM_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EM_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${EM_FLAGS} --preload-file ${CMAKE_SOURCE_DIR}/data@/data")
target_compile_options(${PROJECT_NAME} PUBLIC
"-Os"
"-Wno-invalid-source-encoding"
"-Wno-narrowing"
"-Wno-deprecated-register"
"-Wno-reserved-user-defined-literal"
)
target_link_options(${PROJECT_NAME} PUBLIC
"-Os"
"-sALLOW_MEMORY_GROWTH=1"
"-sFORCE_FILESYSTEM=1"
"-sLEGACY_GL_EMULATION=1"
"-sGL_UNSAFE_OPTS=0"
"-sEMULATE_FUNCTION_POINTER_CASTS=1"
"-sALLOW_TABLE_GROWTH=1"
"-sEXPORTED_RUNTIME_METHODS=['FS','stringToUTF8','UTF8ToString','cwrap','ccall','HEAP8','HEAPU8','HEAP32','HEAPU32']"
"-sEXPORTED_FUNCTIONS=['_main']"
)
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
message("DEBUG MODE")
target_link_options(${PROJECT_NAME} PUBLIC
"-sASSERTIONS=2"
"-sSTACK_OVERFLOW_CHECK=2"
"-sSTACK_SIZE=5242880"
"-sGL_DEBUG=1"
)
endif()
target_compile_definitions(${PROJECT_NAME} PUBLIC "__EMSCRIPTEN__" "NO_SOUND" "NO_NETWORK")
endif()
# Client
target_compile_definitions(${PROJECT_NAME} PUBLIC "OPENGL_ES" "NO_EGL" "${PLATFORM_CPP}")
target_link_libraries(${PROJECT_NAME} zlib ${PNG_LIB} OpenAL::OpenAL glfw ${EXTRA_LIBS})
if (OpenSSL_FOUND)
target_link_libraries(${PROJECT_NAME} OpenSSL::SSL OpenSSL::Crypto)
target_compile_definitions(${PROJECT_NAME} PUBLIC HTTPCLIENT_USE_OPENSSL)
endif()
if (NOT UNIX)
add_custom_command(
@@ -167,8 +388,19 @@ add_custom_command(
)
endif()
if(NOT ${PLATFORM} MATCHES "Web")
add_custom_command(
TARGET ${PROJECT_NAME}
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_SOURCE_DIR}/data" $<TARGET_FILE_DIR:${PROJECT_NAME}>/data
)
else()
add_custom_command(
TARGET ${PROJECT_NAME}
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_SOURCE_DIR}/misc/web/index.html" $<TARGET_FILE_DIR:${PROJECT_NAME}>
)
endif()
message(STATUS "Compiling with the flags:")
message(STATUS " PLATFORM=" ${PLATFORM_CPP})

194
README.md
View File

@@ -1,18 +1,200 @@
# MinecraftPE
> [!Warning]
> Github repository **isnt main**. All issues and pull requests should be send in [Gitea Repository](https://gitea.sffempire.ru/Kolyah35/minecraft-pe-0.6.1).
This is leaked source code of Minecraft PE 0.6.1 with my own impovements :sunglasses:
> [!Important]
> We have a discord server, where you can report bugs or send feedback https://discord.gg/c58YesBxve
First of all I made it build with CMake (w/o VS2012). Also I fixed some compile errors. And finally I ported it to GLFW to make it run on several platforms and remove binary dependencies.
Source code for **Minecraft Pocket Edition 0.6.1 alpha** with various fixes and improvements.
# TODO
This project aims to preserve and improve this early version of Minecraft PE.
# TODO / Roadmap
- [x] Add platform GLFW
- [x] Compile for Linux
- [ ] Compile for android aarch64
- [x] Compile for android aarch64
- [x] Touch control improvements
- [ ] Screen fixes
- [ ] Rewrite platform logic
- [x] Fix sound
- [x] Do a server connection GUI
- [ ] Controller support
- [x] Minecraft server hosting
- [x] Screen fixess
- [x] Fix fog
- [x] Add sprinting
- [x] Chat (semi working) and commands
- [x] Implementing options
- [x] Better F3
# Build
## CMake
### Linux
1. Install dependiences
(Debian-like)
``sudo apt install build-essential git cmake libgl-dev libwayland-dev xorg-dev libxkbcommon-dev``
(Arch-like)
``sudo pacman -S base-devel git cmake libglvnd wayland xorg-server-devel xorgproto libxkbcommon``
2. Create build folder
``mkdir build && cd build``
3. Generate CMake cache and build the project
```
cmake .. -B .
cmake --build .
```
### Windows
1. Install [Visual studio Build Tools](https://aka.ms/vs/stable/vs_BuildTools.exe) and [CMake](https://github.com/Kitware/CMake/releases/download/v4.3.0-rc3/cmake-4.3.0-rc3-windows-x86_64.msi)
2. Create build folder
``mkdir build && cd build``
3. Generate CMake cache and build the project
```
cmake ..
cmake --build .
```
## Visual Studio
1. Open the repository folder in **Visual Studio**.
2. Visual Studio will automatically detect the `CMakeLists.txt` file and generate the project configuration.
3. Set **MinecraftPE.exe** as the **target**.
4. Press **Run** (or F5) to build and launch the game.
## Android
### Windows
1. Download **Android NDK r14b**:
http://dl.google.com/android/repository/android-ndk-r14b-windows-x86_64.zip
2. Extract it to the root of your `C:` drive so the path becomes:
```
C:\android-ndk-r14b
```
3. Run the build script:
```powershell
# Full build (NDK + Java + APK + install)
.\build.ps1
# Skip C++ compilation (Java/assets changed only)
.\build.ps1 -NoCpp
# Skip Java compilation (C++ changed only)
.\build.ps1 -NoJava
# Only repackage + install (no compilation)
.\build.ps1 -NoBuild
```
### Linux
1. Download **Command line tools**:
https://developer.android.com/studio#command-line-tools-only
2. Unzip it into a folder, e.g.:
```bash
mkdir -p "$HOME/Android/Sdk/"
unzip commandlinetools-linux-*.zip -d "$HOME/Android/Sdk/"
```
3. Your structure should look like
```bash
$HOME/Android/Sdk/cmdline-tools/bin/sdkmanager
```
> [!Note]
> `sdkmanager` expects the SDK to include a `cmdline-tools/latest/` folder.
> If you only have `cmdline-tools/bin`, create the required layout:
>
> ```bash
> mkdir -p "$HOME/Android/Sdk/cmdline-tools/latest"
> ln -snf ../bin "$HOME/Android/Sdk/cmdline-tools/latest/bin"
> ln -snf ../lib "$HOME/Android/Sdk/cmdline-tools/latest/lib"
> ln -snf ../source.properties "$HOME/Android/Sdk/cmdline-tools/latest/source.properties"
> ln -snf ../NOTICE.txt "$HOME/Android/Sdk/cmdline-tools/latest/NOTICE.txt"
> ```
4. Install the build tools (and platform) using `sdkmanager`
```bash
export ANDROID_SDK_ROOT="$HOME/Android/Sdk"
export PATH="$ANDROID_SDK_ROOT/cmdline-tools/latest/bin:$PATH"
sdkmanager --install "platform-tools" "platforms;android-35" "build-tools;35.0.0"
```
> [!Note]
> if you want build.sh to always find the SDK,
> Set ANDROID_SDK_ROOT in your shell config (~/.bashrc / ~/.profile / ~/.config/fish/config.fish), for example:
>
> ```bash
> export ANDROID_SDK_ROOT="$HOME/Android/Sdk"
> ```
>
> Then restart your shell (or `source` the file)
5. Verify the install
```bash
ls "$ANDROID_SDK_ROOT/build-tools"
```
You should see a version folder like:
```bash
35.0.0
33.0.2
```
6. Download **Android NDK r14b**:
https://dl.google.com/android/repository/android-ndk-r14b-linux-x86_64.zip
7. Extract the archive to `/home/username/`, so that the final directory path is `/home/username/android-ndk-r14b/`
> [!Warning]
> Make sure you dont end up with a nested folder like `/home/username/android-ndk-r14b/android-ndk-r14b/`.
8. Re run `build.sh`
## Web
1. Download and install **emsdk**: https://emscripten.org/docs/getting_started/downloads.html
> [!Note]
> On arch linux you can use AUR:
> `yay -Sy emsdk`
2. Configure and build project:
```
mkdir build && cd build
cmake .. -B .
make -j4
cmake .. -B . -G Ninja "-DCMAKE_TOOLCHAIN_FILE=$EMSDK/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake"
cmake --build . --target MinecraftPE
```
> [!Note]
> If you are using VSCode with CMake plugin, you can add Emscripten kit
> 1. Press Ctrl + Shift + P
> 2. Type `CMake: Edit User-Local CMake Kits` and hit Enter
> 3. Add this:
```json
{
"name": "Emscripten",
"compilers": {
"C": "/usr/lib/emsdk/upstream/bin/clang",
"CXX": "/usr/lib/emsdk/upstream/bin/clang++"
},
"toolchainFile": "/usr/lib/emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake"
}
```
3. Run game:
```
emrun --port 8080 .
```

305
build.ps1 Normal file
View File

@@ -0,0 +1,305 @@
# ============================================================
# Usage:
# .\build.ps1 # full build (NDK + Java + APK + install)
# .\build.ps1 -NoCpp # skip NDK rebuild (Java/assets changed)
# .\build.ps1 -NoJava # skip Java recompile (C++ changed only)
# .\build.ps1 -NoBuild # repackage + install only (no recompile)
# .\build.ps1 -Clean # remove build output before building
# ============================================================
param(
[switch]$NoCpp,
[switch]$NoJava,
[switch]$NoBuild,
[switch]$Clean
)
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
# ── Paths ────────────────────────────────────────────────────
$repo = $PSScriptRoot
$apkbuild = "C:\apkbuild"
$ndk = "C:\android-ndk-r14b"
$sdkTools = "$env:LOCALAPPDATA\Android\Sdk\build-tools\35.0.0"
$androidJar = "$env:LOCALAPPDATA\Android\Sdk\platforms\android-36\android.jar"
$adb = "$env:LOCALAPPDATA\Android\Sdk\platform-tools\adb.exe"
$keystore = "$apkbuild\debug.keystore"
$pkg = "com.mojang.minecraftpe"
# Auto-detect keytool from JAVA_HOME, then from common install locations
$keytool = if ($env:JAVA_HOME) { "$env:JAVA_HOME\bin\keytool.exe" } else {
$found = Get-ChildItem "C:\Program Files\Java","C:\Program Files\Eclipse Adoptium" `
-Filter keytool.exe -Recurse -ErrorAction SilentlyContinue |
Sort-Object FullName -Descending | Select-Object -First 1 -ExpandProperty FullName
if (-not $found) { throw "keytool not found. Set JAVA_HOME or install a JDK." }
$found
}
$jniDir = "$repo\project\android\jni"
$libSrc = "$repo\project\android\libs\arm64-v8a\libminecraftpe.so"
$libDst = "$apkbuild\lib\arm64-v8a\libminecraftpe.so"
$manifest = "$repo\project\android_java\AndroidManifest.xml"
$res = "$repo\project\android_java\res"
$javaSrc = "$repo\project\android_java\src"
$stubsDir = "$apkbuild\stubs"
$rJava = "$apkbuild\gen\R.java"
$classesDir = "$apkbuild\classes"
$dexOut = "$apkbuild\classes.dex"
$dataDir = "$repo\data"
$unsigned = "$apkbuild\minecraftpe-unsigned.apk"
$aligned = "$apkbuild\minecraftpe-aligned.apk"
$signed = "$apkbuild\minecraftpe-debug.apk"
Add-Type -Assembly "System.IO.Compression.FileSystem"
function Write-Step([string]$msg) { Write-Host "`n==> $msg" -ForegroundColor Cyan }
function Assert-ExitCode([string]$step) {
if ($LASTEXITCODE -ne 0) { Write-Host "FAILED: $step (exit $LASTEXITCODE)" -ForegroundColor Red; exit 1 }
}
function New-Dir([string]$path) { New-Item $path -ItemType Directory -Force | Out-Null }
function Write-Stub([string]$rel, [string]$content) {
$full = "$stubsDir\$rel"
New-Dir (Split-Path $full -Parent)
if (-not (Test-Path $full)) { [System.IO.File]::WriteAllText($full, $content); Write-Host " stub: $rel" }
}
# ── 0. Clean (optional) ───────────────────────────────────────
if ($Clean) {
Write-Step "Cleaning build output"
Remove-Item -Recurse -Force $apkbuild -ErrorAction SilentlyContinue
}
# ── 1. Bootstrap ─────────────────────────────────────────────
Write-Step "Bootstrap"
New-Dir $apkbuild
New-Dir "$apkbuild\lib\arm64-v8a"
New-Dir "$apkbuild\gen"
New-Dir $stubsDir
if (-not (Test-Path $keystore)) {
Write-Host " generating debug.keystore..."
$eap = $ErrorActionPreference; $ErrorActionPreference = "Continue"
& $keytool -genkeypair `
-keystore $keystore -storepass android -keypass android `
-alias androiddebugkey -keyalg RSA -keysize 2048 -validity 10000 `
-dname "CN=Android Debug,O=Android,C=US" 2>&1 | Out-Null
$ErrorActionPreference = $eap
Assert-ExitCode "keytool"
Write-Host " keystore created"
} else { Write-Host " keystore OK" }
Write-Stub "com\mojang\android\StringValue.java" "package com.mojang.android;`npublic interface StringValue { String getStringValue(); }`n"
Write-Stub "com\mojang\android\licensing\LicenseCodes.java" "package com.mojang.android.licensing;`npublic class LicenseCodes { public static final int LICENSE_OK = 0; }`n"
Write-Stub "com\mojang\android\EditTextAscii.java" @"
package com.mojang.android;
import android.content.Context;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.widget.EditText;
public class EditTextAscii extends EditText implements TextWatcher {
public EditTextAscii(Context c) { super(c); addTextChangedListener(this); }
public EditTextAscii(Context c, AttributeSet a) { super(c,a); addTextChangedListener(this); }
public EditTextAscii(Context c, AttributeSet a, int d) { super(c,a,d); addTextChangedListener(this); }
@Override public void onTextChanged(CharSequence s,int st,int b,int co){}
public void beforeTextChanged(CharSequence s,int st,int co,int aft){}
public void afterTextChanged(Editable e){
String s=e.toString(),san=sanitize(s);
if(!s.equals(san))e.replace(0,e.length(),san);
}
static public String sanitize(String s){
StringBuilder sb=new StringBuilder();
for(int i=0;i<s.length();i++){char c=s.charAt(i);if(c<128)sb.append(c);}
return sb.toString();
}
}
"@
Write-Stub "com\mojang\android\preferences\SliderPreference.java" @"
package com.mojang.android.preferences;
import android.content.Context;
import android.content.res.Resources;
import android.preference.DialogPreference;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.SeekBar;
import android.widget.TextView;
public class SliderPreference extends DialogPreference implements SeekBar.OnSeekBarChangeListener {
private static final String NS="http://schemas.android.com/apk/res/android";
private Context _ctx; private TextView _tv; private SeekBar _sb;
private String _suf; private int _def,_max,_val,_min;
public SliderPreference(Context ctx,AttributeSet a){
super(ctx,a); _ctx=ctx;
_suf=gStr(a,NS,"text",""); _def=gInt(a,NS,"defaultValue",0);
_max=gInt(a,NS,"max",100); _min=gInt(a,null,"min",0);
setDefaultValue(_def);
}
@Override protected View onCreateDialogView(){
LinearLayout l=new LinearLayout(_ctx); l.setOrientation(LinearLayout.VERTICAL); l.setPadding(6,6,6,6);
_tv=new TextView(_ctx); _tv.setGravity(Gravity.CENTER_HORIZONTAL); _tv.setTextSize(32);
l.addView(_tv,new LinearLayout.LayoutParams(-1,-2));
_sb=new SeekBar(_ctx); _sb.setOnSeekBarChangeListener(this);
l.addView(_sb,new LinearLayout.LayoutParams(-1,-2));
if(shouldPersist())_val=getPersistedInt(_def);
_sb.setMax(_max); _sb.setProgress(_val); return l;
}
@Override protected void onSetInitialValue(boolean r,Object d){
super.onSetInitialValue(r,d);
_val=r?(shouldPersist()?getPersistedInt(_def):0):(Integer)d;
}
public void onProgressChanged(SeekBar s,int v,boolean f){
_val=v+_min; _tv.setText(_val+_suf);
if(shouldPersist())persistInt(_val); callChangeListener(Integer.valueOf(_val));
}
public void onStartTrackingTouch(SeekBar s){}
public void onStopTrackingTouch(SeekBar s){}
private int gInt(AttributeSet a,String ns,String n,int d){int id=a.getAttributeResourceValue(ns,n,0);return id!=0?getContext().getResources().getInteger(id):a.getAttributeIntValue(ns,n,d);}
private String gStr(AttributeSet a,String ns,String n,String d){int id=a.getAttributeResourceValue(ns,n,0);if(id!=0)return getContext().getResources().getString(id);String v=a.getAttributeValue(ns,n);return v!=null?v:d;}
}
"@
Write-Stub "com\mojang\minecraftpe\MainMenuOptionsActivity.java" @"
package com.mojang.minecraftpe;
import android.app.Activity;
public class MainMenuOptionsActivity extends Activity {
public static final String Internal_Game_DifficultyPeaceful="internal_game_difficulty_peaceful";
public static final String Game_DifficultyLevel="game_difficulty";
public static final String Controls_Sensitivity="controls_sensitivity";
}
"@
Write-Stub "com\mojang\minecraftpe\Minecraft_Market.java" @"
package com.mojang.minecraftpe;
import android.app.Activity; import android.content.Intent; import android.os.Bundle;
public class Minecraft_Market extends Activity {
@Override protected void onCreate(Bundle s){super.onCreate(s);startActivity(new Intent(this,MainActivity.class));finish();}
}
"@
Write-Stub "com\mojang\minecraftpe\Minecraft_Market_Demo.java" @"
package com.mojang.minecraftpe;
import android.content.Intent; import android.net.Uri;
public class Minecraft_Market_Demo extends MainActivity {
@Override public void buyGame(){startActivity(new Intent(Intent.ACTION_VIEW,Uri.parse("market://details?id=com.mojang.minecraftpe")));}
@Override protected boolean isDemo(){return true;}
}
"@
Write-Stub "com\mojang\minecraftpe\GameModeButton.java" @"
package com.mojang.minecraftpe;
import com.mojang.android.StringValue;
import android.content.Context; import android.util.AttributeSet;
import android.view.View; import android.view.View.OnClickListener;
import android.widget.TextView; import android.widget.ToggleButton;
public class GameModeButton extends ToggleButton implements OnClickListener,StringValue {
static final int Creative=0,Survival=1;
private int _type=0; private boolean _attached=false;
public GameModeButton(Context c,AttributeSet a){super(c,a);setOnClickListener(this);}
public void onClick(View v){_update();}
@Override protected void onFinishInflate(){super.onFinishInflate();_update();}
@Override protected void onAttachedToWindow(){if(!_attached){_update();_attached=true;}}
private void _update(){_set(isChecked()?Survival:Creative);}
private void _set(int i){
_type=i<Creative?Creative:(i>Survival?Survival:i);
int id=_type==Survival?R.string.gamemode_survival_summary:R.string.gamemode_creative_summary;
String desc=getContext().getString(id);
View v=getRootView().findViewById(R.id.labelGameModeDesc);
if(desc!=null&&v instanceof TextView)((TextView)v).setText(desc);
}
public String getStringValue(){return new String[]{"creative","survival"}[_type];}
static public String getStringForType(int i){int c=i<Creative?Creative:(i>Survival?Survival:i);return new String[]{"creative","survival"}[c];}
}
"@
Write-Host " stubs OK"
# ── 1. NDK build ─────────────────────────────────────────────
if (-not $NoCpp -and -not $NoBuild) {
Write-Step "NDK build (arm64-v8a)"
# NDK r14b on Windows hits the 32K CreateProcess limit with long paths.
# Work around it by building through a short junction C:\m -> repo root.
# Use forward slashes in the build paths to prevent the NDK toolchain from stripping backslashes.
$junctionBase = "C:/m"
if (-not (Test-Path "C:\m")) {
& cmd.exe /c "mklink /J `"C:\m`" `"$repo`"" | Out-Null
}
Push-Location "$junctionBase/project/android/jni"
$env:NDK_MODULE_PATH = "$junctionBase/project/lib_projects"
# run ndk-build and stream output directly to the console
$ndkCmd = Join-Path $ndk 'ndk-build.cmd'
$ndkArgs = "NDK_PROJECT_PATH=`"$junctionBase/project/android`" APP_BUILD_SCRIPT=`"$junctionBase/project/android/jni/Android.mk`""
$proc = Start-Process -FilePath $ndkCmd -ArgumentList $ndkArgs -NoNewWindow -Wait -PassThru
Pop-Location
if ($proc.ExitCode -ne 0) {
Write-Host "ndk-build failed (exit $($proc.ExitCode))" -ForegroundColor Red
exit 1
}
Copy-Item $libSrc $libDst -Force
Write-Host " .so -> $libDst"
}
# ── 2. Java compile ──────────────────────────────────────────
if (-not $NoJava -and -not $NoBuild) {
Write-Step "Java compile"
New-Dir (Split-Path $rJava -Parent)
& "$sdkTools\aapt.exe" package -f -M $manifest -S $res -I $androidJar -J "$apkbuild\gen" -F "$apkbuild\_rgen.apk"
Assert-ExitCode "aapt R.java"
Remove-Item "$apkbuild\_rgen.apk" -ea SilentlyContinue
$srcs = @(
Get-ChildItem $javaSrc -Recurse -Filter "*.java" | Select-Object -Exp FullName
Get-ChildItem $stubsDir -Recurse -Filter "*.java" | Select-Object -Exp FullName
$rJava
)
Remove-Item $classesDir -Recurse -Force -ea SilentlyContinue
New-Dir $classesDir
& javac --release 8 -cp $androidJar -d $classesDir @srcs
if ($LASTEXITCODE -ne 0) { Write-Host 'javac failed' -ForegroundColor Red; exit 1 }
Write-Host " javac OK"
$classFiles = Get-ChildItem $classesDir -Recurse -Filter "*.class" | Select-Object -Exp FullName
& "$sdkTools\d8.bat" --min-api 21 --output $apkbuild $classFiles
Assert-ExitCode "d8"
Write-Host " d8 -> $dexOut"
}
# ── 3. Package APK ───────────────────────────────────────────
Write-Step "Package APK"
Remove-Item $unsigned,$aligned,$signed -ea SilentlyContinue
& "$sdkTools\aapt.exe" package -f -M $manifest -S $res -I $androidJar -F $unsigned
Assert-ExitCode "aapt package"
$zip = [System.IO.Compression.ZipFile]::Open($unsigned, 'Update')
try {
[System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile($zip,$dexOut,"classes.dex",[System.IO.Compression.CompressionLevel]::Fastest)|Out-Null
[System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile($zip,$libDst,"lib/arm64-v8a/libminecraftpe.so",[System.IO.Compression.CompressionLevel]::NoCompression)|Out-Null
Get-ChildItem $dataDir -Recurse -File | ForEach-Object {
$rel=$_.FullName.Substring("$dataDir\".Length).Replace('\','/')
[System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile($zip,$_.FullName,"assets/$rel",[System.IO.Compression.CompressionLevel]::NoCompression)|Out-Null
}
} finally { $zip.Dispose() }
Write-Host " APK assembled"
& "$sdkTools\zipalign.exe" -p 4 $unsigned $aligned; Assert-ExitCode "zipalign"
& "$sdkTools\apksigner.bat" sign --ks $keystore --ks-pass pass:android --key-pass pass:android --out $signed $aligned; Assert-ExitCode "apksigner"
Write-Host " signed -> $signed"
# ── 4. Install ───────────────────────────────────────────────
Write-Step "Install"
& $adb shell am force-stop $pkg
& $adb uninstall $pkg 2>$null
& $adb install --no-incremental $signed
Assert-ExitCode "adb install"
Write-Host "`nDone." -ForegroundColor Green

455
build.sh Executable file
View File

@@ -0,0 +1,455 @@
#!/usr/bin/env bash
# ============================================================
# Usage:
# ./build.sh # full build (NDK + Java + APK + install)
# ./build.sh --no-cpp # skip NDK rebuild (Java/assets changed)
# ./build.sh --no-java # skip Java recompile (C++ changed only)
# ./build.sh --no-build # repackage + install only (no recompile)
#
# ABI targeting:
# ./build.sh --abi arm64-v8a # build for arm64 only (default)
# ./build.sh --abi armeabi-v7a # build for ARMv7 only
# ./build.sh --abi all # build for both ABIs (fat APK)
# ============================================================
# lets be strict cuz we are safe like that
# *thanos snap*
set -euo pipefail
IFS=$'\n\t'
########################################
# configuration
########################################
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$SCRIPT_DIR"
# build output directory (similar to apkbuild in the PS script)
# maybe doing this in build.ps1 would be cleaner, than putting the apkbuild in C:
BUILD_DIR="$REPO_ROOT/build-apk"
# default Android/NDK/SDK paths (can be overridden by env vars)
ANDROID_NDK_PATH="${ANDROID_NDK_PATH:-$HOME/android-ndk-r14b}"
ANDROID_SDK_ROOT="${ANDROID_SDK_ROOT:-${ANDROID_HOME:-$HOME/Android/Sdk}}"
ANDROID_BUILD_TOOLS_VERSION="${ANDROID_BUILD_TOOLS_VERSION:-}"
ANDROID_PLATFORM_API="${ANDROID_PLATFORM_API:-}"
# ABI selection: can be set via --abi flag or MATRIX_ABI env var.
# Supported values: arm64-v8a, armeabi-v7a, all
# MATRIX_ABI takes precedence over the default but is overridden by --abi on the CLI.
TARGET_ABI="${MATRIX_ABI:-arm64-v8a}"
function fail() {
echo "ERROR: $1" >&2
exit 1
}
function find_build_tools_dir() {
if [[ -n "$ANDROID_BUILD_TOOLS_VERSION" ]]; then
local candidate="$ANDROID_SDK_ROOT/build-tools/$ANDROID_BUILD_TOOLS_VERSION"
[[ -d "$candidate" ]] && echo "$candidate" && return
fi
if [[ ! -d "$ANDROID_SDK_ROOT/build-tools" ]]; then
fail "Android build-tools not found under $ANDROID_SDK_ROOT/build-tools. Set ANDROID_SDK_ROOT or install Android SDK build-tools."
fi
# picking the highest build tools version because its the easiest way rn
# i guess if it breaks then fuck you
local best
best=$(ls -1 "$ANDROID_SDK_ROOT/build-tools" | sort -V | tail -n 1)
[[ -n "$best" && -d "$ANDROID_SDK_ROOT/build-tools/$best" ]] || \
fail "No Android build-tools versions found under $ANDROID_SDK_ROOT/build-tools."
echo "$ANDROID_SDK_ROOT/build-tools/$best"
}
function find_android_platform_dir() {
if [[ -n "$ANDROID_PLATFORM_API" ]]; then
local candidate="$ANDROID_SDK_ROOT/platforms/android-$ANDROID_PLATFORM_API"
[[ -d "$candidate" ]] && echo "$candidate" && return
fi
if [[ ! -d "$ANDROID_SDK_ROOT/platforms" ]]; then
fail "Android platforms not found under $ANDROID_SDK_ROOT/platforms. Install an Android platform."
fi
# pick the highest api level installed for now
# ideally we should be able to build to any api level, but lets keep it simple for now and
# just pick the highest one available
local best
best=$(ls -1 "$ANDROID_SDK_ROOT/platforms" | grep -E '^android-[0-9]+' | sed 's/android-//' | sort -n | tail -n 1)
[[ -n "$best" ]] || fail "No Android platforms found under $ANDROID_SDK_ROOT/platforms."
echo "$ANDROID_SDK_ROOT/platforms/android-$best"
}
ANDROID_BUILD_TOOLS_DIR="$(find_build_tools_dir)"
ANDROID_PLATFORM_DIR="$(find_android_platform_dir)"
KEYSTORE_FILE="$BUILD_DIR/debug.keystore"
PACKAGE_NAME="com.mojang.minecraftpe"
# android tool binaries
AAPT="$ANDROID_BUILD_TOOLS_DIR/aapt"
ZIPALIGN="$ANDROID_BUILD_TOOLS_DIR/zipalign"
APKSIGNER="$ANDROID_BUILD_TOOLS_DIR/apksigner"
DEX_TOOL="$ANDROID_BUILD_TOOLS_DIR/d8"
ADB="${ADB:-$ANDROID_SDK_ROOT/platform-tools/adb}"
# java tool binaries
JAVA_HOME_DEFAULT="${JAVA_HOME:-}" # may be empty
# prefer javac from the jdk;
# on some systems /usr/lib/jvm/default points to a JRE only.
# If javac is missing, try to locate a JDK installation.
JAVAC_CMD=""
if command -v javac >/dev/null 2>&1; then
JAVAC_CMD="$(command -v javac)"
elif [[ -n "$JAVA_HOME_DEFAULT" && -x "$JAVA_HOME_DEFAULT/bin/javac" ]]; then
JAVAC_CMD="$JAVA_HOME_DEFAULT/bin/javac"
elif [[ -x "/usr/lib/jvm/java-8-openjdk/bin/javac" ]]; then
JAVAC_CMD="/usr/lib/jvm/java-8-openjdk/bin/javac"
elif [[ -x "/usr/lib/jvm/default/bin/javac" ]]; then
JAVAC_CMD="/usr/lib/jvm/default/bin/javac"
fi
if [[ -z "$JAVAC_CMD" ]]; then
fail "javac not found; install a JDK and ensure javac is on PATH"
fi
KEYTOOL="" # will be detected later
# swource directories
JNI_DIR="$REPO_ROOT/project/android/jni"
JAVA_SRC_DIR="$REPO_ROOT/project/android_java/src"
ANDROID_MANIFEST="$REPO_ROOT/project/android_java/AndroidManifest.xml"
ANDROID_RES_DIR="$REPO_ROOT/project/android_java/res"
DATA_DIR="$REPO_ROOT/data"
# output files: APK names are derived after argument parsing once TARGET_ABI is final.
# see the "resolve APK output filenames" block below.
APK_UNSIGNED=""
APK_ALIGNED=""
APK_SIGNED=""
DEX_OUTPUT="$BUILD_DIR/classes.dex"
# flags parsed from CLI args
NO_CPP=false
NO_JAVA=false
NO_BUILD=false
########################################
# helpers
########################################
function usage() {
cat <<EOF
Usage: $0 [--no-cpp] [--no-java] [--no-build] [--abi <abi>]
Options:
--no-cpp Skip the NDK (C++) build step
--no-java Skip the Java build step
--no-build Skip the compile steps; just package + install
--abi <abi> Target ABI: arm64-v8a (default), armeabi-v7a, or all
Can also be set via MATRIX_ABI env var for CI matrix builds.
EOF
exit 1
}
function log_step() {
echo -e "\n==> $1"
}
function fail() {
echo "ERROR: $1" >&2
exit 1
}
function require_cmd() {
if ! command -v "$1" >/dev/null 2>&1; then
fail "$1 not found; install it (e.g. 'sudo pacman -S $1')"
fi
}
# ensure required tools are available early
require_cmd zip
require_cmd unzip
function ensure_dir() {
mkdir -p "$1"
}
function find_keytool() {
# first try JAVA_HOME if set
if [[ -n "$JAVA_HOME_DEFAULT" && -x "$JAVA_HOME_DEFAULT/bin/keytool" ]]; then
echo "$JAVA_HOME_DEFAULT/bin/keytool"
return
fi
# try common install locations
if [[ -n "${JAVA_HOME:-}" && -x "${JAVA_HOME}/bin/keytool" ]]; then
echo "${JAVA_HOME}/bin/keytool"
return
fi
if command -v keytool >/dev/null 2>&1; then
command -v keytool
return
fi
fail "keytool not found. Set JAVA_HOME or install a JDK."
}
function write_stub_file() {
local rel_path="$1"
local content="$2"
local full_path="$BUILD_DIR/stubs/$rel_path"
ensure_dir "$(dirname "$full_path")"
if [[ ! -f "$full_path" ]]; then
echo -e "$content" > "$full_path"
echo " stub: $rel_path"
fi
}
function build_ndk_abi() {
local abi="$1"
# armeabi-v7a needs a few extra NDK flags to get hardware FPU support
# without APP_ABI the default would be whatever Android.mk says, so we
# always pass it explicitly so the same Android.mk works for both targets
local -a extra_flags=( "APP_ABI=$abi" )
if [[ "$abi" == "armeabi-v7a" ]]; then
# enable hardware FPU + NEON like the old Minecraft ARMv7 builds used to
extra_flags+=( "APP_ARM_MODE=arm" "APP_ARM_NEON=true" )
fi
echo " ndk-build for $abi..."
if ! "$ANDROID_NDK_PATH/ndk-build" \
NDK_PROJECT_PATH="$REPO_ROOT/project/android" \
APP_BUILD_SCRIPT="$JNI_DIR/Android.mk" \
"${extra_flags[@]}" \
2>&1 | tee "$BUILD_DIR/ndk-build-${abi}.log"; then
echo "NDK build failed for $abi. See $BUILD_DIR/ndk-build-${abi}.log" >&2
exit 1
fi
ensure_dir "$BUILD_DIR/lib/$abi"
cp -v "$REPO_ROOT/project/android/libs/$abi/libminecraftpe.so" "$BUILD_DIR/lib/$abi/"
echo " .so -> $BUILD_DIR/lib/$abi/libminecraftpe.so"
}
########################################
# argument parsing
########################################
while [[ $# -gt 0 ]]; do
case "$1" in
--no-cpp) NO_CPP=true ;;
--no-java) NO_JAVA=true ;;
--no-build) NO_BUILD=true ;;
--abi)
shift
[[ $# -gt 0 ]] || fail "--abi requires a value (arm64-v8a, armeabi-v7a, all)"
TARGET_ABI="$1"
;;
-h|--help) usage ;;
*)
echo "Unknown option: $1" >&2
usage
;;
esac
shift
done
# validate the ABI value now that all args are parsed
case "$TARGET_ABI" in
arm64-v8a|armeabi-v7a|all) ;;
*) fail "Unknown ABI '$TARGET_ABI'. Supported values: arm64-v8a, armeabi-v7a, all" ;;
esac
echo " TARGET_ABI=$TARGET_ABI"
# resolve APK output filenames now that TARGET_ABI is final.
# arm64-v8a -> minecraftpe-v8a-debug.apk
# armeabi-v7a -> minecraftpe-v7a-debug.apk
# all -> minecraftpe-all-debug.apk (fat APK containing both ABIs)
case "$TARGET_ABI" in
arm64-v8a) APK_SUFFIX="v8a" ;;
armeabi-v7a) APK_SUFFIX="v7a" ;;
*) APK_SUFFIX="$TARGET_ABI" ;;
esac
APK_UNSIGNED="$BUILD_DIR/minecraftpe-${APK_SUFFIX}-unsigned.apk"
APK_ALIGNED="$BUILD_DIR/minecraftpe-${APK_SUFFIX}-aligned.apk"
APK_SIGNED="$BUILD_DIR/minecraftpe-${APK_SUFFIX}-debug.apk"
########################################
# validate required tools
########################################
KEYTOOL="$(find_keytool)"
if [[ ! -x "$AAPT" ]]; then
fail "aapt not found at $AAPT"
fi
if [[ ! -x "$ZIPALIGN" ]]; then
fail "zipalign not found at $ZIPALIGN"
fi
if [[ ! -x "$APKSIGNER" ]]; then
fail "apksigner not found at $APKSIGNER"
fi
if [[ ! -x "$DEX_TOOL" ]]; then
fail "d8 not found at $DEX_TOOL"
fi
if [[ ! -x "$ADB" ]]; then
fail "adb not found at $ADB"
fi
########################################
# bootstrap
########################################
log_step "Bootstrap"
ensure_dir "$BUILD_DIR"
ensure_dir "$BUILD_DIR/lib/arm64-v8a"
ensure_dir "$BUILD_DIR/lib/armeabi-v7a"
ensure_dir "$BUILD_DIR/gen"
ensure_dir "$BUILD_DIR/stubs"
# create a debug keystore if it doesn't exist
if [[ ! -f "$KEYSTORE_FILE" ]]; then
echo " generating debug.keystore..."
"$KEYTOOL" -genkeypair \
-keystore "$KEYSTORE_FILE" -storepass android -keypass android \
-alias androiddebugkey -keyalg RSA -keysize 2048 -validity 10000 \
-dname "CN=Android Debug,O=Android,C=US" >/dev/null 2>&1
echo " keystore created"
else
echo " keystore OK"
fi
# why dont we just include the stubs lol
write_stub_file "com/mojang/android/StringValue.java" "package com.mojang.android;\npublic interface StringValue { String getStringValue(); }\n"
write_stub_file "com/mojang/android/licensing/LicenseCodes.java" "package com.mojang.android.licensing;\npublic class LicenseCodes { public static final int LICENSE_OK = 0; }\n"
write_stub_file "com/mojang/android/EditTextAscii.java" "package com.mojang.android;\nimport android.content.Context;\nimport android.text.Editable;\nimport android.text.TextWatcher;\nimport android.util.AttributeSet;\nimport android.widget.EditText;\npublic class EditTextAscii extends EditText implements TextWatcher {\n public EditTextAscii(Context c) { super(c); addTextChangedListener(this); }\n public EditTextAscii(Context c, AttributeSet a) { super(c,a); addTextChangedListener(this); }\n public EditTextAscii(Context c, AttributeSet a, int d) { super(c,a,d); addTextChangedListener(this); }\n @Override public void onTextChanged(CharSequence s,int st,int b,int co){}\n public void beforeTextChanged(CharSequence s,int st,int co,int aft){}\n public void afterTextChanged(Editable e){\n String s=e.toString(),san=sanitize(s);\n if(!s.equals(san))e.replace(0,e.length(),san);\n }\n static public String sanitize(String s){\n StringBuilder sb=new StringBuilder();\n for(int i=0;i<s.length();i++){char c=s.charAt(i);if(c<128)sb.append(c);}\n return sb.toString();\n }\n}\n"
write_stub_file "com/mojang/android/preferences/SliderPreference.java" "package com.mojang.android.preferences;\nimport android.content.Context;\nimport android.content.res.Resources;\nimport android.preference.DialogPreference;\nimport android.util.AttributeSet;\nimport android.view.Gravity;\nimport android.view.View;\nimport android.widget.LinearLayout;\nimport android.widget.SeekBar;\nimport android.widget.TextView;\npublic class SliderPreference extends DialogPreference implements SeekBar.OnSeekBarChangeListener {\n private static final String NS=\"http://schemas.android.com/apk/res/android\";\n private Context _ctx; private TextView _tv; private SeekBar _sb;\n private String _suf; private int _def,_max,_val,_min;\n public SliderPreference(Context ctx,AttributeSet a){\n super(ctx,a); _ctx=ctx;\n _suf=gStr(a,NS,\"text\",\"\"); _def=gInt(a,NS,\"defaultValue\",0);\n _max=gInt(a,NS,\"max\",100); _min=gInt(a,null,\"min\",0);\n setDefaultValue(_def);\n }\n @Override protected View onCreateDialogView(){\n LinearLayout l=new LinearLayout(_ctx); l.setOrientation(LinearLayout.VERTICAL); l.setPadding(6,6,6,6);\n _tv=new TextView(_ctx); _tv.setGravity(Gravity.CENTER_HORIZONTAL); _tv.setTextSize(32);\n l.addView(_tv,new LinearLayout.LayoutParams(-1,-2));\n _sb=new SeekBar(_ctx); _sb.setOnSeekBarChangeListener(this);\n l.addView(_sb,new LinearLayout.LayoutParams(-1,-2));\n if(shouldPersist())_val=getPersistedInt(_def);\n _sb.setMax(_max); _sb.setProgress(_val); return l;\n }\n @Override protected void onSetInitialValue(boolean r,Object d){\n super.onSetInitialValue(r,d);\n _val=r?(shouldPersist()?getPersistedInt(_def):0):(Integer)d;\n }\n public void onProgressChanged(SeekBar s,int v,boolean f){\n _val=v+_min; _tv.setText(_val+_suf);\n if(shouldPersist())persistInt(_val); callChangeListener(Integer.valueOf(_val));\n }\n public void onStartTrackingTouch(SeekBar s){}\n public void onStopTrackingTouch(SeekBar s){}\n private int gInt(AttributeSet a,String ns,String n,int d){int id=a.getAttributeResourceValue(ns,n,0);return id!=0?getContext().getResources().getInteger(id):a.getAttributeIntValue(ns,n,d);}\n private String gStr(AttributeSet a,String ns,String n,String d){int id=a.getAttributeResourceValue(ns,n,0);if(id!=0)return getContext().getResources().getString(id);String v=a.getAttributeValue(ns,n);return v!=null?v:d;}\n}\n"
write_stub_file "com/mojang/minecraftpe/MainMenuOptionsActivity.java" "package com.mojang.minecraftpe;\nimport android.app.Activity;\npublic class MainMenuOptionsActivity extends Activity {\n public static final String Internal_Game_DifficultyPeaceful=\"internal_game_difficulty_peaceful\";\n public static final String Game_DifficultyLevel=\"game_difficulty\";\n public static final String Controls_Sensitivity=\"controls_sensitivity\";\n}\n"
write_stub_file "com/mojang/minecraftpe/Minecraft_Market.java" "package com.mojang.minecraftpe;\nimport android.app.Activity; import android.content.Intent; import android.os.Bundle;\npublic class Minecraft_Market extends Activity {\n @Override protected void onCreate(Bundle s){super.onCreate(s);startActivity(new Intent(this,MainActivity.class));finish();}\n}\n"
write_stub_file "com/mojang/minecraftpe/Minecraft_Market_Demo.java" "package com.mojang.minecraftpe;\nimport android.content.Intent; import android.net.Uri;\npublic class Minecraft_Market_Demo extends MainActivity {\n @Override public void buyGame(){startActivity(new Intent(Intent.ACTION_VIEW,Uri.parse(\"market://details?id=com.mojang.minecraftpe\")));}\n @Override protected boolean isDemo(){return true;}\n}\n"
write_stub_file "com/mojang/minecraftpe/GameModeButton.java" "package com.mojang.minecraftpe;\nimport com.mojang.android.StringValue;\nimport android.content.Context; import android.util.AttributeSet;\nimport android.view.View; import android.view.View.OnClickListener;\nimport android.widget.TextView; import android.widget.ToggleButton;\npublic class GameModeButton extends ToggleButton implements OnClickListener,StringValue {\n static final int Creative=0,Survival=1;\n private int _type=0; private boolean _attached=false;\n public GameModeButton(Context c,AttributeSet a){super(c,a);setOnClickListener(this);}\n public void onClick(View v){_update();}\n @Override protected void onFinishInflate(){super.onFinishInflate();_update();}\n @Override protected void onAttachedToWindow(){if(!_attached){_update();_attached=true;}}\n private void _update(){_set(isChecked()?Survival:Creative);}\n private void _set(int i){\n _type=i<Creative?Creative:(i>Survival?Survival:i);\n int id=_type==Survival?R.string.gamemode_survival_summary:R.string.gamemode_creative_summary;\n String desc=getContext().getString(id);\n View v=getRootView().findViewById(R.id.labelGameModeDesc);\n if(desc!=null&&v instanceof TextView)((TextView)v).setText(desc);\n }\n public String getStringValue(){return new String[]{\"creative\",\"survival\"}[_type];}\n static public String getStringForType(int i){int c=i<Creative?Creative:(i>Survival?Survival:i);return new String[]{\"creative\",\"survival\"}[c];}\n}\n"
echo " stubs OK"
########################################
# ndk build
########################################
if [[ "$NO_CPP" == false && "$NO_BUILD" == false ]]; then
log_step "NDK build ($TARGET_ABI)"
# the original windows build script used a junction to avoid long paths here
# on linux, path lengths are *usually* fine, but we still keep things simple
pushd "$JNI_DIR" >/dev/null
export NDK_MODULE_PATH="$REPO_ROOT/project/lib_projects"
# build each requested ABI by delegating to build_ndk_abi()
if [[ "$TARGET_ABI" == "all" ]]; then
build_ndk_abi "arm64-v8a"
build_ndk_abi "armeabi-v7a"
else
build_ndk_abi "$TARGET_ABI"
fi
popd >/dev/null
fi
########################################
# java compile
########################################
if [[ "$NO_JAVA" == false && "$NO_BUILD" == false ]]; then
log_step "Java compile"
ensure_dir "$(dirname "$BUILD_DIR/gen/R.java")"
# generate R.java
"$AAPT" package -f -M "$ANDROID_MANIFEST" -S "$ANDROID_RES_DIR" -I "$ANDROID_PLATFORM_DIR/android.jar" -J "$BUILD_DIR/gen" -F "$BUILD_DIR/_rgen.apk"
rm -f "$BUILD_DIR/_rgen.apk"
# collect all source files (project + stubs + generated R.java)
JAVA_SOURCES=(
$(find "$JAVA_SRC_DIR" -name "*.java" -print)
$(find "$BUILD_DIR/stubs" -name "*.java" -print)
"$BUILD_DIR/gen/R.java"
)
rm -rf "$BUILD_DIR/classes"
ensure_dir "$BUILD_DIR/classes"
# Some JDK versions (<=8) don't support --release.
JAVAC_ARGS=(--release 8)
if "$JAVAC_CMD" -version 2>&1 | grep -qE '^javac 1\.'; then
JAVAC_ARGS=(-source 1.8 -target 1.8)
fi
"$JAVAC_CMD" "${JAVAC_ARGS[@]}" -cp "$ANDROID_PLATFORM_DIR/android.jar" -d "$BUILD_DIR/classes" "${JAVA_SOURCES[@]}"
echo " javac OK"
# convert class files into dex
JAVA_CLASS_FILES=( $(find "$BUILD_DIR/classes" -name "*.class" -print) )
"$DEX_TOOL" --min-api 21 --output "$BUILD_DIR" "${JAVA_CLASS_FILES[@]}"
echo " d8 -> $DEX_OUTPUT"
fi
########################################
# package apk
########################################
log_step "Package APK"
rm -f "$APK_UNSIGNED" "$APK_ALIGNED" "$APK_SIGNED"
"$AAPT" package -f -M "$ANDROID_MANIFEST" -S "$ANDROID_RES_DIR" -I "$ANDROID_PLATFORM_DIR/android.jar" -F "$APK_UNSIGNED"
# add classes.dex and native library/libraries into apk.
# when building for "all" we pack both ABIs into the same APK so Android can
# pick the right one at install time (fat APK). for a single-ABI build we
# only include the one .so that was actually compiled.
pushd "$BUILD_DIR" >/dev/null
zip -q "$APK_UNSIGNED" "classes.dex"
if [[ "$TARGET_ABI" == "all" ]]; then
zip -q "$APK_UNSIGNED" "lib/arm64-v8a/libminecraftpe.so"
zip -q "$APK_UNSIGNED" "lib/armeabi-v7a/libminecraftpe.so"
else
zip -q "$APK_UNSIGNED" "lib/$TARGET_ABI/libminecraftpe.so"
fi
popd >/dev/null
# add assets from data/ directory into the apk under assets/
TMP_ASSETS_DIR="$(mktemp -d)"
mkdir -p "$TMP_ASSETS_DIR/assets"
cp -r "$DATA_DIR/." "$TMP_ASSETS_DIR/assets/"
pushd "$TMP_ASSETS_DIR" >/dev/null
zip -q -r "$APK_UNSIGNED" assets
popd >/dev/null
rm -rf "$TMP_ASSETS_DIR"
"$ZIPALIGN" -p 4 "$APK_UNSIGNED" "$APK_ALIGNED"
"$APKSIGNER" sign --ks "$KEYSTORE_FILE" --ks-pass pass:android --key-pass pass:android --out "$APK_SIGNED" "$APK_ALIGNED"
echo " signed -> $APK_SIGNED"
########################################
# install
########################################
log_step "Install"
"$ADB" shell am force-stop "$PACKAGE_NAME" || true
"$ADB" uninstall "$PACKAGE_NAME" || true
"$ADB" install --no-incremental "$APK_SIGNED"
echo -e "\nDone. Enjoy MCPE 0.6.1 on your device!"

9
cmake/EnumOption.cmake Normal file
View File

@@ -0,0 +1,9 @@
macro(enum_option var values description)
set(${var}_VALUES ${values})
list(GET ${var}_VALUES 0 default)
set(${var} "${default}" CACHE STRING "${description}")
set_property(CACHE ${var} PROPERTY STRINGS ${${var}_VALUES})
if (NOT ";${${var}_VALUES};" MATCHES ";${${var}};")
message(FATAL_ERROR "Unknown value ${${var}}. Only -D${var}=${${var}_VALUES} allowed.")
endif()
endmacro()

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 90 KiB

After

Width:  |  Height:  |  Size: 111 KiB

View File

@@ -144,6 +144,18 @@ options.fov.max=Quake Pro
options.gamma=Brightness
options.gamma.min=Moody
options.gamma.max=Bright
options.group.mojang=Login
options.group.general=General
options.group.game=Game
options.group.controls=Controls
options.group.graphics=Graphics
options.group.tweaks=Tweaks
options.allowSprint=Allow sprint
options.barOnTop=HUD above inventory
options.rpiCursor=Show Raspberry PI cursor
options.autoJump=Auto Jump
options.thirdperson=Third Person
options.servervisible=Server Visible
options.sensitivity=Sensitivity
options.sensitivity.min=*yawn*
options.sensitivity.max=HYPERSPEED!!!
@@ -156,6 +168,8 @@ options.viewBobbing=View Bobbing
options.ao=Smooth Lighting
options.anaglyph=3D Anaglyph
options.framerateLimit=Performance
options.limitFramerate=Limit Framerate
options.vsync=VSync
options.difficulty=Difficulty
options.difficulty.peaceful=Peaceful
options.difficulty.easy=Easy
@@ -168,8 +182,10 @@ options.graphics.fast=Fast
options.guiScale=GUI Scale
options.guiScale.auto=Auto
options.guiScale.small=Small
options.guiScale.normal=Normal
options.guiScale.medium=Medium
options.guiScale.large=Large
options.guiScale.larger=Larger
options.guiScale.largest=Largest
options.advancedOpengl=Advanced OpenGL
options.renderClouds=Clouds
options.farWarning1=A 64 bit Java installation is recommended
@@ -178,6 +194,15 @@ options.particles=Particles
options.particles.all=All
options.particles.decreased=Decreased
options.particles.minimal=Minimal
options.username=Username
options.smoothCamera=Smooth camera
options.destroyVibration=Destroy vibration
options.isLeftHanded=Left handed
options.useTouchscreen=Use touchscreen
options.fancyGraphics=Fancy graphics
options.renderDebug=Debug render
options.anaglyph3d=3D anaglyph
performance.max=Max FPS
performance.balanced=Balanced
@@ -185,21 +210,21 @@ performance.powersaver=Power saver
controls.title=Controls
key.forward=Forward
key.left=Left
key.back=Back
key.right=Right
key.jump=Jump
key.inventory=Inventory
key.drop=Drop
key.chat=Chat
key.fog=Toggle Fog
key.sneak=Sneak
key.playerlist=List Players
key.attack=Attack
key.use=Use Item
key.pickItem=Pick Block
key.mouseButton=Button %1$s
options.key.forward=Forward
options.key.left=Left
options.key.back=Back
options.key.right=Right
options.key.jump=Jump
options.key.inventory=Inventory
options.key.drop=Drop
options.key.chat=Chat
options.key.fog=Toggle Fog
options.key.sneak=Sneak
options.key.playerlist=List Players
options.key.attack=Attack
options.key.use=Use Item
options.key.pickItem=Pick Block
options.key.mouseButton=Button %1$s
texturePack.openFolder=Open texture pack folder
texturePack.title=Select Texture Pack

0
glad/include/KHR/khrplatform.h Executable file → Normal file
View File

2941
glad/include/glad/glad.h Executable file → Normal file

File diff suppressed because it is too large Load Diff

1393
glad/src/glad.c Executable file → Normal file

File diff suppressed because it is too large Load Diff

46
misc/web/index.html Normal file
View File

@@ -0,0 +1,46 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>MCPE 0.6.1</title>
<style>
html, body {
margin: 0;
padding: 0;
height: 100%;
background: black;
overflow: hidden;
}
#canvas {
width: 100vw;
height: 100vh;
display: block;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script>
var Module = {
canvas: document.getElementById('canvas'),
onRuntimeInitialized: function () { resizeCanvas() }
};
function resizeCanvas() {
const canvas = Module.canvas;
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
window.addEventListener('resize', resizeCanvas);
window.addEventListener('onunload', () => {
FS.syncfs(true, function (err) { console.log('Sync FS failed: ' + err) });
})
</script>
<script src="MinecraftPE.js"></script>
</body>
</html>

View File

@@ -1,13 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mojang.minecraftpe"
android:versionCode="6006"
android:versionName="0.6.0"
android:versionCode="6010"
android:versionName="0.6.1-alpha-0.0.3"
android:installLocation="preferExternal">
<!-- This is the platform API where NativeActivity was introduced. -->
<uses-sdk android:minSdkVersion="9"
android:targetSdkVersion="9" />
<uses-sdk android:minSdkVersion="19"
android:targetSdkVersion="30" />
<!-- uses-feature android:name="android.hardware.touchscreen.multitouch" android:required="true"/ -->

View File

@@ -168,8 +168,10 @@ options.graphics.fast=Fast
options.guiScale=GUI Scale
options.guiScale.auto=Auto
options.guiScale.small=Small
options.guiScale.normal=Normal
options.guiScale.medium=Medium
options.guiScale.large=Large
options.guiScale.larger=Larger
options.guiScale.largest=Largest
options.advancedOpengl=Advanced OpenGL
options.renderClouds=Clouds
options.farWarning1=A 64 bit Java installation is recommended

View File

@@ -1,10 +1,12 @@
LOCAL_PATH := $(call my-dir)
# Convert Windows backslashes to forward slashes so NDK toolchain doesnt treat them as escapes.
LOCAL_PATH := $(subst \,/,$(LOCAL_PATH))
include $(CLEAR_VARS)
LOCAL_MODULE := minecraftpe
LOCAL_SRC_FILES := ../../../src/main.cpp \
../../../src/main_android.cpp \
../../../src/main_android_java.cpp \
../../../src/platform/audio/SoundSystemSL.cpp \
../../../src/platform/input/Controller.cpp \
../../../src/platform/input/Keyboard.cpp \
@@ -12,6 +14,7 @@ LOCAL_SRC_FILES := ../../../src/main.cpp \
../../../src/platform/input/Multitouch.cpp \
../../../src/platform/time.cpp \
../../../src/platform/CThread.cpp \
../../../src/platform/HttpClient.cpp \
../../../src/NinecraftApp.cpp \
../../../src/Performance.cpp \
../../../src/SharedConstants.cpp \
@@ -21,6 +24,7 @@ LOCAL_SRC_FILES := ../../../src/main.cpp \
../../../src/client/Options.cpp \
../../../src/client/OptionsFile.cpp \
../../../src/client/OptionStrings.cpp \
../../../src/client/Option.cpp \
../../../src/client/gamemode/GameMode.cpp \
../../../src/client/gamemode/CreativeMode.cpp \
../../../src/client/gamemode/SurvivalMode.cpp \
@@ -34,13 +38,14 @@ LOCAL_SRC_FILES := ../../../src/main.cpp \
../../../src/client/gui/components/NinePatch.cpp \
../../../src/client/gui/components/OptionsGroup.cpp \
../../../src/client/gui/components/OptionsItem.cpp \
../../../src/client/gui/components/OptionsPane.cpp \
../../../src/client/gui/components/KeyOption.cpp \
../../../src/client/gui/components/TextOption.cpp \
../../../src/client/gui/components/RolledSelectionListH.cpp \
../../../src/client/gui/components/RolledSelectionListV.cpp \
../../../src/client/gui/components/ScrolledSelectionList.cpp \
../../../src/client/gui/components/ScrollingPane.cpp \
../../../src/client/gui/components/Slider.cpp \
../../../src/client/gui/components/SmallButton.cpp \
../../../src/client/gui/components/TextBox.cpp \
../../../src/client/gui/Font.cpp \
../../../src/client/gui/Gui.cpp \
../../../src/client/gui/GuiComponent.cpp \
@@ -48,6 +53,10 @@ LOCAL_SRC_FILES := ../../../src/main.cpp \
../../../src/client/gui/screens/ScreenChooser.cpp \
../../../src/client/gui/screens/ArmorScreen.cpp \
../../../src/client/gui/screens/ChatScreen.cpp \
../../../src/client/gui/screens/ChooseLevelScreen.cpp \
../../../src/client/gui/screens/SimpleChooseLevelScreen.cpp \
../../../src/client/gui/screens/ConsoleScreen.cpp \
../../../src/client/gui/screens/UsernameScreen.cpp \
../../../src/client/gui/screens/ConfirmScreen.cpp \
../../../src/client/gui/screens/ChestScreen.cpp \
../../../src/client/gui/screens/DeathScreen.cpp \
@@ -56,12 +65,14 @@ LOCAL_SRC_FILES := ../../../src/main.cpp \
../../../src/client/gui/screens/IngameBlockSelectionScreen.cpp \
../../../src/client/gui/screens/JoinGameScreen.cpp \
../../../src/client/gui/screens/OptionsScreen.cpp \
../../../src/client/gui/screens/CreditsScreen.cpp \
../../../src/client/gui/screens/PauseScreen.cpp \
../../../src/client/gui/screens/ProgressScreen.cpp \
../../../src/client/gui/screens/RenameMPLevelScreen.cpp \
../../../src/client/gui/screens/SelectWorldScreen.cpp \
../../../src/client/gui/screens/StartMenuScreen.cpp \
../../../src/client/gui/screens/TextEditScreen.cpp \
../../../src/client/gui/screens/JoinByIPScreen.cpp \
../../../src/client/gui/screens/touch/TouchIngameBlockSelectionScreen.cpp \
../../../src/client/gui/screens/touch/TouchJoinGameScreen.cpp \
../../../src/client/gui/screens/touch/TouchSelectWorldScreen.cpp \
@@ -245,7 +256,10 @@ LOCAL_SRC_FILES := ../../../src/main.cpp \
../../../src/world/level/tile/entity/FurnaceTileEntity.cpp \
../../../src/world/phys/HitResult.cpp
LOCAL_CFLAGS := -Wno-psabi $(LOCAL_CFLAGS)
LOCAL_CFLAGS := -DPLATFORM_ANDROID -DPRE_ANDROID23 -Wno-narrowing $(LOCAL_CFLAGS)
LOCAL_CPPFLAGS := -std=c++14 -frtti
LOCAL_CPPFLAGS += -frtti
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../../src
#LOCAL_CFLAGS := -DANDROID_PUBLISH -DDEMO_MODE $(LOCAL_CFLAGS)
#LOCAL_CFLAGS := -DANDROID_PUBLISH $(LOCAL_CFLAGS)

View File

@@ -1,5 +1,7 @@
APP_PLATFORM := android-9
APP_STL := stlport_static
APP_PLATFORM := android-19
APP_STL := gnustl_static
APP_OPTIM := release
APP_ABI := armeabi-v7a
APP_ABI := arm64-v8a
APP_SHORT_COMMANDS := true
APP_CPPFLAGS += -frtti -fexceptions
#APP_ABI := armeabi-v7a x86

View File

@@ -468,17 +468,16 @@ public class MainActivity extends NativeActivity {
_userInputStatus = 1;
InputMethodManager inputManager = (InputMethodManager)getSystemService("input_method");
boolean result = inputManager.showSoftInput(this.getCurrentFocus(), InputMethodManager.SHOW_IMPLICIT);
View focused = this.getCurrentFocus();
if (focused != null) {
boolean result = inputManager.showSoftInput(focused, InputMethodManager.SHOW_IMPLICIT);
} else {
// fallback: try to show using decor view token
View decor = getWindow().getDecorView();
if (decor != null) {
inputManager.showSoftInput(decor, InputMethodManager.SHOW_IMPLICIT);
}
protected void onStart() {
//System.out.println("onStart");
super.onStart();
}
protected void onResume() {
//System.out.println("onResume");
super.onResume();
}
protected void onPause() {

View File

@@ -1,30 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mojang.minecraftpe"
android:versionCode="4000"
android:versionName="0.4.0"
>
<!-- android:installLocation="preferExternal" -->
android:versionCode="6010"
android:versionName="0.6.1-alpha-0.0.3">
<uses-sdk android:targetSdkVersion="8" android:minSdkVersion="7"/>
<uses-sdk
android:minSdkVersion="19"
android:targetSdkVersion="30"/>
<uses-feature android:name="android.hardware.touchscreen.multitouch" android:required="true"/>
<uses-feature
android:name="android.hardware.touchscreen.multitouch"
android:required="true"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.VIBRATE"/>
<application android:icon="@drawable/icon"
<application
android:icon="@drawable/icon"
android:label="@string/app_name"
>
android:hardwareAccelerated="true"
android:extractNativeLibs="true"
android:requestLegacyExternalStorage="true">
<activity android:name="com.mojang.minecraftpe.Minecraft_Market"
<activity
android:name="com.mojang.minecraftpe.Minecraft_Market"
android:label="@string/app_name_short"
android:configChanges="orientation|keyboardHidden"
android:configChanges="orientation|keyboardHidden|screenSize|uiMode"
android:screenOrientation="landscape"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:exported="true">
<meta-data android:name="android.app.lib_name"
<meta-data
android:name="android.app.lib_name"
android:value="minecraftpe"/>
<intent-filter>
@@ -32,13 +41,34 @@
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name="com.mojang.minecraftpe.MainMenuOptionsActivity"></activity>
<meta-data android:name="xperiaplayoptimized_content" android:resource="@string/xperiaplayoptimized_content" />
<meta-data android:name="game_display_name" android:resource="@string/app_name" />
<meta-data android:name="game_icon" android:resource="@drawable/iconx" />
<activity
android:name="com.mojang.minecraftpe.MainActivity"
android:configChanges="orientation|keyboardHidden|screenSize|uiMode"
android:screenOrientation="landscape"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:exported="false"/>
<activity
android:name="com.mojang.minecraftpe.MainMenuOptionsActivity"
android:exported="false"/>
<meta-data
android:name="xperiaplayoptimized_content"
android:resource="@string/xperiaplayoptimized_content"/>
<meta-data
android:name="game_display_name"
android:resource="@string/app_name"/>
<meta-data
android:name="game_icon"
android:resource="@drawable/iconx"/>
<uses-library
android:name="xperiaplaycertified"
android:required="false"/>
<uses-library android:name="xperiaplaycertified" android:required="false"/>
</application>
</manifest>

View File

@@ -168,8 +168,10 @@ options.graphics.fast=Fast
options.guiScale=GUI Scale
options.guiScale.auto=Auto
options.guiScale.small=Small
options.guiScale.normal=Normal
options.guiScale.medium=Medium
options.guiScale.large=Large
options.guiScale.larger=Larger
options.guiScale.largest=Largest
options.advancedOpengl=Advanced OpenGL
options.renderClouds=Clouds
options.farWarning1=A 64 bit Java installation is recommended

View File

@@ -1,4 +1,4 @@
APP_PLATFORM := android-9
APP_PLATFORM := android-19
APP_STL := gnustl_static
APP_OPTIM := release
APP_ABI := armeabi-v7a

View File

@@ -31,6 +31,8 @@ import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.content.pm.PackageManager;
import android.os.Build;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.media.AudioManager;
@@ -40,7 +42,6 @@ import android.os.Vibrator;
import android.preference.PreferenceManager;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
@@ -55,9 +56,13 @@ import com.mojang.minecraftpe.sound.SoundPlayer;
public class MainActivity extends Activity {
/** Called when the activity is first created. */
private static final int PERMISSION_REQUEST_CODE = 123;
private GLView _glView;
private boolean _nativeInitialized = false;
public float invScale = 1.0f;// / 1.5f;
private int _screenWidth = 0;
private int _screenHeight = 0;
Vector<MotionEvent> _touchEvents = new Vector<MotionEvent>();
Vector<KeyEvent> _keyEvents = new Vector<KeyEvent>();
@@ -68,53 +73,103 @@ public class MainActivity extends Activity {
super.onCreate(savedInstanceState);
nativeRegisterThis();
nativeOnCreate();
// Cache screen dimensions once to avoid re-entrant getDisplayMetrics() callbacks
android.util.DisplayMetrics _dm = getResources().getDisplayMetrics();
_screenWidth = Math.max(_dm.widthPixels, _dm.heightPixels);
_screenHeight = Math.min(_dm.widthPixels, _dm.heightPixels);
_glView = new GLView(getApplication(), this);
//_glView.setEGLConfigChooser(8, 8, 8, 8, 16, 0);
_glView.setEGLConfigChooser(true);
//_glView
// _glView.setEGLConfigChooser(
// new GLSurfaceView.EGLConfigChooser() {
//
// @Override
// public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
// // TODO Auto-generated method stub
//
// // Specify a configuration for our opengl session
// // and grab the first configuration that matches is
// int[] configSpec = {
// EGL10.EGL_DEPTH_SIZE, 24,
// EGL10.EGL_NONE
// };
// EGLConfig[] configs = new EGLConfig[1];
// int[] num_config = new int[1];
// egl.eglChooseConfig(display, configSpec, configs, 1, num_config);
// EGLConfig config = configs[0];
// return config;
//
// //return null;
// }
// } );
_glView.commit();
setContentView(_glView);
_soundPlayer = new SoundPlayer(this, AudioManager.STREAM_MUSIC);
checkAndRequestPermissions();
initNative();
}
private void initNative() {
if (_nativeInitialized) {
return;
}
_nativeInitialized = true;
nativeOnCreate(_screenWidth, _screenHeight);
}
// request dangerous permissions at runtime if necessary
private boolean checkAndRequestPermissions() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
return true;
}
boolean writeGranted = checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
boolean readGranted = checkSelfPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
if (writeGranted && readGranted) {
return true;
}
requestPermissions(new String[] {
android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
android.Manifest.permission.READ_EXTERNAL_STORAGE
}, PERMISSION_REQUEST_CODE);
return false;
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == PERMISSION_REQUEST_CODE) {
boolean granted = true;
for (int r : grantResults) {
if (r != PackageManager.PERMISSION_GRANTED) {
granted = false;
break;
}
}
if (granted) {
initNative();
} else {
// We can still run using app-specific external files in scoped-storage,
// so allow startup while warning the user.
initNative();
new AlertDialog.Builder(this)
.setTitle("Storage permission recommended")
.setMessage("MinecraftPE can still run with app-private storage, but public external save/load may require permission.")
.setPositiveButton("OK", null)
.setCancelable(true)
.show();
}
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
// method required by native code to detect touchscreen support
public boolean supportsTouchscreen() {
return true; // all devices using this build are touch-capable
}
public boolean isTouchscreen() { return true; }
static public boolean isXperiaPlay() { return false; }
static private boolean _isPowerVr = false;
public void setIsPowerVR(boolean status) { MainActivity._isPowerVr = status; }
static public boolean isPowerVR() { return _isPowerVr; }
@SuppressWarnings("deprecation")
public void vibrate(int milliSeconds) {
Vibrator v = (Vibrator)this.getSystemService(VIBRATOR_SERVICE);
Vibrator v = (Vibrator) getSystemService(VIBRATOR_SERVICE);
if (android.os.Build.VERSION.SDK_INT >= 26) {
v.vibrate(android.os.VibrationEffect.createOneShot(milliSeconds,
android.os.VibrationEffect.DEFAULT_AMPLITUDE));
} else {
v.vibrate(milliSeconds);
}
}
private void createAlertDialog(boolean hasOkButton, boolean hasCancelButton, boolean preventBackKey) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
@@ -144,9 +199,16 @@ public class MainActivity extends Activity {
@Override
public void onWindowFocusChanged(boolean hasFocus) {
// TODO Auto-generated method stub
//System.out.println("Focus has changed. Has Focus? " + hasFocus);
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
}
}
@Override
@@ -184,9 +246,12 @@ public class MainActivity extends Activity {
return;
}
if (event.getAction() == KeyEvent.ACTION_DOWN)
if (event.getAction() == KeyEvent.ACTION_DOWN) {
nativeOnKeyDown(keyCode);
else if (event.getAction() == KeyEvent.ACTION_UP)
int unicodeChar = event.getUnicodeChar(event.getMetaState());
if (unicodeChar > 0)
nativeTextChar(unicodeChar);
} else if (event.getAction() == KeyEvent.ACTION_UP)
nativeOnKeyUp(keyCode);
}
@@ -347,22 +412,15 @@ public class MainActivity extends Activity {
}
public int getScreenWidth() {
Display display = ((WindowManager)this.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
int out = Math.max(display.getWidth(), display.getHeight());
//System.out.println("getwidth: " + out);
return out;
return _screenWidth;
}
public int getScreenHeight() {
Display display = ((WindowManager)this.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
int out = Math.min(display.getWidth(), display.getHeight());
//System.out.println("getheight: " + out);
return out;
return _screenHeight;
}
public float getPixelsPerMillimeter() {
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
android.util.DisplayMetrics metrics = getResources().getDisplayMetrics();
return (metrics.xdpi + metrics.ydpi) * 0.5f / 25.4f;
}
@@ -465,8 +523,8 @@ public class MainActivity extends Activity {
MainActivity.this.mDialog.show();
MainActivity.this.mDialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
MainActivity.this.mDialog.getWindow().setLayout(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
//MainActivity.this.getWindow().setLayout(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
MainActivity.this.mDialog.getWindow().setLayout(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
//MainActivity.this.getWindow().setLayout(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
}
});
}
@@ -516,6 +574,20 @@ public class MainActivity extends Activity {
public void buyGame() {}
public int getKeyFromKeyCode(int keyCode, int metaState, int deviceId) {
android.view.KeyCharacterMap kcm = android.view.KeyCharacterMap.load(deviceId);
return kcm.get(keyCode, metaState);
}
public void openURL(String url) {
try {
Intent intent = new Intent(Intent.ACTION_VIEW, android.net.Uri.parse(url));
startActivity(intent);
} catch (Exception e) {
e.printStackTrace();
}
}
public String getPlatformStringVar(int id) {
if (id == 0) return android.os.Build.MODEL;
return null;
@@ -604,10 +676,11 @@ public class MainActivity extends Activity {
//
native void nativeRegisterThis();
native void nativeUnregisterThis();
native static void nativeOnCreate();
native static void nativeOnCreate(int screenWidth, int screenHeight);
native static void nativeOnDestroy();
native static void nativeOnKeyDown(int key);
native static void nativeOnKeyUp(int key);
native static void nativeTextChar(int unicodeChar);
native static boolean nativeHandleBack(boolean isDown);
native static void nativeMouseDown(int pointerId, int buttonId, float x, float y);
native static void nativeMouseUp(int pointerId, int buttonId, float x, float y);

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 2.8.7)
cmake_minimum_required(VERSION 3.5.0)
find_package (Threads)
include_directories("${PROJECT_SOURCE_DIR}/../lib_projects/raknet/jni/RaknetSources")
add_subdirectory("${PROJECT_SOURCE_DIR}/../lib_projects/raknet/jni" "${CMAKE_CURRENT_BINARY_DIR}/raknet")
@@ -19,6 +19,7 @@ set(CompileFiles ../../src/main.cpp
../../src/client/IConfigListener.cpp
../../src/client/Minecraft.cpp
../../src/client/Options.cpp
../../src/client/Option.cpp
../../src/client/OptionsFile.cpp
../../src/client/OptionStrings.cpp
../../src/client/gamemode/GameMode.cpp
@@ -151,6 +152,9 @@ set(CompileFiles ../../src/main.cpp
../../src/world/level/tile/entity/TileEntity.cpp
../../src/world/level/tile/entity/FurnaceTileEntity.cpp
../../src/world/phys/HitResult.cpp)
message(${CMAKE_LIBRARY_ARCHITECTURE})
add_executable(mcpe_server ${CompileFiles})
target_link_libraries(mcpe_server raknet ${CMAKE_THREAD_LIBS_INIT})
target_include_directories(mcpe_server PUBLIC
"../../src/"
)

View File

@@ -4,10 +4,11 @@ include $(CLEAR_VARS)
LOCAL_MODULE := RakNet
MY_PREFIX := $(LOCAL_PATH)/RakNetSources/
MY_PREFIX := $(LOCAL_PATH)/RaknetSources/
MY_SOURCES := $(wildcard $(MY_PREFIX)*.cpp)
LOCAL_SRC_FILES += $(MY_SOURCES:$(MY_PREFIX)%=RakNetSources/%)
LOCAL_SRC_FILES += $(MY_SOURCES:$(MY_PREFIX)%=RaknetSources/%)
LOCAL_CFLAGS := -Wno-psabi $(LOCAL_CFLAGS)
LOCAL_CPPFLAGS += -frtti
include $(BUILD_STATIC_LIBRARY)

View File

@@ -5,13 +5,13 @@
#include <stdio.h> // RAKNET_DEBUG_PRINTF
#include "RakAssert.h"
#if defined(ANDROID)
#include <asm/io.h>
// <asm/io.h> not needed and unavailable on arm64
#elif defined(_WIN32) || defined(__CYGWIN__)
#include <io.h>
#elif !defined ( __APPLE__ ) && !defined ( __APPLE_CC__ ) && !defined ( __PPC__ ) && !defined ( __FreeBSD__ ) && !defined ( __S3E__ )
#include <sys/io.h>
// #elif !defined ( __APPLE__ ) && !defined ( __APPLE_CC__ ) && !defined ( __PPC__ ) && !defined ( __FreeBSD__ ) && !defined ( __S3E__ )
// #include <sys/io.h>
#endif

View File

@@ -124,7 +124,7 @@ static const unsigned int MAX_OFFLINE_DATA_LENGTH=400; // I set this because I l
#pragma warning(disable:4309) // 'initializing' : truncation of constant value
#endif
// Make sure highest bit is 0, so isValid in DatagramHeaderFormat is false
static const char OFFLINE_MESSAGE_DATA_ID[16]={0x00,0xFF,0xFF,0x00,0xFE,0xFE,0xFE,0xFE,0xFD,0xFD,0xFD,0xFD,0x12,0x34,0x56,0x78};
static const unsigned char OFFLINE_MESSAGE_DATA_ID[16]={0x00,0xFF,0xFF,0x00,0xFE,0xFE,0xFE,0xFE,0xFD,0xFD,0xFD,0xFD,0x12,0x34,0x56,0x78};
struct PacketFollowedByData
{

View File

@@ -1,8 +1,8 @@
#if defined(X360__)
#elif defined (_WIN32)
#include <WinSock2.h>
#include <winsock2.h>
#include <windows.h>
#include <Ws2tcpip.h>
#include <ws2tcpip.h>
// Must always include Winsock2.h before windows.h
// or else:

26
src/App.cpp Normal file
View File

@@ -0,0 +1,26 @@
#include "App.hpp"
#include "IPlatform.hpp"
#include "platform/server/PlatformServer.hpp"
#include "platform/glfw/PlatformGlfw.hpp"
std::unique_ptr<IPlatform> App::CreatePlatform() {
#if defined(STANDALONE_SERVER)
return std::make_unique<PlatformServer>();
#elif defined(PLATFORM_DESKTOP)
return std::make_unique<PlatformGlfw>();
#else
static_assert(false, "Unsupported platform!");
#endif
}
void App::run() {
init();
m_platform->runMainLoop(*this);
}
void App::swapBuffers() {
m_platform->swapBuffers();
}

View File

@@ -1,87 +0,0 @@
#ifndef APP_H__
#define APP_H__
#ifdef __APPLE__
#define NO_EGL
#endif
#ifdef STANDALONE_SERVER
#define NO_EGL
#endif
#include "AppPlatform.h"
#ifndef NO_EGL
#include <EGL/egl.h>
#endif
#include "platform/log.h"
typedef struct AppContext {
#ifndef NO_EGL
EGLDisplay display;
EGLContext context;
EGLSurface surface;
#endif
AppPlatform* platform;
bool doRender;
} AppContext;
class App
{
public:
App()
: _finished(false),
_inited(false)
{
_context.platform = 0;
}
virtual ~App() {}
void init(AppContext& c) {
_context = c;
init();
_inited = true;
}
bool isInited() { return _inited; }
virtual AppPlatform* platform() { return _context.platform; }
void onGraphicsReset(AppContext& c) {
_context = c;
onGraphicsReset();
}
virtual void audioEngineOn () {}
virtual void audioEngineOff() {}
virtual void destroy() {}
virtual void loadState(void* state, int stateSize) {}
virtual bool saveState(void** state, int* stateSize) { return false; }
void swapBuffers() {
#ifndef NO_EGL
if (_context.doRender)
eglSwapBuffers(_context.display, _context.surface);
#endif
}
virtual void draw() {}
virtual void update() {};// = 0;
virtual void setSize(int width, int height) {}
virtual void quit() { _finished = true; }
virtual bool wantToQuit() { return _finished; }
virtual bool handleBack(bool isDown) { return false; }
protected:
virtual void init() {}
//virtual void onGraphicsLost() = 0;
virtual void onGraphicsReset() = 0;
private:
bool _inited;
bool _finished;
AppContext _context;
};
#endif//APP_H__

71
src/App.hpp Executable file
View File

@@ -0,0 +1,71 @@
#pragma once
#include <memory>
#ifdef __APPLE__
#define NO_EGL
#endif
#ifdef STANDALONE_SERVER
#define NO_EGL
#endif
#include <IPlatform.hpp>
#ifndef NO_EGL
#include <EGL/egl.h>
#endif
// typedef struct AppContext {
// #ifndef NO_EGL
// EGLDisplay display;
// EGLContext context;
// EGLSurface surface;
// #endif
// AppPlatform* platform;
// bool doRender;
// } AppContext;
class App {
protected:
std::unique_ptr<IPlatform> m_platform;
public:
static std::unique_ptr<IPlatform> CreatePlatform();
App(std::unique_ptr<IPlatform> platform) : m_platform(std::move(platform)), m_finished(false), m_inited(false) {}
App() = delete;
virtual ~App() {}
void run();
bool isInited() { return m_inited; }
virtual void audioEngineOn () {}
virtual void audioEngineOff() {}
virtual void destroy() {}
virtual void loadState(void* state, int stateSize) {}
virtual bool saveState(void** state, int* stateSize) { return false; }
void swapBuffers();
// {
// #ifndef NO_EGL
// if (_context.doRender)
// eglSwapBuffers(_context.display, _context.surface);
// #endif
// m_platform->swapBuffers();
// }
virtual void update() = 0;
virtual void quit() { m_finished = true; }
virtual bool wantToQuit() { return m_finished; }
virtual bool handleBack(bool isDown) { return false; }
protected:
virtual void init() { m_inited = true;}
private:
bool m_inited = false;
bool m_finished = false;
};

View File

@@ -1,10 +0,0 @@
#ifndef _MINECRAFT_APPCONSTANTS_H_
#define _MINECRAFT_APPCONSTANTS_H_
#define APP_VERSION_STRING "Demo"
#define APP_NAME "Minecraft - Pocket Edition " APP_VERSION_STRING
#endif

View File

@@ -1,143 +0,0 @@
#ifndef APPPLATFORM_H__
#define APPPLATFORM_H__
#include <vector>
#include <string>
#include <cstring>
#include "client/renderer/TextureData.h"
typedef std::vector<std::string> StringVector;
/*
typedef struct UserInput
{
static const int STATUS_INVALID = -1;
static const int STATUS_NOTINITED = -2;
static const int STATUS_OK = 1;
static const int STATUS_CANCEL = 0;
UserInput(int id)
: _id(id),
status(STATUS_NOTINITED)
{}
UserInput(int id, int status)
: _id(id),
status(status)
{}
int getId() { return _id; }
int status;
private:
int _id;
} UserInput;
class UserInputStatus {
int _status;
public:
UserInputStatus(int status)
: _status(status)
{}
bool isAnswered() { return _status >= 0; }
bool isOk() { return _status == UserInput::STATUS_OK; }
bool isCancel() { return _status == UserInput::STATUS_CANCEL; }
};
*/
class BinaryBlob {
public:
BinaryBlob()
: data(NULL),
size(-1) {}
BinaryBlob(unsigned char* data, unsigned int size)
: data(data),
size(size) {}
unsigned char* data;
int size;
};
class PlatformStringVars {
public:
static const int DEVICE_BUILD_MODEL = 0;
};
class AppPlatform
{
public:
AppPlatform() : keyboardVisible(false) {}
virtual ~AppPlatform() {}
virtual void saveScreenshot(const std::string& filename, int glWidth, int glHeight) {}
virtual TextureData loadTexture(const std::string& filename_, bool textureFolder) { return TextureData(); }
virtual void playSound(const std::string& fn, float volume, float pitch) {}
virtual void showDialog(int dialogId) {}
virtual void createUserInput() {}
bool is_big_endian(void) {
union {
unsigned int i;
char c[4];
} bint = {0x01020304};
return bint.c[0] == 1;
}
void createUserInput(int dialogId)
{
showDialog(dialogId);
createUserInput();
}
virtual int getUserInputStatus() { return 0; }
virtual StringVector getUserInput() { return StringVector(); }
virtual std::string getDateString(int s) { return ""; }
//virtual void createUserInputScreen(const char* types) {}
virtual int checkLicense() { return 0; }
virtual bool hasBuyButtonWhenInvalidLicense() { return false; }
virtual void uploadPlatformDependentData(int id, void* data) {}
virtual BinaryBlob readAssetFile(const std::string& filename) { return BinaryBlob(); }
virtual void _tick() {}
virtual int getScreenWidth() { return 854; }
virtual int getScreenHeight() { return 480; }
virtual float getPixelsPerMillimeter() { return 10; }
virtual bool isNetworkEnabled(bool onlyWifiAllowed) { return true; }
virtual bool isPowerVR() {
return false;
}
virtual int getKeyFromKeyCode(int keyCode, int metaState, int deviceId) {return 0;}
#ifdef __APPLE__
virtual bool isSuperFast() = 0;
#endif
virtual void buyGame() {}
virtual void finish() {}
virtual bool supportsTouchscreen() { return false; }
virtual void vibrate(int milliSeconds) {}
virtual std::string getPlatformStringVar(int stringId) {
return "<getPlatformStringVar NotImplemented>";
}
virtual void showKeyboard() {
keyboardVisible = true;
}
virtual void hideKeyboard() {
keyboardVisible = false;
}
virtual bool isKeyboardVisible() {return keyboardVisible;}
protected:
bool keyboardVisible;
};
#endif /*APPPLATFORM_H__*/

View File

@@ -1,12 +0,0 @@
#include "AppPlatform_glfw.h"
float AppPlatform_glfw::getPixelsPerMillimeter() {
GLFWmonitor* monitor = glfwGetPrimaryMonitor();
int width_mm, height_mm;
glfwGetMonitorPhysicalSize(monitor, &width_mm, &height_mm);
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
return (float)mode->width / (float)width_mm;
}

View File

@@ -1,129 +0,0 @@
#ifndef APPPLATFORM_GLFW_H__
#define APPPLATFORM_GLFW_H__
#include "AppPlatform.h"
#include "platform/log.h"
#include "client/renderer/gles.h"
#include "world/level/storage/FolderMethods.h"
#include <png.h>
#include <cmath>
#include <fstream>
#include <sstream>
#include <GLFW/glfw3.h>
static void png_funcReadFile(png_structp pngPtr, png_bytep data, png_size_t length) {
((std::istream*)png_get_io_ptr(pngPtr))->read((char*)data, length);
}
class AppPlatform_glfw: public AppPlatform
{
public:
AppPlatform_glfw()
{
}
BinaryBlob readAssetFile(const std::string& filename) {
FILE* fp = fopen(("data/" + filename).c_str(), "r");
if (!fp)
return BinaryBlob();
int size = getRemainingFileSize(fp);
BinaryBlob blob;
blob.size = size;
blob.data = new unsigned char[size];
fread(blob.data, 1, size, fp);
fclose(fp);
return blob;
}
void saveScreenshot(const std::string& filename, int glWidth, int glHeight) {
//@todo
}
__inline unsigned int rgbToBgr(unsigned int p) {
return (p & 0xff00ff00) | ((p >> 16) & 0xff) | ((p << 16) & 0xff0000);
}
TextureData loadTexture(const std::string& filename_, bool textureFolder)
{
TextureData out;
std::string filename = textureFolder? "data/images/" + filename_
: filename_;
std::ifstream source(filename.c_str(), std::ios::binary);
if (source) {
png_structp pngPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!pngPtr)
return out;
png_infop infoPtr = png_create_info_struct(pngPtr);
if (!infoPtr) {
png_destroy_read_struct(&pngPtr, NULL, NULL);
return out;
}
// Hack to get around the broken libpng for windows
png_set_read_fn(pngPtr,(void*)&source, png_funcReadFile);
png_read_info(pngPtr, infoPtr);
// Set up the texdata properties
out.w = png_get_image_width(pngPtr, infoPtr);
out.h = png_get_image_height(pngPtr, infoPtr);
png_bytep* rowPtrs = new png_bytep[out.h];
out.data = new unsigned char[4 * out.w * out.h];
out.memoryHandledExternally = false;
int rowStrideBytes = 4 * out.w;
for (int i = 0; i < out.h; i++) {
rowPtrs[i] = (png_bytep)&out.data[i*rowStrideBytes];
}
png_read_image(pngPtr, rowPtrs);
// Teardown and return
png_destroy_read_struct(&pngPtr, &infoPtr,(png_infopp)0);
delete[] (png_bytep)rowPtrs;
source.close();
return out;
}
else
{
LOGI("Couldn't find file: %s\n", filename.c_str());
return out;
}
}
std::string getDateString(int s) {
std::stringstream ss;
ss << s << " s (UTC)";
return ss.str();
}
virtual int checkLicense() {
static int _z = 0;//20;
_z--;
if (_z < 0) return 0;
//if (_z < 0) return 107;
return -2;
}
virtual int getScreenWidth() { return 854; };
virtual int getScreenHeight() { return 480; };
virtual float getPixelsPerMillimeter();
virtual bool supportsTouchscreen() { return true; }
virtual bool hasBuyButtonWhenInvalidLicense() { return false; }
private:
};
#endif /*APPPLATFORM_GLFW_H__*/

View File

@@ -1,5 +1,4 @@
#ifndef EGLCONFIGPRINTER_H__
#define EGLCONFIGPRINTER_H__
#pragma once
#include <cstdio>
#include <string>
@@ -122,4 +121,3 @@ public:
}
};
#endif /*EGLCONFIGPRINTER_H__*/

View File

@@ -1,13 +0,0 @@
#ifndef ERRORCODES_H__
#define ERRORCODES_H__
namespace ErrorCodes {
enum Enum {
Unknown,
ContainerRefStillExistsAfterDestruction
};
}
#endif /*ERRORCODES_H__*/

14
src/IPlatform.cpp Normal file
View File

@@ -0,0 +1,14 @@
#include <IPlatform.hpp>
#include <App.hpp>
#include <fstream>
void IPlatform::runMainLoop(App& app) {
while(!app.wantToQuit()) app.update();
}
ByteVector IPlatform::readAssetFile(const std::string& path) {
std::ifstream instream(path, std::ios::in | std::ios::binary);
std::vector<uint8_t> data((std::istreambuf_iterator<char>(instream)), std::istreambuf_iterator<char>());
return data;
}

81
src/IPlatform.hpp Executable file
View File

@@ -0,0 +1,81 @@
#pragma once
#include <vector>
#include <string>
#include "client/renderer/TextureData.hpp"
#include <cstdint>
typedef std::vector<std::string> StringVector;
typedef std::vector<uint8_t> ByteVector;
class App;
class IPlatform {
public:
IPlatform() : keyboardVisible(false), windowSizeChanged(false), m_targetFrametime(0.f) {}
virtual ~IPlatform() {}
virtual bool init() { return true; }
virtual void swapBuffers() {}
virtual void runMainLoop(App& app);
virtual ByteVector readAssetFile(const std::string& path);
// Mojang functions here
virtual TextureData loadTexture(const std::string& filename_, bool textureFolder) { return TextureData(); }
virtual TextureData loadTextureFromMemory(const unsigned char* data, size_t size) { return TextureData(); }
virtual void playSound(const std::string& fn, float volume, float pitch) {}
virtual void hideCursor(bool hide) {}
virtual std::string getDateString(int s) = 0;
virtual void uploadPlatformDependentData(int id, void* data) {}
// virtual BinaryBlob readAssetFile(const std::string& filename) { return BinaryBlob(); }
virtual void _tick() {}
virtual int getScreenWidth() { return 854; }
virtual int getScreenHeight() { return 480; }
virtual float getPixelsPerMillimeter() { return 10; }
virtual bool isNetworkEnabled(bool onlyWifiAllowed) { return true; }
virtual bool isPowerVR() {
return false;
}
virtual int getKeyFromKeyCode(int keyCode, int metaState, int deviceId) {return 0;}
#ifdef __APPLE__
virtual bool isSuperFast() = 0;
#endif
virtual void openURL(const std::string& url) {}
virtual void finish() {}
virtual bool supportsTouchscreen() { return false; }
virtual void vibrate(int milliSeconds) {}
virtual std::string getPlatformStringVar(int stringId) = 0;
virtual void showKeyboard() { keyboardVisible = true; }
virtual void hideKeyboard() { keyboardVisible = false; }
virtual bool isKeyboardVisible() { return keyboardVisible; }
virtual void setTargetFPS(int fps) { m_targetFrametime = 1.0 / fps; }
bool isWindowSizeChanged() { return windowSizeChanged; }
virtual void setVSync(bool on) { vsync = on; }
protected:
bool keyboardVisible;
bool windowSizeChanged;
bool vsync;
double m_targetFrametime;
};

View File

@@ -1,5 +1,4 @@
#ifndef LICENSECODES_H__
#define LICENSECODES_H__
#pragma once
class LicenseCodes
{

502
src/Minecraft.cpp Executable file
View File

@@ -0,0 +1,502 @@
#include <Minecraft.hpp>
#include "gamemode/CreativeMode.hpp"
#include "gamemode/SurvivalMode.hpp"
#include "gamemode/CreatorMode.hpp"
#include "world/entity/player/Player.hpp"
#include "world/item/Item.hpp"
#include "world/item/ItemInstance.hpp"
#include "world/item/crafting/Recipes.hpp"
#include "world/level/Level.hpp"
#include "world/level/tile/entity/TileEntity.hpp"
#include <string>
#include <cstdlib>
#include "client/gui/Screen.hpp"
#include "world/level/storage/ExternalFileLevelStorageSource.hpp"
#if defined(APPLE_DEMO_PROMOTION)
#define NO_NETWORK
#endif
#if defined(RPI)
#define CREATORMODE
#endif
#include "network/RakNetInstance.hpp"
#include "network/ClientSideNetworkHandler.hpp"
#include "network/ServerSideNetworkHandler.hpp"
//#include "network/Packet.hpp"
#include "world/entity/player/Inventory.hpp"
#include "world/level/tile/Tile.hpp"
#include "world/level/storage/LevelStorageSource.hpp"
#include "world/level/storage/LevelStorage.hpp"
#include "world/level/chunk/ChunkSource.hpp"
#include "platform/CThread.hpp"
#include <IPlatform.hpp>
#include "util/PerfTimer.hpp"
#include "util/PerfRenderer.hpp"
#include "world/entity/MobFactory.hpp"
#include "world/level/MobSpawner.hpp"
#include "util/Mth.hpp"
#include "world/entity/MobCategory.hpp"
#include "server/ServerLevel.hpp"
#ifdef CREATORMODE
#include "server/CreatorLevel.hpp"
#endif
#include "network/command/CommandServer.hpp"
/*static*/
const char* Minecraft::progressMessages[] = {
"Locating server",
"Building terrain",
"Preparing",
"Saving chunks"
};
// int Minecraft::customDebugId = Minecraft::CDI_NONE;
bool Minecraft::_hasInitedStatics = false;
#if defined(_MSC_VER)
#pragma warning( disable : 4355 ) // 'this' pointer in initialization list which is perfectly legal
#endif
// Minecraft::Minecraft() :
// #ifdef __APPLE__
// _isSuperFast(false),
// #endif
// #if defined(NO_NETWORK)
// raknetInstance = new IRakNetInstance();
// #else
// raknetInstance = new RakNetInstance();
// #endif
// #ifndef STANDALONE_SERVER
// soundEngine = new SoundEngine(20.0f);
// soundEngine->init(this, &options);
// #endif
// //setupPieces();
// #if defined(ANDROID) || defined(__APPLE__) || defined(RPI)
// signal(SIGPIPE, SIG_IGN);
// #endif
// externalCacheStoragePath = '.';
// externalCacheStoragePath = '.';
// }
Minecraft::~Minecraft() {
delete netCallback;
delete raknetInstance;
delete gameMode;
if (level != NULL) {
level->saveGame();
if (level->getChunkSource())
level->getChunkSource()->saveAll(true);
delete level->getLevelStorage();
delete level;
level = NULL;
}
//delete player;
delete storageSource;
delete _commandServer;
MobFactory::clearStaticTestMobs();
// Note: Don't tear down statics if we run on Android
// (we might change this in the future)
#ifndef ANDROID
Biome::teardownBiomes();
Item ::teardownItems();
Tile ::teardownTiles();
Material::teardownMaterials();
Recipes ::teardownRecipes();
TileEntity::teardownTileEntities();
#endif
}
// Only called by server
void Minecraft::selectLevel( const std::string& levelId, const std::string& levelName, const LevelSettings& settings ) {
level = (Level*)new ServerLevel(
storageSource->selectLevel(levelId, false),
levelName,
settings,
SharedConstants::GeneratorVersion
);
// note: settings is useless beyond this point, since it's
// either copied to LevelData (or LevelData read from file)
setLevel(level, "Generating level");
setIsCreativeMode(level->getLevelData()->getGameType() == GameType::Creative);
_running = true;
}
void Minecraft::setLevel(Level* level, const std::string& message, Player* forceInsertPlayer) {
LOGI("Seed is %ld\n", level->getSeed());
if (level != NULL) {
level->raknetInstance = raknetInstance;
gameMode->initLevel(level);
this->level = level;
_hasSignaledGeneratingLevelFinished = false;
#ifdef STANDALONE_SERVER
const bool threadedLevelCreation = false;
#else
const bool threadedLevelCreation = true;
#endif
if (threadedLevelCreation) {
// Threaded
// "Lock"
isGeneratingLevel = true;
generateLevelThread = new CThread(Minecraft::prepareLevel_tspawn, this);
} else {
// Non-threaded
generateLevel("Currently not used", level);
}
}
this->lastTickTime = 0;
this->_running = true;
}
void Minecraft::prepareLevel(const std::string& title) {
LOGI("status: 1\n");
progressStageStatusId = 1;
Stopwatch A, B, C, D;
A.start();
Stopwatch L;
// Dont update lights if we load the level (ok, actually just with leveldata version=1.+(?))
if (!level->isNew())
level->setUpdateLights(false);
int Max = CHUNK_CACHE_WIDTH * CHUNK_CACHE_WIDTH;
int pp = 0;
for (int x = 8; x < (CHUNK_CACHE_WIDTH * CHUNK_WIDTH); x += CHUNK_WIDTH) {
for (int z = 8; z < (CHUNK_CACHE_WIDTH * CHUNK_WIDTH); z += CHUNK_WIDTH) {
progressStagePercentage = 100 * pp++ / Max;
//printf("level generation progress %d\n", progressStagePercentage);
B.start();
level->getTile(x, 64, z);
B.stop();
L.start();
if (level->isNew())
while (level->updateLights())
;
L.stop();
}
}
A.stop();
level->setUpdateLights(true);
C.start();
for (int x = 0; x < CHUNK_CACHE_WIDTH; x++)
{
for (int z = 0; z < CHUNK_CACHE_WIDTH; z++)
{
LevelChunk* chunk = level->getChunk(x, z);
if (chunk && !chunk->createdFromSave)
{
chunk->unsaved = false;
chunk->clearUpdateMap();
}
}
}
C.stop();
LOGI("status: 3\n");
progressStageStatusId = 3;
if (level->isNew()) {
level->setInitialSpawn(); // @note: should obviously be called from Level itself
level->saveLevelData();
level->getChunkSource()->saveAll(false);
level->saveGame();
} else {
level->saveLevelData();
level->loadEntities();
}
progressStagePercentage = -1;
progressStageStatusId = 2;
LOGI("status: 2\n");
D.start();
level->prepare();
D.stop();
A.print("Generate level: ");
L.print(" - light: ");
B.print(" - getTl: ");
C.print(" - clear: ");
D.print(" - prepr: ");
progressStageStatusId = 0;
}
void Minecraft::update() {
timer.advanceTime();
raknetInstance->runEvents(netCallback);
TIMER_PUSH("tick");
int toTick = timer.ticks;
timer.ticks = 0;
for (int i = 0; i < toTick; ++i, ++ticks) tick(i, toTick-1);
TIMER_POP_PUSH("updatelights");
{
if (level && !isGeneratingLevel) {
level->updateLights();
}
}
TIMER_POP();
// Restart the server if (our modded) RakNet reports an error
if (level && raknetInstance->isProbablyBroken() && raknetInstance->isServer()) {
restartServer();
}
}
void Minecraft::restartServer() {
if (!level) return;
raknetInstance->resetIsBroken();
hostMultiplayer();
if (netCallback) netCallback->levelGenerated(level);
}
void Minecraft::tick(int nTick, int maxTick) {
if (missTime > 0) missTime--;
TIMER_PUSH("gameMode");
if (level) {
gameMode->tick();
}
TIMER_POP_PUSH("commandServer");
if (level && _commandServer) {
_commandServer->tick();
}
//
// Ongoing level generation in a (perhaps) different thread. When it's
// ready, _levelGenerated() is called once and any threads are deleted.
//
if (isGeneratingLevel) {
return;
} else if (!_hasSignaledGeneratingLevelFinished) {
if (generateLevelThread) {
delete generateLevelThread;
generateLevelThread = NULL;
}
_levelGenerated();
}
//
// Normal game loop, run before or efter level generation
//
if (level != NULL) {
TIMER_POP_PUSH("level");
level->tickEntities();
level->tick();
}
TIMER_POP();
}
bool Minecraft::isOnlineClient() {
return false;
}
bool Minecraft::isOnline() {
return netCallback != NULL;
}
void Minecraft::init()
{
// WHY DO WE NEED THIS ON MODERN PLATFORMS :sob:
// Global initialization goes here
Mth::initMth();
if (raknetInstance != nullptr) {
delete raknetInstance;
}
raknetInstance = new RakNetInstance();
// If we're running Android, only initialize
// the first time class is instanced
#ifdef ANDROID
if (!_hasInitedStatics) {
_hasInitedStatics = true;
#endif
Material::initMaterials();
MobCategory::initMobCategories();
Tile::initTiles();
Item::initItems();
Biome::initBiomes();
TileEntity::initTileEntities();
#ifdef ANDROID
}
#endif
setIsCreativeMode(false); // false means it's Survival Mode
#if !defined(NO_STORAGE)
storageSource = new ExternalFileLevelStorageSource(externalStoragePath, externalCacheStoragePath);
#else
storageSource = new MemoryLevelStorageSource();
#endif
// Server-only featire @todo server class app
hostMultiplayer();
}
//
// Multiplayer
//
void Minecraft::hostMultiplayer(int port) {
// Tear down last instance
raknetInstance->disconnect();
delete netCallback;
netCallback = nullptr;
#if !defined(NO_NETWORK)
netCallback = new ServerSideNetworkHandler(this, raknetInstance);
#endif
}
//
// Level generation
//
/*static*/
void* Minecraft::prepareLevel_tspawn(void *p_param) {
Minecraft* mc = (Minecraft*) p_param;
mc->generateLevel("Currently not used", mc->level);
return 0;
}
void Minecraft::generateLevel( const std::string& message, Level* level ) {
Stopwatch s;
s.start();
prepareLevel(message);
s.stop();
s.print("Level generated: ");
// "Unlock"
isGeneratingLevel = false;
}
void Minecraft::_levelGenerated() {
level->validateSpawn();
if (raknetInstance->isServer())
raknetInstance->announceServer(getServerName());
if (netCallback) {
netCallback->levelGenerated(level);
}
_hasSignaledGeneratingLevelFinished = true;
}
Player* Minecraft::respawnPlayer(int playerId) {
for (unsigned int i = 0; i < level->players.size(); ++i) {
if (level->players[i]->entityId == playerId) {
resetPlayer(level->players[i]);
return level->players[i];
}
}
return NULL;
}
void Minecraft::resetPlayer(Player* player) {
level->validateSpawn();
player->reset();
Pos p;
if(player->hasRespawnPosition()) {
p = player->getRespawnPosition();
}
else {
p = level->getSharedSpawnPos();
}
player->setPos((float)p.x + 0.5f, (float)p.y + 1.0f, (float)p.z + 0.5f);
player->resetPos(true);
if (isCreativeMode())
player->inventory->clearInventoryWithDefault();
}
int Minecraft::getProgressStatusId() {
return progressStageStatusId;
}
const char* Minecraft::getProgressMessage()
{
return progressMessages[progressStageStatusId];
}
bool Minecraft::isLevelGenerated()
{
return level != NULL && !isGeneratingLevel;
}
LevelStorageSource* Minecraft::getLevelSource()
{
return storageSource;
}
void Minecraft::setIsCreativeMode(bool isCreative)
{
#ifdef CREATORMODE
delete gameMode;
gameMode = new CreatorMode(this);
_isCreativeMode = true;
#else
if (!gameMode || isCreative != _isCreativeMode)
{
delete gameMode;
if (isCreative) gameMode = new CreativeMode(*this);
else gameMode = new SurvivalMode(*this);
_isCreativeMode = isCreative;
}
#endif
}
bool Minecraft::isCreativeMode() {
return _isCreativeMode;
}
ICreator* Minecraft::getCreator()
{
#ifdef CREATORMODE
return ((CreatorMode*)gameMode)->getCreator();
#else
return NULL;
#endif
}
void Minecraft::optionUpdated(OptionId option, bool value ) {
if(netCallback != NULL && option == OPTIONS_SERVER_VISIBLE) {
ServerSideNetworkHandler* ss = (ServerSideNetworkHandler*) netCallback;
ss->allowIncomingConnections(value);
}
}
void Minecraft::optionUpdated(OptionId option, float value ) {}
void Minecraft::optionUpdated(OptionId option, int value ) {}

138
src/Minecraft.hpp Executable file
View File

@@ -0,0 +1,138 @@
#pragma once
#include "client/Options.hpp"
#include "client/Timer.hpp"
//#include "../network/RakNetInstance.hpp"
#include "world/phys/HitResult.hpp"
#include "App.hpp"
#include <cstddef>
class Level;
class LocalPlayer;
class IInputHolder;
class Mob;
class Player;
class Entity;
class ICreator;
class GameMode;
class CThread;
class LevelStorageSource;
class BuildActionIntention;
class PerfRenderer;
class LevelSettings;
class IRakNetInstance;
class NetEventCallback;
class CommandServer;
struct PingedCompatibleServer;
class Minecraft: public App {
public:
using App::App;
virtual ~Minecraft();
virtual void init();
virtual void update();
virtual void restartServer();
virtual void tick(int nTick, int maxTick);
virtual bool isOnlineClient();
virtual bool isOnline();
virtual void setIsCreativeMode(bool isCreative);
virtual void optionUpdated(OptionId option, bool value);
virtual void optionUpdated(OptionId option, float value);
virtual void optionUpdated(OptionId option, int value);
/**
* @brief Get public name that will be listed in JoinGame menu
*/
virtual std::string getServerName() { return "Unknown"; }
void toggleDimension() {}
bool isCreativeMode();
virtual void selectLevel(const std::string& levelId, const std::string& levelName, const LevelSettings& settings);
virtual void setLevel(Level* level, const std::string& message = "", Player* forceInsertPlayer = NULL);
virtual void onBlockDestroyed(Player* player, int x, int y, int z, int face) {}
void generateLevel( const std::string& message, Level* level );
LevelStorageSource* getLevelSource();
virtual void hostMultiplayer(int port=19132);
Player* respawnPlayer(int playerId);
void respawnPlayer();
void resetPlayer(Player* player);
void doActuallyRespawnPlayer();
void prepareLevel(const std::string& message);
int getProgressStatusId();
const char* getProgressMessage();
ICreator* getCreator();
bool isLevelGenerated();
#ifdef __APPLE__
bool _isSuperFast = false;
bool isSuperFast() { return _isSuperFast; }
#endif
protected:
virtual void _levelGenerated();
private:
static void* prepareLevel_tspawn(void *p_param);
public:
Level* level = nullptr;
CommandServer* _commandServer = nullptr;
GameMode* gameMode = nullptr;
IRakNetInstance* raknetInstance = nullptr;
NetEventCallback* netCallback = nullptr;
int commandPort = 4711;
int lastTime = 0;
int lastTickTime = -1;
int missTime = 0;
int ticks = 0;
CThread* generateLevelThread = nullptr;
// static int customDebugId;
HitResult hitResult;
volatile int progressStagePercentage = 0;
// This field is initialized in main()
// It sets the base path to where worlds can be written (sdcard on android)
std::string externalStoragePath;
std::string externalCacheStoragePath;
protected:
Timer timer{20};
// @note @attn @warn: this is dangerous as fuck!
volatile bool isGeneratingLevel = false;
bool _hasSignaledGeneratingLevelFinished = true;
LevelStorageSource* storageSource;
bool _running;
protected:
volatile int progressStageStatusId = 0;
static const char* progressMessages[];
int _licenseId;
bool _isCreativeMode;
Player* _pendingRemovePlayer; // @attn @todo @fix: remove this shait and fix the respawn behaviour
// from NinecraftApp
bool _verbose = true;
int _lastTickMs = 0;
static bool _hasInitedStatics;
};

1258
src/MinecraftClient.cpp Normal file

File diff suppressed because it is too large Load Diff

142
src/MinecraftClient.hpp Normal file
View File

@@ -0,0 +1,142 @@
#pragma once
#include "client/gui/Font.hpp"
#include "client/gui/Screen.hpp"
#include "client/particle/ParticleEngine.hpp"
#include "client/player/LocalPlayer.hpp"
#include "client/renderer/GameRenderer.hpp"
#include "client/renderer/Textures.hpp"
#include "client/sound/SoundEngine.hpp"
#include <Minecraft.hpp>
#include <client/MouseHandler.hpp>
#include <client/gui/Gui.hpp>
#include <client/gui/screens/ScreenChooser.hpp>
#include <client/PixelCalc.hpp>
#include <client/renderer/LevelRenderer.hpp>
class MinecraftClient : public Minecraft {
public:
using Minecraft::Minecraft;
~MinecraftClient();
void init() override;
void update() override;
void setSize(int width, int height);
void reloadOptions();
bool supportNonTouchScreen();
bool useTouchscreen();
void grabMouse();
void releaseMouse();
void setScreen(Screen*);
void leaveGame(bool renameLevel = false);
void setLevel(Level* level, const std::string& message = "", Player* forceInsertPlayer = NULL) override;
void updateStats();
void restartServer() override;
bool handleBack(bool isDown) override;
void onGraphicsReset();
void initGLStates();
void tick(int nTick, int maxTick) override;
void tickInput();
void handleBuildAction(BuildActionIntention* action);
bool isOnlineClient() override;
void pauseGame(bool isBackPaused);
void gameLostFocus();
void respawnPlayer();
void audioEngineOn() override;
void audioEngineOff() override;
void setIsCreativeMode(bool isCreative) override;
void optionUpdated(OptionId option, bool value) override;
void optionUpdated(OptionId option, float value) override;
void optionUpdated(OptionId option, int value) override;
LocalPlayer* getPlayer() { return player; }
Font* getFont() { return font; }
Textures& textures() { return m_textures; }
Options& options() { return m_options;}
Screen* getScreen() { return m_screen; }
Gui& gui() { return m_gui; }
ParticleEngine* getParticleEngine() {return particleEngine; }
int getScreenWidth() { return width; }
int getScreenHeigth() { return height; }
virtual void hostMultiplayer(int port) override;
bool isPowerVR() { return _powerVr; }
bool isKindleFire(int kindleVersion);
bool transformResolution(int* w, int* h);
virtual std::string getServerName() override;
void locateMultiplayer();
void cancelLocateMultiplayer();
bool joinMultiplayer(const PingedCompatibleServer& server);
bool joinMultiplayerFromString(const std::string& server);
void onBlockDestroyed(Player* player, int x, int y, int z, int face) override;
protected:
void _reloadInput();
void _levelGenerated() override;
int width = 1, height = 1;
Font* font = nullptr;
// @warn This is unsafe cuz Gui may call some MinecraftClient method while MinecraftClient is not ready
MouseHandler mouseHandler;
LevelRenderer* levelRenderer = nullptr;
GameRenderer* gameRenderer = nullptr;
ParticleEngine* particleEngine = nullptr;
SoundEngine* soundEngine = nullptr;
PerfRenderer* _perfRenderer = nullptr;
bool mouseGrabbed = false;
PixelCalc pixelCalc;
PixelCalc pixelCalcUi;
Screen* m_screen = nullptr;
bool screenMutex = false;
bool hasScheduledScreen = false;
Screen* scheduledScreen = nullptr;
int m_frames = 0;
volatile bool pause = false;
// @todo make static
LocalPlayer* player = nullptr;
IInputHolder* inputHolder = nullptr;
Mob* cameraTargetPlayer = nullptr;
bool _supportsNonTouchscreen = false;
bool isLookingForMultiplayer = false;
bool _powerVr = false;
Options m_options{*this};
Textures m_textures{m_options, *m_platform};
ScreenChooser screenChooser{*this};
Gui m_gui{*this};
};

15
src/MinecraftServer.cpp Normal file
View File

@@ -0,0 +1,15 @@
#include "MinecraftServer.hpp"
#include <Minecraft.hpp>
#include <network/RakNetInstance.hpp>
void MinecraftServer::hostMultiplayer(int port) {
Minecraft::hostMultiplayer(port);
raknetInstance->host("Server", port, 16);
}
std::string MinecraftServer::getServerName() {
// @todo read server name from config
return "Dedicated server 0.6.1";
}

10
src/MinecraftServer.hpp Normal file
View File

@@ -0,0 +1,10 @@
#pragma once
#include <Minecraft.hpp>
class MinecraftServer : public Minecraft {
public:
using Minecraft::Minecraft;
void hostMultiplayer(int port) override;
std::string getServerName() override;
};

View File

@@ -1,419 +0,0 @@
#include "NinecraftApp.h"
//#include <EGL/egl.h>
#ifdef RPI
//#define NO_STORAGE
#endif
#include <errno.h>
#include "platform/input/Mouse.h"
#include "platform/input/Multitouch.h"
#include "world/item/Item.h"
#include "world/level/Level.h"
#include "world/level/biome/Biome.h"
#include "world/level/material/Material.h"
#include "world/entity/MobCategory.h"
//#include "world/level/storage/FolderMethods.h"
#ifndef STANDALONE_SERVER
#include "client/gui/screens/StartMenuScreen.h"
#endif
#include "client/player/LocalPlayer.h"
#ifndef STANDALONE_SERVER
#include "client/renderer/gles.h"
#include "client/renderer/Chunk.h"
#include "client/renderer/LevelRenderer.h"
#include "client/renderer/Tesselator.h"
#endif
// sorry for raknet dependency, but I'm too lazy to find another getTime method
#include "raknet/GetTime.h"
#include "network/RakNetInstance.h"
#include "network/ClientSideNetworkHandler.h"
#include "client/gui/screens/ProgressScreen.h"
//#include "world/entity/player/Inventory2.h"
#if !defined(DEMO_MODE) && !defined(APPLE_DEMO_PROMOTION) && !defined(NO_STORAGE)
#include "world/level/storage/ExternalFileLevelStorageSource.h"
#else
#include "world/level/storage/MemoryLevelStorageSource.h"
#endif
#ifndef STANDALONE_SERVER
#include "client/renderer/Textures.h"
#include "client/renderer/entity/ItemRenderer.h"
#endif
#include "world/item/crafting/Recipes.h"
#include "world/level/tile/entity/TileEntity.h"
#ifndef STANDALONE_SERVER
#include "client/renderer/EntityTileRenderer.h"
#endif
bool NinecraftApp::_hasInitedStatics = false;
NinecraftApp::NinecraftApp()
: _verbose(true),
_lastTickMs(0),
_frames(0)
{
#if defined(ANDROID) || defined(__APPLE__) || defined(RPI)
signal(SIGPIPE, SIG_IGN);
#endif
}
NinecraftApp::~NinecraftApp()
{
teardown();
}
void NinecraftApp::init()
{
// Global initialization goes here
Mth::initMth();
//#ifdef DEMO_MODE
//writeDemoFile();
//#endif
// If we're running Android, only initialize
// the first time class is instanced
#ifdef ANDROID
if (!_hasInitedStatics) {
_hasInitedStatics = true;
#endif
Material::initMaterials();
MobCategory::initMobCategories();
Tile::initTiles();
Item::initItems();
Biome::initBiomes();
TileEntity::initTileEntities();
#ifdef ANDROID
}
#endif
#ifndef STANDALONE_SERVER
initGLStates();
Tesselator::instance.init();
I18n::loadLanguage(platform(), "en_US");
#endif
Minecraft::init();
#if !defined(DEMO_MODE) && !defined(APPLE_DEMO_PROMOTION) && !defined(NO_STORAGE)
storageSource = new ExternalFileLevelStorageSource(externalStoragePath, externalCacheStoragePath);
#else
storageSource = new MemoryLevelStorageSource();
#endif
_running = false;
#ifndef STANDALONE_SERVER
LOGI("This: %p\n", this);
screenChooser.setScreen(SCREEN_STARTMENU);
#else
user->name = "Server";
hostMultiplayer();
#endif
}
void NinecraftApp::teardown()
{
// Note: Don't tear down statics if we run on Android
// (we might change this in the future)
#ifndef ANDROID
Biome::teardownBiomes();
Item ::teardownItems();
Tile ::teardownTiles();
Material::teardownMaterials();
Recipes ::teardownRecipes();
TileEntity::teardownTileEntities();
#endif
#ifdef WIN32
ItemRenderer::teardown_static();
if (EntityTileRenderer::instance != NULL) {
delete EntityTileRenderer::instance;
EntityTileRenderer::instance = NULL;
}
TileEntityRenderDispatcher::destroy();
#endif
}
void NinecraftApp::update()
{
++_frames;
// Generate Multitouch active pointer list
Multitouch::commit();
#ifndef ANDROID_PUBLISH
//testCreationAndDestruction();
//testJoiningAndDestruction();
#endif /*ANDROID_PUBLISH*/
Minecraft::update();
swapBuffers();
Mouse::reset2();
// Restart the server if (our modded) RakNet reports an error
if (level && raknetInstance->isProbablyBroken() && raknetInstance->isServer()) {
restartServer();
}
#ifndef WIN32
updateStats();
#endif
}
void NinecraftApp::updateStats()
{
#ifndef STANDALONE_SERVER
if (Options::debugGl)
LOGI("--------------------------------------------\n");
//*
int now = getTimeMs();
//int since = now - _lastTickMs;
if (now >= lastTime + 1000)
{
if (player) {
LOGI("%d fps \t%3d chunk updates. (%.2f, %.2f, %.2f)\n",
_frames, Chunk::updates, player->x, player->y, player->z);
Chunk::resetUpdates();
//static int _n = 0;
//if (++_n % 5 == -1) { // @note: -1
// static char filename[256];
// sprintf(filename, "%s/games/com.mojang/img_%.4d.jpg", externalStoragePath.c_str(), _n/5);
// _context.platform->saveScreenshot(filename, width, height);
//}
LOGI("%s", levelRenderer->gatherStats1().c_str());
//printf("Texture swaps (this frame): %d\n", Textures::textureChanges);
} else {
LOGI("%d fps\n", _frames);
}
//const int* pointerIds;
//int pointerCount = Multitouch::getActivePointerIds(&pointerIds);
//if (pointerCount) {
// std::string s = "Pointers (";
// s += (char)(48 + pointerCount);
// s += ": ";
// for (int i = 0; i < pointerCount; ++i) {
// s += (char)(48 + pointerIds[i]);
// s += ", ";
// }
// LOGI("%s\n", s.c_str());
//}
lastTime = now;
_frames = 0;
#ifdef GLDEBUG
while (1) {
int error = glGetError();
if (error == GL_NO_ERROR) break;
LOGI("#################### GL-ERROR: %d\t#####################\n", error);
LOGI("#################### GL-ERROR: %d\t#####################\n", error);
LOGI("#################### GL-ERROR: %d\t#####################\n", error);
}
#endif
}
Textures::textureChanges = 0;
/**/
#endif /* STANDALONE_SERVER */
}
void NinecraftApp::initGLStates()
{
#ifndef STANDALONE_SERVER
//glShadeModel2(GL_SMOOTH);
//glClearDepthf(1.0f);
glEnable2(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glDepthRangef(0, 1);
glEnable2(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0.1f);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glEnable2(GL_TEXTURE_2D);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
// Both updates isPowerVR flag in java and returns if the graphics chip is PowerVR SGX or not
_powerVr = platform()->isPowerVR();
#ifdef __APPLE__
_isSuperFast = platform()->isSuperFast();
#endif
//glLineWidth(4);
#endif /* STANDALONE_SERVER */
}
void NinecraftApp::restartServer() {
if (!level) return;
for (int i = level->players.size()-1; i >= 0; --i) {
Player* p = level->players[i];
if (p != player)
level->removeEntity(p);
}
raknetInstance->resetIsBroken();
#ifndef STANDALONE_SERVER
gui.addMessage("This server has restarted!");
#endif
hostMultiplayer();
if (netCallback) netCallback->levelGenerated(level);
}
bool NinecraftApp::handleBack(bool isDown)
{
if (isGeneratingLevel)
{
return true;
}
if (level)
{
if (!isDown)
{
if (screen)
{
if (!screen->handleBackEvent(isDown))
{
if (player->containerMenu) player->closeContainer();
setScreen(NULL);
}
return true;
} else {
pauseGame(true);
}
//leaveGame();
return false;
}
return true;
}
else if (screen)
{
return screen->handleBackEvent(isDown);
}
return false;
}
void NinecraftApp::onGraphicsReset()
{
#ifndef STANDALONE_SERVER
initGLStates();
Tesselator::instance.init();
Minecraft::onGraphicsReset();
#endif
}
#ifndef ANDROID_PUBLISH
static int _state = -1;
static int _stateTicksLeft = 0;
void NinecraftApp::testCreationAndDestruction()
{
if (_state == -1) {
_stateTicksLeft = 100;
_state = 0;
}
if (_state == 0) {
if (--_stateTicksLeft <= 0)
_state = 1;
}
else if (_state == 1) {
getLevelSource()->deleteLevel("perf");
int seed = getEpochTimeS();
LOGI(">seed %d\n", seed);
selectLevel("perf", "perf", LevelSettings(seed, GameType::Creative));
hostMultiplayer();
#ifndef STANDALONE_SERVER
setScreen(new ProgressScreen());
#endif
_state = 2;
_stateTicksLeft = 1000;//25000;//00;
}
else if (_state == 2) {
if (isLevelGenerated()) {
if (--_stateTicksLeft <= 0) {
_state = 3;
}
}
} else if (_state == 3) {
leaveGame();
_state = 1;
}
}
void NinecraftApp::testJoiningAndDestruction()
{
if (_state == -1) {
//LightUpdate sz[2] = { LightUpdate(LightLayer::Block, 0, 0, 0, 1, 1, 1),
// LightUpdate(LightLayer::Sky, 0, 0, 0, 1, 1, 1) };
//LOGI("size of lightupdate: %lu == %d\n", sizeof(LightUpdate), (const char*)&sz[1] - (const char*)&sz[0]);
_stateTicksLeft = 100;
_state = 0;
}
if (_state == 0) {
if (--_stateTicksLeft <= 0) {
raknetInstance->clearServerList();
locateMultiplayer();
_state = 1;
}
}
else if (_state == 1) {
if (!raknetInstance->getServerList().empty()) {
PingedCompatibleServer s = raknetInstance->getServerList().at(0);
if (s.name.GetLength() > 0) {
joinMultiplayer(s);
#ifndef STANDALONE_SERVER
setScreen(new ProgressScreen());
#endif
_state = 2;
_stateTicksLeft = 80;//1000;
}
}
}
else if (_state == 2) {
if (isLevelGenerated()) {
if (--_stateTicksLeft <= 0) {
_state = 3;
}
}
} else if (_state == 3) {
leaveGame();
_stateTicksLeft = 50;
_state = 0;
}
}
#endif /*ANDROID_PUBLISH*/
/*
void NinecraftApp::writeDemoFile() {
std::string path = externalStoragePath + "/games";
if (createFolderIfNotExists(path.c_str())) {
path += "/com.mojang";
if (createFolderIfNotExists(path.c_str())) {
path += "/minecraftpe";
if (createFolderIfNotExists(path.c_str())) {
path += "/played_demo";
FILE* fp = fopen(path.c_str(), "w");
if (fp) fclose(fp);
}}}
}
bool NinecraftApp::hasPlayedDemo() {
std::string filename = externalStoragePath + "/games/com.mojang/minecraftpe/played_demo";
FILE* fp = fopen(filename.c_str(), "r");
if (!fp) return false;
fclose(fp);
return true;
}
*/

View File

@@ -1,52 +0,0 @@
#ifndef NINECRAFTAPP_H__
#define NINECRAFTAPP_H__
#include "world/Pos.h"
#include "App.h"
#include "client/Minecraft.h"
#include "world/level/storage/MemoryLevelStorage.h"
#include <string>
class Level;
class LocalPlayer;
class ExternalFileLevelStorageSource;
class NinecraftApp: public Minecraft
{
public:
NinecraftApp();
~NinecraftApp();
void init();
void teardown();
void update();
virtual bool handleBack(bool isDown);
protected:
void onGraphicsReset();
private:
void initGLStates();
void restartServer();
void updateStats();
//void writeDemoFile();
//bool hasPlayedDemo();
#ifndef ANDROID_PUBLISH
void testCreationAndDestruction();
void testJoiningAndDestruction();
#endif /*ANDROID_PUBLISH*/
bool _verbose;
int _frames;
int _lastTickMs;
static bool _hasInitedStatics;
};
#endif//NINECRAFTAPP_H__

View File

@@ -1,4 +1,4 @@
#include "Performance.h"
#include "Performance.hpp"
/*static*/
StopwatchHandler Performance::watches;

View File

@@ -1,12 +0,0 @@
#ifndef PERFORMANCE_H__
#define PERFORMANCE_H__
#include "platform/time.h"
class Performance
{
public:
static StopwatchHandler watches;
};
#endif /*PERFORMANCE_H__*/

10
src/Performance.hpp Executable file
View File

@@ -0,0 +1,10 @@
#pragma once
#include "platform/time.hpp"
class Performance
{
public:
static StopwatchHandler watches;
};

View File

@@ -1,10 +1,16 @@
#include "SharedConstants.h"
#include "SharedConstants.hpp"
namespace Common {
std::string getGameVersionString(const std::string& versionSuffix /* = "" */)
{
return std::string("v0.6.1") + versionSuffix + " alpha";
std::string result = std::string("v0.6.1") + versionSuffix;
// append 64-bit port marker only on Android 64bit targets
#if defined(ANDROID) && (defined(__aarch64__) || defined(__x86_64__))
result += " (64-bit port)";
#endif
result += " alpha";
return result;
}
};

View File

@@ -1,5 +1,4 @@
#ifndef NET_MINECRAFT_SharedConstants_H__
#define NET_MINECRAFT_SharedConstants_H__
#pragma once
#include <string>
@@ -31,4 +30,3 @@ namespace SharedConstants
//int FULLBRIGHT_LIGHTVALUE = 15 << 20 | 15 << 4;
}
#endif /*NET_MINECRAFT_SharedConstants_H__*/

View File

@@ -1,7 +1,7 @@
#include "IConfigListener.h"
#include "Minecraft.h"
#include "IConfigListener.hpp"
#include "Minecraft.hpp"
#ifndef STANDALONE_SERVER
#include "gui/Gui.h"
#include "gui/Gui.hpp"
#endif /* STANDALONE_SERVER */
Config createConfig(Minecraft* mc) {
Config c;

View File

@@ -1,7 +1,6 @@
#ifndef CONFIGLISTENER_H__
#define CONFIGLISTENER_H__
#pragma once
#include "PixelCalc.h"
#include "PixelCalc.hpp"
class Minecraft;
class Options;
@@ -45,4 +44,3 @@ public:
virtual void onConfigChanged(const Config& config) = 0;
};
#endif /*CONFIGLISTENER_H__*/

View File

@@ -1,21 +0,0 @@
#ifndef NET_MINECRAFT_CLIENT__KeyMapping_H__
#define NET_MINECRAFT_CLIENT__KeyMapping_H__
//package net.minecraft.client;
#include <string>
class KeyMapping
{
public:
std::string name;
int key;
KeyMapping() {}
KeyMapping(const std::string& name_, int key_)
: name(name_),
key(key_)
{}
};
#endif /*NET_MINECRAFT_CLIENT__KeyMapping_H__*/

File diff suppressed because it is too large Load Diff

View File

@@ -1,230 +0,0 @@
#ifndef NET_MINECRAFT_CLIENT__Minecraft_H__
#define NET_MINECRAFT_CLIENT__Minecraft_H__
#include "Options.h"
#ifndef STANDALONE_SERVER
#include "MouseHandler.h"
#endif
#include "Timer.h"
#include "player/input/ITurnInput.h"
#ifndef STANDALONE_SERVER
#include "gui/Gui.h"
#include "gui/screens/ScreenChooser.h"
#endif
//#include "../network/RakNetInstance.h"
#include "../world/phys/HitResult.h"
class User;
class Level;
class LocalPlayer;
class IInputHolder;
class Mob;
class Player;
class LevelRenderer;
class GameRenderer;
class ParticleEngine;
class Entity;
class ICreator;
class GameMode;
class Textures;
class CThread;
class SoundEngine;
class Screen;
class Font;
class LevelStorageSource;
class BuildActionIntention;
class PerfRenderer;
class LevelSettings;
class IRakNetInstance;
class NetEventCallback;
class CommandServer;
struct PingedCompatibleServer;
//class ExternalFileLevelStorageSource;
#include "../App.h"
#include "PixelCalc.h"
class AppPlatform;
class AppPlatform_android;
class Minecraft: public App
{
protected:
Minecraft();
public:
virtual ~Minecraft();
void init();
void setSize(int width, int height);
void reloadOptions();
bool supportNonTouchScreen();
bool useTouchscreen();
void grabMouse();
void releaseMouse();
void handleBuildAction(BuildActionIntention*);
void toggleDimension(){}
bool isCreativeMode();
void setIsCreativeMode(bool isCreative);
void setScreen(Screen*);
virtual void selectLevel(const std::string& levelId, const std::string& levelName, const LevelSettings& settings);
virtual void setLevel(Level* level, const std::string& message = "", LocalPlayer* forceInsertPlayer = NULL);
void generateLevel( const std::string& message, Level* level );
LevelStorageSource* getLevelSource();
bool isLookingForMultiplayer;
void locateMultiplayer();
void cancelLocateMultiplayer();
bool joinMultiplayer(const PingedCompatibleServer& server);
void hostMultiplayer(int port=19132);
Player* respawnPlayer(int playerId);
void respawnPlayer();
void resetPlayer(Player* player);
void doActuallyRespawnPlayer();
void update();
void tick(int nTick, int maxTick);
void tickInput();
bool isOnlineClient();
bool isOnline();
void pauseGame(bool isBackPaused);
void gameLostFocus();
void prepareLevel(const std::string& message);
void leaveGame(bool renameLevel = false);
int getProgressStatusId();
const char* getProgressMessage();
ICreator* getCreator();
// void onGraphicsLost() {}
void onGraphicsReset();
bool isLevelGenerated();
int getLicenseId();
void audioEngineOn();
void audioEngineOff();
bool isPowerVR() { return _powerVr; }
bool isKindleFire(int kindleVersion);
bool transformResolution(int* w, int* h);
void optionUpdated(const Options::Option* option, bool value);
void optionUpdated(const Options::Option* option, float value);
void optionUpdated(const Options::Option* option, int value);
#ifdef __APPLE__
bool _isSuperFast;
bool isSuperFast() { return _isSuperFast; }
#endif
protected:
void _levelGenerated();
private:
static void* prepareLevel_tspawn(void *p_param);
void _reloadInput();
public:
int width;
int height;
// Vars that the platform is allowed to use in the future
int commandPort;
int reserved_d1, reserved_d2;
float reserved_f1, reserved_f2;
Options options;
static bool useAmbientOcclusion;
//static bool threadInterrupt;
volatile bool pause;
LevelRenderer* levelRenderer;
GameRenderer* gameRenderer;
ParticleEngine* particleEngine;
SoundEngine* soundEngine;
GameMode* gameMode;
#ifndef STANDALONE_SERVER
Textures* textures;
ScreenChooser screenChooser;
Font* font;
#endif
IRakNetInstance* raknetInstance;
NetEventCallback* netCallback;
int lastTime;
int lastTickTime;
float ticksSinceLastUpdate;
User* user;
Level* level;
LocalPlayer* player;
IInputHolder* inputHolder;
Mob* cameraTargetPlayer;
#ifndef STANDALONE_SERVER
Gui gui;
#endif
CThread* generateLevelThread;
Screen* screen;
static int customDebugId;
static const int CDI_NONE = 0;
static const int CDI_GRAPHICS = 1;
#ifndef STANDALONE_SERVER
MouseHandler mouseHandler;
#endif
bool mouseGrabbed;
PixelCalc pixelCalc;
PixelCalc pixelCalcUi;
HitResult hitResult;
volatile int progressStagePercentage;
// This field is initialized in main()
// It sets the base path to where worlds can be written (sdcard on android)
std::string externalStoragePath;
std::string externalCacheStoragePath;
protected:
Timer timer;
// @note @attn @warn: this is dangerous as fuck!
volatile bool isGeneratingLevel;
bool _hasSignaledGeneratingLevelFinished;
LevelStorageSource* storageSource;
bool _running;
bool _powerVr;
private:
volatile int progressStageStatusId;
static const char* progressMessages[];
int missTime;
int ticks;
bool screenMutex;
bool hasScheduledScreen;
Screen* scheduledScreen;
int _licenseId;
bool _supportsNonTouchscreen;
bool _isCreativeMode;
//int _respawnPlayerTicks;
Player* _pendingRemovePlayer; // @attn @todo @fix: remove this shait and fix the respawn behaviour
PerfRenderer* _perfRenderer;
CommandServer* _commandServer;
};
#endif /*NET_MINECRAFT_CLIENT__Minecraft_H__*/

View File

@@ -1,11 +1,11 @@
#include "MouseHandler.h"
#include "player/input/ITurnInput.h"
#include "MouseHandler.hpp"
#include "player/input/ITurnInput.hpp"
#ifdef RPI
#include <SDL/SDL.h>
#endif
#ifdef PLATFORM_GLFW
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
#include <GLFW/glfw3.h>
#endif
@@ -34,7 +34,7 @@ void MouseHandler::grab() {
SDL_ShowCursor(0);
#endif
#ifdef PLATFORM_GLFW
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
glfwSetInputMode(glfwGetCurrentContext(), GLFW_CURSOR, GLFW_CURSOR_DISABLED);
#endif
}
@@ -46,7 +46,7 @@ void MouseHandler::release() {
SDL_ShowCursor(1);
#endif
#ifdef PLATFORM_GLFW
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
glfwSetInputMode(glfwGetCurrentContext(), GLFW_CURSOR, GLFW_CURSOR_NORMAL);
#endif
}

View File

@@ -1,5 +1,4 @@
#ifndef NET_MINECRAFT_CLIENT__MouseHandler_H__
#define NET_MINECRAFT_CLIENT__MouseHandler_H__
#pragma once
//package net.minecraft.client;
@@ -25,4 +24,3 @@ private:
ITurnInput* _turnInput;
};
#endif /*NET_MINECRAFT_CLIENT__MouseHandler_H__*/

52
src/client/Option.cpp Normal file
View File

@@ -0,0 +1,52 @@
#include "Option.hpp"
#include <sstream>
#include <cstdio>
Option::~Option() {}
bool Option::parse_bool_like(const std::string& value, bool& out) {
if (value == "true" || value == "YES") {
out = true;
return true;
}
if (value == "false" || value == "NO") {
out = false;
return true;
}
return false;
}
bool OptionFloat::parse(const std::string& value) {
bool b;
if (parse_bool_like(value, b)) {
m_value = b ? 1.f : 0.f;
return true;
}
return sscanf(value.c_str(), "%f", &m_value) == 1;
}
bool OptionInt::parse(const std::string& value) {
bool b;
if (parse_bool_like(value, b)) {
m_value = b ? 1 : 0;
return true;
}
return sscanf(value.c_str(), "%d", &m_value) == 1;
}
bool OptionBool::parse(const std::string& value) {
if (value == "0") {
m_value = false;
return true;
}
if (value == "1") {
m_value = true;
return true;
}
return parse_bool_like(value, m_value);
}

107
src/client/Option.hpp Normal file
View File

@@ -0,0 +1,107 @@
#pragma once
#include <sstream>
#include <type_traits>
#include <util/Mth.hpp>
/*
template<typename T>
struct is_option_type : std::false_type {};
template<> struct is_option_type<bool> : std::true_type {};
template<> struct is_option_type<int> : std::true_type {};
template<> struct is_option_type<float> : std::true_type {};
template<> struct is_option_type<std::string> : std::true_type {};
template<typename T>
struct is_min_max_option : std::false_type {};
template<> struct is_min_max_option<int> : std::true_type {};
template<> struct is_min_max_option<float> : std::true_type {};
*/
class Option {
public:
Option(const std::string& key) : m_key("options." + key) {}
virtual ~Option();
const std::string& getStringId() { return m_key; }
virtual bool parse(const std::string& value) { return false; }
virtual std::string serialize() { return m_key + ":"; }
protected:
std::string m_key;
template<typename T>
std::string serialize_value(const T& value) const {
std::ostringstream ss;
ss << m_key << ":" << value;
return ss.str();
}
bool parse_bool_like(const std::string& value, bool& out);
};
class OptionFloat : public Option {
public:
OptionFloat(const std::string& key, float value = 0.f, float min = 0.f, float max = 1.f) :
Option(key), m_value(value), m_min(min), m_max(max) {}
float get() { return m_value; }
void set(float value) { m_value = Mth::clamp(value, m_min, m_max); }
float getMin() { return m_min; }
float getMax() { return m_max; }
virtual bool parse(const std::string& value);
virtual std::string serialize() { return serialize_value(m_value); }
private:
float m_value, m_min, m_max;
};
class OptionInt : public Option {
public:
OptionInt(const std::string& key, int value = 0, int min = -999999, int max = 999999) :
Option(key), m_value(value), m_min(min), m_max(max) {}
int get() { return m_value; }
void set(int value) { m_value = Mth::clamp(value, m_min, m_max); }
int getMin() { return m_min; }
int getMax() { return m_max; }
virtual bool parse(const std::string& value);
virtual std::string serialize() { return serialize_value(m_value); }
private:
int m_value, m_min, m_max;
};
class OptionBool : public Option {
public:
OptionBool(const std::string& key, bool value = false) : Option(key), m_value(value) {}
bool get() { return m_value; }
void set(int value) { m_value = value; }
void toggle() { m_value = !m_value; }
virtual bool parse(const std::string& value);
virtual std::string serialize() { return serialize_value(m_value); }
private:
bool m_value;
};
class OptionString : public Option {
public:
OptionString(const std::string& key, const std::string& str = "") : Option(key), m_value(str) {}
const std::string& get() { return m_value; }
void set(const std::string& value) { m_value = value; }
virtual bool parse(const std::string& value) { m_value = value; return true; }
virtual std::string serialize() { return m_key + ":" + m_value; }
private:
std::string m_value;
};

View File

@@ -1,16 +1,24 @@
#include "OptionStrings.h"
#include "OptionStrings.hpp"
const char* OptionStrings::Multiplayer_Username = "mp_username";
const char* OptionStrings::Multiplayer_ServerVisible = "mp_server_visible_default";
const char* OptionStrings::Graphics_Fancy = "gfx_fancygraphics";
const char* OptionStrings::Graphics_LowQuality = "gfx_lowquality";
const char* OptionStrings::Graphics_Vsync = "gfx_vsync";
const char* OptionStrings::Graphics_GUIScale = "gfx_guiscale";
const char* OptionStrings::Graphics_SmoothLightning = "gfx_smoothlightning";
const char* OptionStrings::Graphics_Anaglyph = "gfx_anaglyph";
const char* OptionStrings::Graphics_ViewBobbing = "gfx_viewbobbing";
const char* OptionStrings::Controls_Sensitivity = "ctrl_sensitivity";
const char* OptionStrings::Controls_InvertMouse = "ctrl_invertmouse";
const char* OptionStrings::Controls_UseTouchScreen = "ctrl_usetouchscreen";
const char* OptionStrings::Controls_UseTouchJoypad = "ctrl_usetouchjoypad";
const char* OptionStrings::Controls_IsLefthanded = "ctrl_islefthanded";
// why it isnt ctrl_feedback_vibration? i dont want touch it because compatibility with older versions
const char* OptionStrings::Controls_FeedbackVibration = "feedback_vibration";
const char* OptionStrings::Controls_AutoJump = "ctrl_autojump";
const char* OptionStrings::Game_DifficultyLevel = "game_difficulty";

View File

@@ -1,5 +1,4 @@
#ifndef NET_MINECRAFT_CLIENT__OptionStrings_H__
#define NET_MINECRAFT_CLIENT__OptionStrings_H__
#pragma once
class OptionStrings {
public:
@@ -8,6 +7,11 @@ public:
static const char* Graphics_Fancy;
static const char* Graphics_LowQuality;
static const char* Graphics_GUIScale;
static const char* Graphics_Vsync;
static const char* Graphics_SmoothLightning;
static const char* Graphics_Anaglyph;
static const char* Graphics_ViewBobbing;
static const char* Controls_Sensitivity;
static const char* Controls_InvertMouse;
@@ -15,8 +19,16 @@ public:
static const char* Controls_UseTouchJoypad;
static const char* Controls_IsLefthanded;
static const char* Controls_FeedbackVibration;
static const char* Controls_AutoJump;
static const char* Audio_Music;
static const char* Audio_Sound;
static const char* Game_DifficultyLevel;
static const char* Tweaks_Sprint;
static const char* Tweaks_BarOnTop;
};
#endif /*NET_MINECRAFT_CLIENT__OptionsStrings_H__*/

View File

@@ -1,460 +1,297 @@
#include "Options.h"
#include "OptionStrings.h"
#include "Minecraft.h"
#include "../platform/log.h"
#include "../world/Difficulty.h"
#include <cmath>
#include <sstream>
/*static*/
#include "Options.hpp"
#include "world/Difficulty.hpp"
#include <MinecraftClient.hpp>
bool Options::debugGl = false;
void Options::initDefaultValues() {
difficulty = Difficulty::NORMAL;
hideGui = false;
thirdPersonView = false;
renderDebug = false;
isFlying = false;
smoothCamera = true;
fixedCamera = false;
flySpeed = 1;
cameraSpeed = 1;
guiScale = 0;
// OPTIONS TABLE
useMouseForDigging = false;
destroyVibration = true;
isLeftHanded = false;
OptionInt difficulty("difficulty", Difficulty::NORMAL, 0, Difficulty::COUNT);
OptionBool hidegui("hidegui", false);
OptionBool thirdPersonView("thirdperson", false);
OptionBool renderDebug("renderDebug", false);
OptionBool smoothCamera("smoothCamera", false);
OptionBool fixedCamera("fixedCamera", false);
OptionBool isFlying("isflying", false);
OptionBool barOnTop("barOnTop", false);
OptionBool allowSprint("allowSprint", true);
OptionBool rpiCursor("rpiCursor", false);
OptionBool autoJump("autoJump", true);
isJoyTouchArea = false;
music = 1;
sound = 1;
sensitivity = 0.5f;
invertYMouse = false;
viewDistance = 2;
bobView = true;
anaglyph3d = false;
limitFramerate = false;
fancyGraphics = true;//false;
ambientOcclusion = false;
if(minecraft->supportNonTouchScreen())
useTouchScreen = false;
else
useTouchScreen = true;
pixelsPerMillimeter = minecraft->platform()->getPixelsPerMillimeter();
//useMouseForDigging = true;
OptionFloat flySpeed("flySpeed", 1.f);
OptionFloat cameraSpeed("cameraSpeed", 1.f);
//skin = "Default";
username = "Steve";
serverVisible = true;
OptionInt guiScale("guiScale", 0, 0, 5);
keyUp = KeyMapping("key.forward", Keyboard::KEY_W);
keyLeft = KeyMapping("key.left", Keyboard::KEY_A);
keyDown = KeyMapping("key.back", Keyboard::KEY_S);
keyRight = KeyMapping("key.right", Keyboard::KEY_D);
keyJump = KeyMapping("key.jump", Keyboard::KEY_SPACE);
keyBuild = KeyMapping("key.inventory", Keyboard::KEY_E);
keySneak = KeyMapping("key.sneak", Keyboard::KEY_LSHIFT);
#ifndef RPI
keyCraft = KeyMapping("key.crafting", Keyboard::KEY_Q);
keyDrop = KeyMapping("key.drop", Keyboard::KEY_Q);
keyChat = KeyMapping("key.chat", Keyboard::KEY_T);
keyFog = KeyMapping("key.fog", Keyboard::KEY_F);
keyDestroy=KeyMapping("key.destroy", 88); // @todo @fix
keyUse = KeyMapping("key.use", Keyboard::KEY_U);
OptionString skin("skin", "Default");
#ifdef RPI
OptionString username("username", "StevePi");
#else
OptionString username("username", "Steve");
#endif
//const int Unused = 99999;
keyMenuNext = KeyMapping("key.menu.next", 40);
keyMenuPrevious = KeyMapping("key.menu.previous", 38);
keyMenuOk = KeyMapping("key.menu.ok", 13);
keyMenuCancel = KeyMapping("key.menu.cancel", 8);
OptionBool destroyVibration("destroyVibration", true);
OptionBool isLeftHanded("isLeftHanded", false);
OptionBool isJoyTouchArea("isJoyTouchArea", false);
int k = 0;
keyMappings[k++] = &keyUp;
keyMappings[k++] = &keyLeft;
keyMappings[k++] = &keyDown;
keyMappings[k++] = &keyRight;
keyMappings[k++] = &keyJump;
keyMappings[k++] = &keySneak;
keyMappings[k++] = &keyDrop;
keyMappings[k++] = &keyBuild;
keyMappings[k++] = &keyChat;
keyMappings[k++] = &keyFog;
keyMappings[k++] = &keyDestroy;
keyMappings[k++] = &keyUse;
OptionFloat musicVolume("music", 1.f, MUSIC_MIN_VALUE, MUSIC_MAX_VALUE);
OptionFloat soundVolume("sound", 1.f, SOUND_MIN_VALUE, SOUND_MAX_VALUE);
keyMappings[k++] = &keyMenuNext;
keyMappings[k++] = &keyMenuPrevious;
keyMappings[k++] = &keyMenuOk;
keyMappings[k++] = &keyMenuCancel;
OptionFloat sensitivityOpt("sensitivity", 0.5f, SENSITIVITY_MIN_VALUE, SENSITIVITY_MAX_VALUE);
// "Polymorphism" at it's worst. At least it's better to have it here
// for now, then to have it spread all around the game code (even if
// it would be slightly better performance with it inlined. Should
// probably create separate subclasses (or read from file). @fix @todo.
#if defined(ANDROID) || defined(__APPLE__) || defined(RPI)
viewDistance = 2;
thirdPersonView = false;
useMouseForDigging = false;
fancyGraphics = false;
OptionBool invertYMouse("invertMouse", false);
OptionInt viewDistance("renderDistance", 2, 0, 4);
//renderDebug = true;
#if !defined(RPI)
keyUp.key = 19;
keyDown.key = 20;
keyLeft.key = 21;
keyRight.key = 22;
keyJump.key = 23;
keyUse.key = 103;
keyDestroy.key = 102;
keyCraft.key = 109;
OptionBool anaglyph3d("anaglyph3d", false);
OptionBool limitFramerate("limitFramerate", false);
OptionBool vsync("vsync", true);
OptionBool fancyGraphics("fancyGraphics", true);
OptionBool viewBobbing("viewBobbing", true);
OptionBool ambientOcclusion("ao", false);
keyMenuNext.key = 20;
keyMenuPrevious.key = 19;
keyMenuOk.key = 23;
keyMenuCancel.key = 4;
#endif
#endif
OptionBool useTouchscreen("useTouchscreen", true);
#if defined(RPI)
username = "StevePi";
OptionBool serverVisible("servervisible", true);
OptionInt keyForward("key.forward", Keyboard::KEY_W);
OptionInt keyLeft("key.left", Keyboard::KEY_A);
OptionInt keyBack("key.back", Keyboard::KEY_S);
OptionInt keyRight("key.right", Keyboard::KEY_D);
OptionInt keyJump("key.jump", Keyboard::KEY_SPACE);
OptionInt keyInventory("key.inventory", Keyboard::KEY_E);
OptionInt keySneak("key.sneak", Keyboard::KEY_LSHIFT);
OptionInt keyDrop("key.drop", Keyboard::KEY_Q);
OptionInt keyChat("key.chat", Keyboard::KEY_T);
OptionInt keyFog("key.fog", Keyboard::KEY_F);
OptionInt keyUse("key.use", Keyboard::KEY_U);
// TODO: make human readable keycodes here
OptionInt keyMenuNext("key.menu.next", 40);
OptionInt keyMenuPrev("key.menu.previous", 38);
OptionInt keyMenuOk("key.menu.ok", 13);
OptionInt keyMenuCancel("key.menu.cancel", 8);
OptionBool firstLaunch("firstLaunch", true);
OptionString lastIp("lastip");
void Options::initTable() {
m_options[OPTIONS_DIFFICULTY] = &difficulty;
m_options[OPTIONS_HIDEGUI] = &hidegui;
m_options[OPTIONS_THIRD_PERSON_VIEW] = &thirdPersonView;
m_options[OPTIONS_RENDER_DEBUG] = &renderDebug;
m_options[OPTIONS_SMOOTH_CAMERA] = &smoothCamera;
m_options[OPTIONS_FIXED_CAMERA] = &fixedCamera;
m_options[OPTIONS_IS_FLYING] = &isFlying;
m_options[OPTIONS_FLY_SPEED] = &flySpeed;
m_options[OPTIONS_CAMERA_SPEED] = &cameraSpeed;
m_options[OPTIONS_GUI_SCALE] = &guiScale;
m_options[OPTIONS_DESTROY_VIBRATION] = &destroyVibration;
m_options[OPTIONS_IS_LEFT_HANDED] = &isLeftHanded;
m_options[OPTIONS_IS_JOY_TOUCH_AREA] = &isJoyTouchArea;
m_options[OPTIONS_MUSIC_VOLUME] = &musicVolume;
m_options[OPTIONS_SOUND_VOLUME] = &soundVolume;
#if defined(PLATFORM_DESKTOP) || defined(RPI)
float sensitivity = sensitivityOpt.get();
sensitivity *= 0.4f;
useMouseForDigging = true;
sensitivityOpt.set(sensitivity);
#endif
m_options[OPTIONS_GUI_SCALE] = &guiScale;
m_options[OPTIONS_SKIN] = &skin;
m_options[OPTIONS_USERNAME] = &username;
m_options[OPTIONS_DESTROY_VIBRATION] = &destroyVibration;
m_options[OPTIONS_IS_LEFT_HANDED] = &isLeftHanded;
m_options[OPTIONS_MUSIC_VOLUME] = &musicVolume;
m_options[OPTIONS_SOUND_VOLUME] = &soundVolume;
m_options[OPTIONS_SENSITIVITY] = &sensitivityOpt;
m_options[OPTIONS_INVERT_Y_MOUSE] = &invertYMouse;
m_options[OPTIONS_VIEW_DISTANCE] = &viewDistance;
m_options[OPTIONS_ANAGLYPH_3D] = &anaglyph3d;
m_options[OPTIONS_LIMIT_FRAMERATE] = &limitFramerate;
m_options[OPTIONS_VSYNC] = &vsync;
m_options[OPTIONS_FANCY_GRAPHICS] = &fancyGraphics;
m_options[OPTIONS_VIEW_BOBBING] = &viewBobbing;
m_options[OPTIONS_AMBIENT_OCCLUSION] = &ambientOcclusion;
m_options[OPTIONS_USE_TOUCHSCREEN] = &useTouchscreen;
m_options[OPTIONS_SERVER_VISIBLE] = &serverVisible;
m_options[OPTIONS_KEY_FORWARD] = &keyForward;
m_options[OPTIONS_KEY_LEFT] = &keyLeft;
m_options[OPTIONS_KEY_BACK] = &keyBack;
m_options[OPTIONS_KEY_RIGHT] = &keyRight;
m_options[OPTIONS_KEY_JUMP] = &keyJump;
m_options[OPTIONS_KEY_INVENTORY] = &keyInventory;
m_options[OPTIONS_KEY_SNEAK] = &keySneak;
m_options[OPTIONS_KEY_DROP] = &keyDrop;
m_options[OPTIONS_KEY_CHAT] = &keyChat;
m_options[OPTIONS_KEY_FOG] = &keyFog;
m_options[OPTIONS_KEY_USE] = &keyUse;
m_options[OPTIONS_KEY_MENU_NEXT] = &keyMenuNext;
m_options[OPTIONS_KEY_MENU_PREV] = &keyMenuPrev;
m_options[OPTIONS_KEY_MENU_OK] = &keyMenuOk;
m_options[OPTIONS_KEY_MENU_CANCEL] = &keyMenuCancel;
m_options[OPTIONS_FIRST_LAUNCH] = &firstLaunch;
m_options[OPTIONS_BAR_ON_TOP] = &barOnTop;
m_options[OPTIONS_ALLOW_SPRINT] = &allowSprint;
m_options[OPTIONS_RPI_CURSOR] = &rpiCursor;
m_options[OPTIONS_AUTOJUMP] = &autoJump;
m_options[OPTIONS_LAST_IP] = &lastIp;
}
const Options::Option
Options::Option::MUSIC (0, "options.music", true, false),
Options::Option::SOUND (1, "options.sound", true, false),
Options::Option::INVERT_MOUSE (2, "options.invertMouse", false, true),
Options::Option::SENSITIVITY (3, "options.sensitivity", true, false),
Options::Option::RENDER_DISTANCE (4, "options.renderDistance",false, false),
Options::Option::VIEW_BOBBING (5, "options.viewBobbing", false, true),
Options::Option::ANAGLYPH (6, "options.anaglyph", false, true),
Options::Option::LIMIT_FRAMERATE (7, "options.limitFramerate",false, true),
Options::Option::DIFFICULTY (8, "options.difficulty", false, false),
Options::Option::GRAPHICS (9, "options.graphics", false, false),
Options::Option::AMBIENT_OCCLUSION (10, "options.ao", false, true),
Options::Option::GUI_SCALE (11, "options.guiScale", false, false),
Options::Option::THIRD_PERSON (12, "options.thirdperson", false, true),
Options::Option::HIDE_GUI (13, "options.hidegui", false, true),
Options::Option::SERVER_VISIBLE (14, "options.servervisible", false, true),
Options::Option::LEFT_HANDED (15, "options.lefthanded", false, true),
Options::Option::USE_TOUCHSCREEN (16, "options.usetouchscreen", false, true),
Options::Option::USE_TOUCH_JOYPAD (17, "options.usetouchpad", false, true),
Options::Option::DESTROY_VIBRATION (18, "options.destroyvibration", false, true),
Options::Option::PIXELS_PER_MILLIMETER(19, "options.pixelspermilimeter", true, false);
void Options::set(OptionId key, const std::string& value) {
auto option = opt<OptionString>(key);
/* private */
const float Options::SOUND_MIN_VALUE = 0.0f;
const float Options::SOUND_MAX_VALUE = 1.0f;
const float Options::MUSIC_MIN_VALUE = 0.0f;
const float Options::MUSIC_MAX_VALUE = 1.0f;
const float Options::SENSITIVITY_MIN_VALUE = 0.0f;
const float Options::SENSITIVITY_MAX_VALUE = 1.0f;
const float Options::PIXELS_PER_MILLIMETER_MIN_VALUE = 3.0f;
const float Options::PIXELS_PER_MILLIMETER_MAX_VALUE = 4.0f;
const int DIFFICULY_LEVELS[] = {
Difficulty::PEACEFUL,
Difficulty::NORMAL
};
if (option) {
option->set(value);
notifyOptionUpdate(key, value);
}
}
/*private*/
const char* Options::RENDER_DISTANCE_NAMES[] = {
"options.renderDistance.far",
"options.renderDistance.normal",
"options.renderDistance.short",
"options.renderDistance.tiny"
};
void Options::set(OptionId key, float value) {
auto option = opt<OptionFloat>(key);
/*private*/
const char* Options::DIFFICULTY_NAMES[] = {
"options.difficulty.peaceful",
"options.difficulty.easy",
"options.difficulty.normal",
"options.difficulty.hard"
};
if (option) {
option->set(value);
notifyOptionUpdate(key, value);
}
}
/*private*/
const char* Options::GUI_SCALE[] = {
"options.guiScale.auto",
"options.guiScale.small",
"options.guiScale.normal",
"options.guiScale.large"
};
void Options::set(OptionId key, int value) {
auto option = opt<OptionInt>(key);
void Options::update()
{
viewDistance = 2;
if (option) {
option->set(value);
notifyOptionUpdate(key, value);
}
}
void Options::toggle(OptionId key) {
auto option = opt<OptionBool>(key);
if (option) {
option->toggle();
notifyOptionUpdate(key, option->get());
}
}
void Options::load() {
StringVector optionStrings = optionsFile.getOptionStrings();
for (unsigned int i = 0; i < optionStrings.size(); i += 2) {
for (auto i = 0; i < optionStrings.size(); i += 2) {
const std::string& key = optionStrings[i];
const std::string& value = optionStrings[i+1];
//LOGI("reading key: %s (%s)\n", key.c_str(), value.c_str());
// FIXME: woah this is so slow
auto opt = std::find_if(m_options.begin(), m_options.end(), [&](auto& it) {
return it != nullptr && it->getStringId() == key;
});
// Multiplayer
if (key == OptionStrings::Multiplayer_Username) username = value;
if (key == OptionStrings::Multiplayer_ServerVisible) readBool(value, serverVisible);
if (opt == m_options.end()) continue;
// Controls
if (key == OptionStrings::Controls_Sensitivity) {
float sens;
if (readFloat(value, sens)) {
// sens is in range [0,1] with default/center at 0.5 (for aesthetics)
// We wanna map it to something like [0.3, 0.9] BUT keep 0.5 @ ~0.5...
sensitivity = 0.3f + std::pow(1.1f * sens, 1.3f) * 0.42f;
}
}
if (key == OptionStrings::Controls_InvertMouse) {
readBool(value, invertYMouse);
}
if (key == OptionStrings::Controls_IsLefthanded) {
readBool(value, isLeftHanded);
}
if (key == OptionStrings::Controls_UseTouchJoypad) {
readBool(value, isJoyTouchArea);
if (!minecraft->useTouchscreen())
isJoyTouchArea = false;
}
(*opt)->parse(value);
/*
// //LOGI("reading key: %s (%s)\n", key.c_str(), value.c_str());
// Feedback
if (key == OptionStrings::Controls_FeedbackVibration)
readBool(value, destroyVibration);
// Graphics
if (key == OptionStrings::Graphics_Fancy) {
readBool(value, fancyGraphics);
}
if (key == OptionStrings::Graphics_LowQuality) {
bool isLow;
readBool(value, isLow);
if (isLow) {
viewDistance = 3;
fancyGraphics = false;
}
}
// Game
if (key == OptionStrings::Game_DifficultyLevel) {
readInt(value, difficulty);
// Only support peaceful and normal right now
if (difficulty != Difficulty::PEACEFUL && difficulty != Difficulty::NORMAL)
difficulty = Difficulty::NORMAL;
}
}
#ifdef __APPLE__
// if (minecraft->isSuperFast()) {
// viewDistance = (viewDistance>0)? --viewDistance : 0;
// // Multiplayer
// // if (key == OptionStrings::Multiplayer_Username) username = value;
// if (key == OptionStrings::Multiplayer_ServerVisible) {
// m_options[OPTIONS_SERVER_VISIBLE] = readBool(value);
// }
// LOGI("Is this card super fast?: %d\n", viewDistance);
#endif
//LOGI("Lefty is: %d\n", isLeftHanded);
// // Controls
// if (key == OptionStrings::Controls_Sensitivity) {
// float sens = readFloat(value);
// // sens is in range [0,1] with default/center at 0.5 (for aesthetics)
// // We wanna map it to something like [0.3, 0.9] BUT keep 0.5 @ ~0.5...
// m_options[OPTIONS_SENSITIVITY] = 0.3f + std::pow(1.1f * sens, 1.3f) * 0.42f;
// }
// if (key == OptionStrings::Controls_InvertMouse) {
// m_options[OPTIONS_INVERT_Y_MOUSE] = readBool(value);
// }
// if (key == OptionStrings::Controls_IsLefthanded) {
// m_options[OPTIONS_IS_LEFT_HANDED] = readBool(value);
// }
// if (key == OptionStrings::Controls_UseTouchJoypad) {
// m_options[OPTIONS_IS_JOY_TOUCH_AREA] = readBool(value) && minecraft->useTouchscreen();
// }
// // Feedback
// if (key == OptionStrings::Controls_FeedbackVibration) {
// m_options[OPTIONS_DESTROY_VIBRATION] = readBool(value);
// }
// // Graphics
// if (key == OptionStrings::Graphics_Fancy) {
// m_options[OPTIONS_FANCY_GRAPHICS] = readBool(value);
// }
// // Graphics extras
// if (key == OptionStrings::Graphics_Vsync) {
// m_options[OPTIONS_VSYNC] = readBool(value);
// }
// if (key == OptionStrings::Graphics_GUIScale) {
// m_options[OPTIONS_GUI_SCALE] = readInt(value) % 5;
// }
// // Game
// if (key == OptionStrings::Game_DifficultyLevel) {
// readInt(value, difficulty);
// // Only support peaceful and normal right now
// if (difficulty != Difficulty::PEACEFUL && difficulty != Difficulty::NORMAL)
// difficulty = Difficulty::NORMAL;
// }*/
}
}
void Options::load()
{
int a = 0;
//try {
// if (!optionsFile.exists()) return;
// BufferedReader br = /*new*/ BufferedReader(/*new*/ FileReader(optionsFile));
// std::string line = "";
// while ((line = br.readLine()) != NULL) {
// std::string[] cmds = line.split(":");
// if (cmds[0].equals("music")) music = readFloat(cmds[1]);
// if (cmds[0].equals("sound")) sound = readFloat(cmds[1]);
// if (cmds[0].equals("mouseSensitivity")) sensitivity = readFloat(cmds[1]);
// if (cmds[0].equals("invertYMouse")) invertYMouse = cmds[1].equals("true");
// if (cmds[0].equals("viewDistance")) viewDistance = Integer.parseInt(cmds[1]);
// if (cmds[0].equals("guiScale")) guiScale = Integer.parseInt(cmds[1]);
// if (cmds[0].equals("bobView")) bobView = cmds[1].equals("true");
// if (cmds[0].equals("anaglyph3d")) anaglyph3d = cmds[1].equals("true");
// if (cmds[0].equals("limitFramerate")) limitFramerate = cmds[1].equals("true");
// if (cmds[0].equals("difficulty")) difficulty = Integer.parseInt(cmds[1]);
// if (cmds[0].equals("fancyGraphics")) fancyGraphics = cmds[1].equals("true");
// if (cmds[0].equals("ao")) ambientOcclusion = cmds[1].equals("true");
// if (cmds[0].equals("skin")) skin = cmds[1];
// if (cmds[0].equals("lastServer") && cmds.length >= 2) lastMpIp = cmds[1];
// for (int i = 0; i < keyMappings.length; i++) {
// if (cmds[0].equals("key_" + keyMappings[i].name)) {
// keyMappings[i].key = Integer.parseInt(cmds[1]);
// }
// }
// }
// br.close();
//} catch (Exception e) {
// System.out.println("Failed to load options");
// e.printStackTrace();
//}
}
void Options::save()
{
void Options::save() {
StringVector stringVec;
// Game
addOptionToSaveOutput(stringVec, OptionStrings::Multiplayer_ServerVisible, serverVisible);
addOptionToSaveOutput(stringVec, OptionStrings::Game_DifficultyLevel, difficulty);
// Input
addOptionToSaveOutput(stringVec, OptionStrings::Controls_InvertMouse, invertYMouse);
addOptionToSaveOutput(stringVec, OptionStrings::Controls_Sensitivity, sensitivity);
addOptionToSaveOutput(stringVec, OptionStrings::Controls_IsLefthanded, isLeftHanded);
addOptionToSaveOutput(stringVec, OptionStrings::Controls_UseTouchScreen, useTouchScreen);
addOptionToSaveOutput(stringVec, OptionStrings::Controls_UseTouchJoypad, isJoyTouchArea);
addOptionToSaveOutput(stringVec, OptionStrings::Controls_FeedbackVibration, destroyVibration);
//
// static const Option MUSIC;
// static const Option SOUND;
// static const Option INVERT_MOUSE;
// static const Option SENSITIVITY;
// static const Option RENDER_DISTANCE;
// static const Option VIEW_BOBBING;
// static const Option ANAGLYPH;
// static const Option LIMIT_FRAMERATE;
// static const Option DIFFICULTY;
// static const Option GRAPHICS;
// static const Option AMBIENT_OCCLUSION;
// static const Option GUI_SCALE;
//
// static const Option THIRD_PERSON;
// static const Option HIDE_GUI;
//try {
// PrintWriter pw = /*new*/ PrintWriter(/*new*/ FileWriter(optionsFile));
// pw.println("music:" + music);
// pw.println("sound:" + sound);
// pw.println("invertYMouse:" + invertYMouse);
// pw.println("mouseSensitivity:" + sensitivity);
// pw.println("viewDistance:" + viewDistance);
// pw.println("guiScale:" + guiScale);
// pw.println("bobView:" + bobView);
// pw.println("anaglyph3d:" + anaglyph3d);
// pw.println("limitFramerate:" + limitFramerate);
// pw.println("difficulty:" + difficulty);
// pw.println("fancyGraphics:" + fancyGraphics);
// pw.println("ao:" + ambientOcclusion);
// pw.println("skin:" + skin);
// pw.println("lastServer:" + lastMpIp);
// for (int i = 0; i < keyMappings.length; i++) {
// pw.println("key_" + keyMappings[i].name + ":" + keyMappings[i].key);
// }
// pw.close();
//} catch (Exception e) {
// System.out.println("Failed to save options");
// e.printStackTrace();
//}
}
void Options::addOptionToSaveOutput(StringVector& stringVector, std::string name, bool boolValue) {
std::stringstream ss;
ss << name << ":" << boolValue;
stringVector.push_back(ss.str());
}
void Options::addOptionToSaveOutput(StringVector& stringVector, std::string name, float floatValue) {
std::stringstream ss;
ss << name << ":" << floatValue;
stringVector.push_back(ss.str());
}
void Options::addOptionToSaveOutput(StringVector& stringVector, std::string name, int intValue) {
std::stringstream ss;
ss << name << ":" << intValue;
stringVector.push_back(ss.str());
for (auto& it : m_options) {
if (it) stringVec.push_back(it->serialize());
}
std::string Options::getMessage( const Option* item )
{
return "Options::getMessage - Not implemented";
//Language language = Language.getInstance();
//std::string caption = language.getElement(item.getCaptionId()) + ": ";
//if (item.isProgress()) {
// float progressValue = getProgressValue(item);
// if (item == Option.SENSITIVITY) {
// if (progressValue == 0) {
// return caption + language.getElement("options.sensitivity.min");
// }
// if (progressValue == 1) {
// return caption + language.getElement("options.sensitivity.max");
// }
// return caption + (int) (progressValue * 200) + "%";
// } else {
// if (progressValue == 0) {
// return caption + language.getElement("options.off");
// }
// return caption + (int) (progressValue * 100) + "%";
// }
//} else if (item.isBoolean()) {
// bool booleanValue = getBooleanValue(item);
// if (booleanValue) {
// return caption + language.getElement("options.on");
// }
// return caption + language.getElement("options.off");
//} else if (item == Option.RENDER_DISTANCE) {
// return caption + language.getElement(RENDER_DISTANCE_NAMES[viewDistance]);
//} else if (item == Option.DIFFICULTY) {
// return caption + language.getElement(DIFFICULTY_NAMES[difficulty]);
//} else if (item == Option.GUI_SCALE) {
// return caption + language.getElement(GUI_SCALE[guiScale]);
//} else if (item == Option.GRAPHICS) {
// if (fancyGraphics) {
// return caption + language.getElement("options.graphics.fancy");
// }
// return caption + language.getElement("options.graphics.fast");
//}
//return caption;
optionsFile.save(stringVec);
}
/*static*/
bool Options::readFloat(const std::string& string, float& value) {
if (string == "true" || string == "YES") { value = 1; return true; }
if (string == "false" || string == "NO") { value = 0; return true; }
#ifdef _WIN32
if (sscanf_s(string.c_str(), "%f", &value))
return true;
#else
if (sscanf(string.c_str(), "%f", &value))
return true;
#endif
return false;
void Options::setOptionsFilePath(const std::string& path) {
optionsFile.setOptionsPath(path + "/options.txt");
}
/*static*/
bool Options::readInt(const std::string& string, int& value) {
if (string == "true" || string == "YES") { value = 1; return true; }
if (string == "false" || string == "NO") { value = 0; return true; }
#ifdef _WIN32
if (sscanf_s(string.c_str(), "%d", &value))
return true;
#else
if (sscanf(string.c_str(), "%d", &value))
return true;
#endif
return false;
void Options::notifyOptionUpdate(OptionId key, bool value) {
minecraft.optionUpdated(key, value);
}
/*static*/
bool Options::readBool(const std::string& string, bool& value) {
std::string s = Util::stringTrim(string);
if (string == "true" || string == "1" || string == "YES") { value = true; return true; }
if (string == "false" || string == "0" || string == "NO") { value = false; return true; }
return false;
void Options::notifyOptionUpdate(OptionId key, float value) {
minecraft.optionUpdated(key, value);
}
void Options::notifyOptionUpdate( const Option* option, bool value ) {
minecraft->optionUpdated(option, value);
}
void Options::notifyOptionUpdate( const Option* option, float value ) {
minecraft->optionUpdated(option, value);
}
void Options::notifyOptionUpdate( const Option* option, int value ) {
minecraft->optionUpdated(option, value);
void Options::notifyOptionUpdate(OptionId key, int value) {
minecraft.optionUpdated(key, value);
}

View File

@@ -1,328 +0,0 @@
#ifndef NET_MINECRAFT_CLIENT__Options_H__
#define NET_MINECRAFT_CLIENT__Options_H__
//package net.minecraft.client;
//#include "locale/Language.h"
#include <string>
#include <cstdio>
#include "KeyMapping.h"
#include "../platform/input/Keyboard.h"
#include "../util/StringUtils.h"
#include "OptionsFile.h"
class Minecraft;
typedef std::vector<std::string> StringVector;
class Options
{
public:
class Option
{
const bool _isProgress;
const bool _isBoolean;
const std::string _captionId;
const int _ordinal;
public:
static const Option MUSIC;
static const Option SOUND;
static const Option INVERT_MOUSE;
static const Option SENSITIVITY;
static const Option RENDER_DISTANCE;
static const Option VIEW_BOBBING;
static const Option ANAGLYPH;
static const Option LIMIT_FRAMERATE;
static const Option DIFFICULTY;
static const Option GRAPHICS;
static const Option AMBIENT_OCCLUSION;
static const Option GUI_SCALE;
static const Option THIRD_PERSON;
static const Option HIDE_GUI;
static const Option SERVER_VISIBLE;
static const Option LEFT_HANDED;
static const Option USE_TOUCHSCREEN;
static const Option USE_TOUCH_JOYPAD;
static const Option DESTROY_VIBRATION;
static const Option PIXELS_PER_MILLIMETER;
/*
static Option* getItem(int id) {
for (Option item : Option.values()) {
if (item.getId() == id) {
return item;
}
}
return NULL;
}
*/
Option(int ordinal, const std::string& captionId, bool hasProgress, bool isBoolean)
: _captionId(captionId),
_isProgress(hasProgress),
_isBoolean(isBoolean),
_ordinal(ordinal)
{}
bool isProgress() const {
return _isProgress;
}
bool isBoolean() const {
return _isBoolean;
}
bool isInt() const {
return (!_isBoolean && !_isProgress);
}
int getId() {
return _ordinal;
}
std::string getCaptionId() const {
return _captionId;
}
};
private:
static const float SOUND_MIN_VALUE;
static const float SOUND_MAX_VALUE;
static const float MUSIC_MIN_VALUE;
static const float MUSIC_MAX_VALUE;
static const float SENSITIVITY_MIN_VALUE;
static const float SENSITIVITY_MAX_VALUE;
static const float PIXELS_PER_MILLIMETER_MIN_VALUE;
static const float PIXELS_PER_MILLIMETER_MAX_VALUE;
static const char* RENDER_DISTANCE_NAMES[];
static const char* DIFFICULTY_NAMES[];
static const char* GUI_SCALE[];
static const int DIFFICULY_LEVELS[];
public:
static bool debugGl;
float music;
float sound;
//note: sensitivity is transformed in Options::update
float sensitivity;
bool invertYMouse;
int viewDistance;
bool bobView;
bool anaglyph3d;
bool limitFramerate;
bool fancyGraphics;
bool ambientOcclusion;
bool useMouseForDigging;
bool isLeftHanded;
bool destroyVibration;
//std::string skin;
KeyMapping keyUp;
KeyMapping keyLeft;
KeyMapping keyDown;
KeyMapping keyRight;
KeyMapping keyJump;
KeyMapping keyBuild;
KeyMapping keyDrop;
KeyMapping keyChat;
KeyMapping keyFog;
KeyMapping keySneak;
KeyMapping keyCraft;
KeyMapping keyDestroy;
KeyMapping keyUse;
KeyMapping keyMenuNext;
KeyMapping keyMenuPrevious;
KeyMapping keyMenuOk;
KeyMapping keyMenuCancel;
KeyMapping* keyMappings[16];
/*protected*/ Minecraft* minecraft;
///*private*/ File optionsFile;
int difficulty;
bool hideGui;
bool thirdPersonView;
bool renderDebug;
bool isFlying;
bool smoothCamera;
bool fixedCamera;
float flySpeed;
float cameraSpeed;
int guiScale;
std::string username;
bool serverVisible;
bool isJoyTouchArea;
bool useTouchScreen;
float pixelsPerMillimeter;
Options(Minecraft* minecraft, const std::string& workingDirectory)
: minecraft(minecraft)
{
//optionsFile = /*new*/ File(workingDirectory, "options.txt");
initDefaultValues();
load();
}
Options()
: minecraft(NULL)
{
}
void initDefaultValues();
std::string getKeyDescription(int i) {
//Language language = Language.getInstance();
//return language.getElement(keyMappings[i].name);
return "Options::getKeyDescription not implemented";
}
std::string getKeyMessage(int i) {
//return Keyboard.getKeyName(keyMappings[i].key);
return "Options::getKeyMessage not implemented";
}
void setKey(int i, int key) {
keyMappings[i]->key = key;
save();
}
void set(const Option* item, float value) {
if (item == &Option::MUSIC) {
music = value;
//minecraft.soundEngine.updateOptions();
} else if (item == &Option::SOUND) {
sound = value;
//minecraft.soundEngine.updateOptions();
} else if (item == &Option::SENSITIVITY) {
sensitivity = value;
} else if (item == &Option::PIXELS_PER_MILLIMETER) {
pixelsPerMillimeter = value;
}
notifyOptionUpdate(item, value);
}
void set(const Option* item, int value) {
if(item == &Option::DIFFICULTY) {
difficulty = value;
}
notifyOptionUpdate(item, value);
}
void toggle(const Option* option, int dir) {
if (option == &Option::INVERT_MOUSE) invertYMouse = !invertYMouse;
if (option == &Option::RENDER_DISTANCE) viewDistance = (viewDistance + dir) & 3;
if (option == &Option::GUI_SCALE) guiScale = (guiScale + dir) & 3;
if (option == &Option::VIEW_BOBBING) bobView = !bobView;
if (option == &Option::THIRD_PERSON) thirdPersonView = !thirdPersonView;
if (option == &Option::HIDE_GUI) hideGui = !hideGui;
if (option == &Option::SERVER_VISIBLE) serverVisible = !serverVisible;
if (option == &Option::LEFT_HANDED) isLeftHanded = !isLeftHanded;
if (option == &Option::USE_TOUCHSCREEN) useTouchScreen = !useTouchScreen;
if (option == &Option::USE_TOUCH_JOYPAD) isJoyTouchArea = !isJoyTouchArea;
if (option == &Option::DESTROY_VIBRATION) destroyVibration = !destroyVibration;
if (option == &Option::ANAGLYPH) {
anaglyph3d = !anaglyph3d;
//minecraft->textures.reloadAll();
}
if (option == &Option::LIMIT_FRAMERATE) limitFramerate = !limitFramerate;
if (option == &Option::DIFFICULTY) difficulty = (difficulty + dir) & 3;
if (option == &Option::GRAPHICS) {
fancyGraphics = !fancyGraphics;
//minecraft->levelRenderer.allChanged();
}
if (option == &Option::AMBIENT_OCCLUSION) {
ambientOcclusion = !ambientOcclusion;
//minecraft->levelRenderer.allChanged();
}
notifyOptionUpdate(option, getBooleanValue(option));
save();
}
int getIntValue(const Option* item) {
if(item == &Option::DIFFICULTY) return difficulty;
return 0;
}
float getProgressValue(const Option* item) {
if (item == &Option::MUSIC) return music;
if (item == &Option::SOUND) return sound;
if (item == &Option::SENSITIVITY) return sensitivity;
if (item == &Option::PIXELS_PER_MILLIMETER) return pixelsPerMillimeter;
return 0;
}
bool getBooleanValue(const Option* item) {
if (item == &Option::INVERT_MOUSE)
return invertYMouse;
if (item == &Option::VIEW_BOBBING)
return bobView;
if (item == &Option::ANAGLYPH)
return anaglyph3d;
if (item == &Option::LIMIT_FRAMERATE)
return limitFramerate;
if (item == &Option::AMBIENT_OCCLUSION)
return ambientOcclusion;
if (item == &Option::THIRD_PERSON)
return thirdPersonView;
if (item == &Option::HIDE_GUI)
return hideGui;
if (item == &Option::THIRD_PERSON)
return thirdPersonView;
if (item == &Option::SERVER_VISIBLE)
return serverVisible;
if (item == &Option::LEFT_HANDED)
return isLeftHanded;
if (item == &Option::USE_TOUCHSCREEN)
return useTouchScreen;
if (item == &Option::USE_TOUCH_JOYPAD)
return isJoyTouchArea;
if (item == &Option::DESTROY_VIBRATION)
return destroyVibration;
return false;
}
float getProgrssMin(const Option* item) {
if (item == &Option::MUSIC) return MUSIC_MIN_VALUE;
if (item == &Option::SOUND) return SOUND_MIN_VALUE;
if (item == &Option::SENSITIVITY) return SENSITIVITY_MIN_VALUE;
if (item == &Option::PIXELS_PER_MILLIMETER) return PIXELS_PER_MILLIMETER_MIN_VALUE;
return 0;
}
float getProgrssMax(const Option* item) {
if (item == &Option::MUSIC) return MUSIC_MAX_VALUE;
if (item == &Option::SOUND) return SOUND_MAX_VALUE;
if (item == &Option::SENSITIVITY) return SENSITIVITY_MAX_VALUE;
if (item == &Option::PIXELS_PER_MILLIMETER) return PIXELS_PER_MILLIMETER_MAX_VALUE;
return 1.0f;
}
std::string getMessage(const Option* item);
void update();
void load();
void save();
void addOptionToSaveOutput(StringVector& stringVector, std::string name, bool boolValue);
void addOptionToSaveOutput(StringVector& stringVector, std::string name, float floatValue);
void addOptionToSaveOutput(StringVector& stringVector, std::string name, int intValue);
void notifyOptionUpdate(const Option* option, bool value);
void notifyOptionUpdate(const Option* option, float value);
void notifyOptionUpdate(const Option* option, int value);
private:
static bool readFloat(const std::string& string, float& value);
static bool readInt(const std::string& string, int& value);
static bool readBool(const std::string& string, bool& value);
private:
OptionsFile optionsFile;
};
#endif /*NET_MINECRAFT_CLIENT__Options_H__*/

164
src/client/Options.hpp Executable file
View File

@@ -0,0 +1,164 @@
#pragma once
#define SOUND_MIN_VALUE 0.0f
#define SOUND_MAX_VALUE 1.0f
#define MUSIC_MIN_VALUE 0.0f
#define MUSIC_MAX_VALUE 1.0f
#define SENSITIVITY_MIN_VALUE 0.0f
#define SENSITIVITY_MAX_VALUE 1.0f
#define PIXELS_PER_MILLIMETER_MIN_VALUE 3.0f
#define PIXELS_PER_MILLIMETER_MAX_VALUE 4.0f
//package net.minecraft.client;
//#include "locale/Language.hpp"
#include <string>
#include <platform/input/Keyboard.hpp>
#include <util/StringUtils.hpp>
#include "OptionsFile.hpp"
#include "Option.hpp"
#include <array>
enum OptionId {
// General
OPTIONS_DIFFICULTY,
OPTIONS_HIDEGUI,
OPTIONS_THIRD_PERSON_VIEW,
OPTIONS_GUI_SCALE,
OPTIONS_DESTROY_VIBRATION,
OPTIONS_MUSIC_VOLUME,
OPTIONS_SOUND_VOLUME,
OPTIONS_SKIN,
OPTIONS_USERNAME,
OPTIONS_SERVER_VISIBLE,
OPTIONS_BAR_ON_TOP,
OPTIONS_ALLOW_SPRINT,
OPTIONS_AUTOJUMP,
// Graphics
OPTIONS_RENDER_DEBUG,
OPTIONS_SMOOTH_CAMERA,
OPTIONS_FIXED_CAMERA,
OPTIONS_VIEW_DISTANCE,
OPTIONS_VIEW_BOBBING,
OPTIONS_AMBIENT_OCCLUSION,
OPTIONS_ANAGLYPH_3D,
OPTIONS_LIMIT_FRAMERATE,
OPTIONS_VSYNC,
OPTIONS_FANCY_GRAPHICS,
// Cheats / debug
OPTIONS_FLY_SPEED,
OPTIONS_CAMERA_SPEED,
OPTIONS_IS_FLYING,
// Control
OPTIONS_USE_MOUSE_FOR_DIGGING,
OPTIONS_IS_LEFT_HANDED,
OPTIONS_IS_JOY_TOUCH_AREA,
OPTIONS_SENSITIVITY,
OPTIONS_INVERT_Y_MOUSE,
OPTIONS_USE_TOUCHSCREEN,
OPTIONS_KEY_FORWARD,
OPTIONS_KEY_LEFT,
OPTIONS_KEY_BACK,
OPTIONS_KEY_RIGHT,
OPTIONS_KEY_JUMP,
OPTIONS_KEY_INVENTORY,
OPTIONS_KEY_SNEAK,
OPTIONS_KEY_DROP,
OPTIONS_KEY_CHAT,
OPTIONS_KEY_FOG,
OPTIONS_KEY_USE,
OPTIONS_KEY_MENU_NEXT,
OPTIONS_KEY_MENU_PREV,
OPTIONS_KEY_MENU_OK,
OPTIONS_KEY_MENU_CANCEL,
OPTIONS_FIRST_LAUNCH,
OPTIONS_LAST_IP,
OPTIONS_RPI_CURSOR,
// Should be last!
OPTIONS_COUNT
};
class MinecraftClient;
typedef std::vector<std::string> StringVector;
class Options
{
public:
static bool debugGl;
Options(MinecraftClient& minecraft, const std::string& workingDirectory = "")
: minecraft(minecraft) {
// elements werent initialized so i was getting a garbage pointer and a crash
m_options.fill(nullptr);
initTable();
// load() is deferred to init() where path is configured correctly
}
void initTable();
int getIntValue(OptionId key) {
auto option = opt<OptionInt>(key);
return (option)? option->get() : 0;
}
std::string getStringValue(OptionId key) {
auto option = opt<OptionString>(key);
return (option)? option->get() : "";
}
float getProgressValue(OptionId key) {
auto option = opt<OptionFloat>(key);
return (option)? option->get() : 0.f;
}
bool getBooleanValue(OptionId key) {
auto option = opt<OptionBool>(key);
return (option)? option->get() : false;
}
float getProgrssMin(OptionId key) {
auto option = opt<OptionFloat>(key);
return (option)? option->getMin() : 0.f;
}
float getProgrssMax(OptionId key) {
auto option = opt<OptionFloat>(key);
return (option)? option->getMax() : 0.f;
}
Option* getOpt(OptionId id) { return m_options[id]; }
void load();
void save();
void set(OptionId key, int value);
void set(OptionId key, float value);
void set(OptionId key, const std::string& value);
void setOptionsFilePath(const std::string& path);
void toggle(OptionId key);
void notifyOptionUpdate(OptionId key, bool value);
void notifyOptionUpdate(OptionId key, float value);
void notifyOptionUpdate(OptionId key, int value);
void notifyOptionUpdate(OptionId key, const std::string& value) {}
private:
template<typename T>
T* opt(OptionId key) {
if (m_options[key] == nullptr) return nullptr;
return dynamic_cast<T*>(m_options[key]);
}
std::array<Option*, OPTIONS_COUNT> m_options;
OptionsFile optionsFile;
MinecraftClient& minecraft;
};

View File

@@ -1,37 +1,98 @@
#include "OptionsFile.h"
#include "OptionsFile.hpp"
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <platform/log.hpp>
#if defined(_WIN32)
#include <direct.h>
#else
#include <sys/stat.h>
#include <sys/types.h>
#endif
OptionsFile::OptionsFile() {
#ifdef __APPLE__
settingsPath = "./Documents/options.txt";
#elif defined(ANDROID)
settingsPath = "options.txt";
#elif defined(__EMSCRIPTEN__)
settingsPath = "/games/com.mojang/options.txt";
#else
settingsPath = "options.txt";
#endif
}
void OptionsFile::setOptionsPath(const std::string& path) {
settingsPath = path;
}
std::string OptionsFile::getOptionsPath() const {
return settingsPath;
}
void OptionsFile::save(const StringVector& settings) {
FILE* pFile = fopen(settingsPath.c_str(), "w");
if(pFile != NULL) {
for(StringVector::const_iterator it = settings.begin(); it != settings.end(); ++it) {
fprintf(pFile, "%s\n", it->c_str());
if (!pFile && errno == ENOENT) {
std::string dir = settingsPath;
size_t fpos = dir.find_last_of("/\\");
if (fpos != std::string::npos) {
dir.resize(fpos);
std::string toCreate;
for (size_t i = 0; i <= dir.size(); ++i) {
if (i == dir.size() || dir[i] == '/' || dir[i] == '\\') {
if (!toCreate.empty()) {
#if defined(_WIN32)
_mkdir(toCreate.c_str());
#else
mkdir(toCreate.c_str(), 0755);
#endif
}
fclose(pFile);
}
if (i < dir.size())
toCreate.push_back(dir[i]);
}
}
pFile = fopen(settingsPath.c_str(), "w");
}
if (!pFile) {
LOGI("OptionsFile::save failed: %s", strerror(errno));
return;
}
for (const auto& s : settings) {
fprintf(pFile, "%s\n", s.c_str());
}
fclose(pFile);
}
StringVector OptionsFile::getOptionStrings() {
StringVector returnVector;
FILE* pFile = fopen(settingsPath.c_str(), "w");
FILE* pFile = fopen(settingsPath.c_str(), "r");
if(pFile != NULL) {
char lineBuff[128];
while(fgets(lineBuff, sizeof lineBuff, pFile)) {
if(strlen(lineBuff) > 2)
returnVector.push_back(std::string(lineBuff));
// Strip trailing newline
size_t len = strlen(lineBuff);
while(len > 0 && (lineBuff[len-1] == '\n' || lineBuff[len-1] == '\r'))
lineBuff[--len] = '\0';
if(len < 3) continue;
// Split "key:value" into two separate entries to match update() pairing
char* colon = strchr(lineBuff, ':');
if(colon) {
returnVector.push_back(std::string(lineBuff, colon - lineBuff));
returnVector.push_back(std::string(colon + 1));
}
}
fclose(pFile);
} else {
if (errno != ENOENT)
LOGI("OptionsFile::getOptionStrings failed to open '%s' for reading: %s", settingsPath.c_str(), strerror(errno));
}
return returnVector;
}

View File

@@ -1,5 +1,4 @@
#ifndef NET_MINECRAFT_CLIENT__OptionsFile_H__
#define NET_MINECRAFT_CLIENT__OptionsFile_H__
#pragma once
//package net.minecraft.client;
#include <string>
@@ -11,9 +10,10 @@ public:
OptionsFile();
void save(const StringVector& settings);
StringVector getOptionStrings();
void setOptionsPath(const std::string& path);
std::string getOptionsPath() const;
private:
std::string settingsPath;
};
#endif /* NET_MINECRAFT_CLIENT__OptionsFile_H__ */

View File

@@ -1,8 +1,7 @@
#ifndef NET_MINECRAFT_CLIENT__Timer_H__
#define NET_MINECRAFT_CLIENT__Timer_H__
#pragma once
//package net.minecraft.client;
#include "../platform/time.h"
#include "platform/time.hpp"
class Timer
{
@@ -121,4 +120,3 @@ private:
float adjustTime;
};
#endif /*NET_MINECRAFT_CLIENT__Timer_H__*/

View File

@@ -1,62 +0,0 @@
#ifndef NET_MINECRAFT_CLIENT__User_H__
#define NET_MINECRAFT_CLIENT__User_H__
//package net.minecraft.client;
#include "../world/level/tile/Tile.h"
class User
{
public:
//static List<Tile> allowedTiles = /*new*/ ArrayList<Tile>();
//static {
// allowedTiles.push_back(Tile::rock);
// allowedTiles.push_back(Tile::stoneBrick);
// allowedTiles.push_back(Tile::redBrick);
// allowedTiles.push_back(Tile::dirt);
// allowedTiles.push_back(Tile::wood);
// allowedTiles.push_back(Tile::treeTrunk);
// allowedTiles.push_back(Tile::leaves);
// allowedTiles.push_back(Tile::torch);
// allowedTiles.push_back(Tile::stoneSlabHalf);
// allowedTiles.push_back(Tile::glass);
// allowedTiles.push_back(Tile::mossStone);
// allowedTiles.push_back(Tile::sapling);
// allowedTiles.push_back(Tile::flower);
// allowedTiles.push_back(Tile::rose);
// allowedTiles.push_back(Tile::mushroom1);
// allowedTiles.push_back(Tile::mushroom2);
// allowedTiles.push_back(Tile::sand);
// allowedTiles.push_back(Tile::gravel);
// allowedTiles.push_back(Tile::sponge);
// allowedTiles.push_back(Tile::cloth);
// allowedTiles.push_back(Tile::coalOre);
// allowedTiles.push_back(Tile::ironOre);
// allowedTiles.push_back(Tile::goldOre);
// allowedTiles.push_back(Tile::ironBlock);
// allowedTiles.push_back(Tile::goldBlock);
// allowedTiles.push_back(Tile::bookshelf);
// allowedTiles.push_back(Tile::tnt);
// allowedTiles.push_back(Tile::obsidian);
// // System.out.println(allowedTiles.size());
//}
static bool isTileAllowed(const Tile& tile) {
return true;
}
std::string name;
std::string sessionId;
//std::string mpPassword;
User(const std::string& name, const std::string& sessionId) {
this->name = name;
this->sessionId = sessionId;
}
};
#endif /*NET_MINECRAFT_CLIENT__User_H__*/

View File

@@ -1,72 +0,0 @@
#include "CreativeMode.h"
#include "../Minecraft.h"
#ifndef STANDALONE_SERVER
#include "../particle/ParticleEngine.h"
#endif
#include "../player/LocalPlayer.h"
#ifndef STANDALONE_SERVER
#include "../renderer/LevelRenderer.h"
#include "../sound/SoundEngine.h"
#endif
#include "../../world/level/Level.h"
//#include "../../network/Packet.h"
#include "../../network/packet/RemoveBlockPacket.h"
#include "../../world/entity/player/Abilities.h"
static const int DestructionTickDelay = 10;
CreativeMode::CreativeMode(Minecraft* minecraft)
: super(minecraft)
{
}
void CreativeMode::startDestroyBlock(int x, int y, int z, int face) {
if(minecraft->player->getCarriedItem() != NULL && minecraft->player->getCarriedItem()->id == Item::bow->id)
return;
creativeDestroyBlock(x, y, z, face);
destroyDelay = DestructionTickDelay;
}
void CreativeMode::creativeDestroyBlock(int x, int y, int z, int face) {
//if (!
minecraft->level->extinguishFire(x, y, z, face)
//{
;
destroyBlock(x, y, z, face);
//}
}
void CreativeMode::continueDestroyBlock(int x, int y, int z, int face) {
destroyDelay--;
if (destroyDelay <= 0) {
destroyDelay = DestructionTickDelay;
creativeDestroyBlock(x, y, z, face);
}
}
void CreativeMode::stopDestroyBlock() {
}
void CreativeMode::initAbilities( Abilities& abilities ) {
abilities.mayfly = true;
abilities.instabuild = true;
abilities.invulnerable = true;
}
bool CreativeMode::isCreativeType() {
return true;
}
void CreativeMode::releaseUsingItem( Player* player ) {
if(player->getCarriedItem() != NULL) {
int oldItemId = player->getCarriedItem()->id;
int oldAux = player->getAuxData();
super::releaseUsingItem(player);
if(player->getCarriedItem() != NULL && player->getCarriedItem()->id == oldItemId) {
player->getCarriedItem()->setAuxValue(oldAux);
}
} else {
super::releaseUsingItem(player);
}
}

View File

@@ -1,27 +0,0 @@
#ifndef NET_MINECRAFT_CLIENT_GAMEMODE__CreativeMode_H__
#define NET_MINECRAFT_CLIENT_GAMEMODE__CreativeMode_H__
//package net.minecraft.client.gamemode;
#include "GameMode.h"
class CreativeMode: public GameMode
{
typedef GameMode super;
public:
CreativeMode(Minecraft* minecraft);
void startDestroyBlock(int x, int y, int z, int face);
void continueDestroyBlock(int x, int y, int z, int face);
void stopDestroyBlock();
bool isCreativeType();
void initAbilities(Abilities& abilities);
void releaseUsingItem(Player* player);
private:
void creativeDestroyBlock(int x, int y, int z, int face);
};
#endif /*NET_MINECRAFT_CLIENT_GAMEMODE__CreativeMode_H__*/

View File

@@ -1,98 +0,0 @@
#include "SurvivalMode.h"
#include "../Minecraft.h"
#include "../player/LocalPlayer.h"
#ifndef STANDALONE_SERVER
#include "../particle/ParticleEngine.h"
#include "../sound/SoundEngine.h"
#endif
#include "../../world/level/Level.h"
#include "../../world/entity/player/Abilities.h"
SurvivalMode::SurvivalMode( Minecraft* minecraft )
: super(minecraft),
xDestroyBlock(-1),
yDestroyBlock(-1),
zDestroyBlock(-1)
{
}
void SurvivalMode::continueDestroyBlock( int x, int y, int z, int face ) {
if (destroyDelay > 0) {
destroyDelay--;
return;
}
if (x == xDestroyBlock && y == yDestroyBlock && z == zDestroyBlock) {
int t = minecraft->level->getTile(x, y, z);
if (t == 0) return;
Tile* tile = Tile::tiles[t];
destroyProgress += tile->getDestroyProgress(minecraft->player);
if ((++destroyTicks & 3) == 1) {
#ifndef STANDALONE_SERVER
if (tile != NULL) {
minecraft->soundEngine->play(tile->soundType->getStepSound(), x + 0.5f, y + 0.5f, z + 0.5f, (tile->soundType->getVolume() + 1) / 8, tile->soundType->getPitch() * 0.5f);
}
#endif
}
if (destroyProgress >= 1) {
destroyBlock(x, y, z, face);
destroyProgress = 0;
oDestroyProgress = 0;
destroyTicks = 0;
destroyDelay = 5;
}
} else {
destroyProgress = 0;
oDestroyProgress = 0;
destroyTicks = 0;
xDestroyBlock = x;
yDestroyBlock = y;
zDestroyBlock = z;
}
}
bool SurvivalMode::destroyBlock( int x, int y, int z, int face ) {
int t = minecraft->level->getTile(x, y, z);
int data = minecraft->level->getData(x, y, z);
bool changed = GameMode::destroyBlock(x, y, z, face);
bool couldDestroy = minecraft->player->canDestroy(Tile::tiles[t]);
ItemInstance* item = minecraft->player->inventory->getSelected();
if (item != NULL) {
item->mineBlock(t, x, y, z);
if (item->count == 0) {
//item->snap(minecraft->player);
minecraft->player->inventory->clearSlot(minecraft->player->inventory->selected);
}
}
if (changed && couldDestroy) {
ItemInstance instance(t, 1, data);
Tile::tiles[t]->playerDestroy(minecraft->level, minecraft->player, x, y, z, data);
}
return changed;
}
void SurvivalMode::stopDestroyBlock() {
destroyProgress = 0;
destroyDelay = 0;
}
void SurvivalMode::initAbilities( Abilities& abilities ) {
abilities.flying = false;
abilities.mayfly = false;
abilities.instabuild = false;
abilities.invulnerable = false;
}
void SurvivalMode::startDestroyBlock( int x, int y, int z, int face ) {
if(minecraft->player->getCarriedItem() != NULL && minecraft->player->getCarriedItem()->id == Item::bow->id)
return;
int t = minecraft->level->getTile(x, y, z);
if (t > 0 && destroyProgress == 0) Tile::tiles[t]->attack(minecraft->level, x, y, z, minecraft->player);
if (t > 0 && Tile::tiles[t]->getDestroyProgress(minecraft->player) >= 1)
destroyBlock(x, y, z, face);
}

View File

@@ -1,31 +0,0 @@
#ifndef NET_MINECRAFT_CLIENT_GAMEMODE__SurvivalMode_H__
#define NET_MINECRAFT_CLIENT_GAMEMODE__SurvivalMode_H__
#include "GameMode.h"
class Abilities;
class Minecraft;
class SurvivalMode: public GameMode
{
typedef GameMode super;
public:
SurvivalMode(Minecraft* minecraft);
bool destroyBlock(int x, int y, int z, int face);
void startDestroyBlock(int x, int y, int z, int face);
void continueDestroyBlock(int x, int y, int z, int face);
void stopDestroyBlock();
bool canHurtPlayer() { return true; }
bool isSurvivalType() { return true; }
void initAbilities( Abilities& abilities );
private:
int xDestroyBlock;
int yDestroyBlock;
int zDestroyBlock;
};
#endif /*NET_MINECRAFT_CLIENT_GAMEMODE__SurvivalMode_H__*/

View File

@@ -1,10 +1,10 @@
#include "Font.h"
#include "Font.hpp"
//#include "SharedConstants.h"
#include "../Options.h"
#include "../renderer/Textures.h"
#include "../renderer/Tesselator.h"
#include "../../util/Mth.h"
//#include "SharedConstants.hpp"
#include "client/Options.hpp"
#include "client/renderer/Textures.hpp"
#include "client/renderer/Tesselator.hpp"
#include "util/Mth.hpp"
#include <cstring>
Font::Font( Options* options, const std::string& name, Textures* textures )
@@ -186,7 +186,7 @@ void Font::draw( const std::string& str, float x, float y, int color, bool darke
glPushMatrix2();
glTranslatef2((GLfloat)x, (GLfloat)y, 0.0f);
for (unsigned int i = 0; i < str.length(); i++) {
while (str.length() > i + 1 && str[i] == '<EFBFBD>') {
while (str.length() > i + 1 && str[i] == '\xa7') {
int cc = hex.find((char)tolower(str[i + 1]));
if (cc < 0 || cc > 15) cc = 15;
lists[index++] = listPos + 256 + cc + (darken ? 16 : 0);
@@ -235,7 +235,7 @@ int Font::width( const std::string& str )
int len = 0;
for (unsigned int i = 0; i < str.length(); i++) {
if (str[i] == '<EFBFBD>') {
if (str[i] == '\xa7') {
i++;
} else {
//int ch = SharedConstants.acceptableLetters.indexOf(str.charAt(i));
@@ -274,7 +274,7 @@ std::string Font::sanitize( const std::string& str )
int j = 0;
for (unsigned int i = 0; i < str.length(); i++) {
if (str[i] == '<EFBFBD>') {
if (str[i] == '\xa7') {
i++;
//} else if (SharedConstants.acceptableLetters.indexOf(str.charAt(i)) >= 0) {
} else {

View File

@@ -1,12 +1,11 @@
#ifndef NET_MINECRAFT_CLIENT_GUI__Font_H__
#define NET_MINECRAFT_CLIENT_GUI__Font_H__
#pragma once
//package net.minecraft.client.gui;
#include <string>
#include <cctype>
#include "../renderer/gles.h"
#include "client/renderer/gles.hpp"
class Textures;
class Options;
@@ -60,4 +59,3 @@ private:
unsigned char _charOffset;
};
#endif /*NET_MINECRAFT_CLIENT_GUI__Font_H__*/

View File

@@ -1,25 +1,36 @@
#include "Gui.h"
#include "Font.h"
#include "screens/IngameBlockSelectionScreen.h"
#include "../Minecraft.h"
#include "../player/LocalPlayer.h"
#include "../renderer/Tesselator.h"
#include "../renderer/TileRenderer.h"
#include "../renderer/LevelRenderer.h"
#include "../renderer/GameRenderer.h"
#include "../renderer/entity/ItemRenderer.h"
#include "../player/input/IInputHolder.h"
#include "../gamemode/GameMode.h"
#include "../gamemode/CreativeMode.h"
#include "../renderer/Textures.h"
#include "../../AppConstants.h"
#include "../../world/entity/player/Inventory.h"
#include "../../world/level/material/Material.h"
#include "../../world/item/Item.h"
#include "../../world/item/ItemInstance.h"
#include "../../platform/input/Mouse.h"
#include "../../world/level/Level.h"
#include "../../world/PosTranslator.h"
#include "Gui.hpp"
#include "Font.hpp"
#include "MinecraftClient.hpp"
#include "client/Options.hpp"
#include "platform/input/Keyboard.hpp"
#include "screens/IngameBlockSelectionScreen.hpp"
#include "screens/ChatScreen.hpp"
#include "screens/ConsoleScreen.hpp"
#include <Minecraft.hpp>
#include "client/player/LocalPlayer.hpp"
#include "client/renderer/Tesselator.hpp"
#include "client/renderer/TileRenderer.hpp"
#include "client/renderer/LevelRenderer.hpp"
#include "client/renderer/GameRenderer.hpp"
#include "client/renderer/entity/ItemRenderer.hpp"
#include "client/player/input/IInputHolder.hpp"
#include "client/gamemode/GameMode.hpp"
#include "client/gamemode/CreativeMode.hpp"
#include "client/renderer/Textures.hpp"
#include "AppConstants.hpp"
#include "world/entity/player/Inventory.hpp"
#include "world/level/material/Material.hpp"
#include "world/item/Item.hpp"
#include "world/item/ItemInstance.hpp"
#include "platform/input/Mouse.hpp"
#include "world/level/Level.hpp"
#include "world/PosTranslator.hpp"
#include "platform/time.hpp"
#include <cmath>
#include <algorithm>
#include <sstream>
#define MAX_MESSAGE_WIDTH 240
float Gui::InvGuiScale = 1.0f / 3.0f;
float Gui::GuiScale = 1.0f / Gui::InvGuiScale;
@@ -27,31 +38,15 @@ const float Gui::DropTicks = 40.0f;
//#include <android/log.h>
Gui::Gui(Minecraft* minecraft)
: minecraft(minecraft),
tickCount(0),
progress(0),
overlayMessageTime(0),
animateOverlayMessageColor(false),
tbr(1),
_inventoryNeedsUpdate(true),
_flashSlotId(-1),
_flashSlotStartTime(-1),
_slotFont(NULL),
_numSlots(4),
_currentDropTicks(-1),
_currentDropSlot(-1),
MAX_MESSAGE_WIDTH(240),
itemNameOverlayTime(2)
{
// @todo virtual controlConfigurationChanged() when player switches from keyboard to touch for example
Gui::Gui(MinecraftClient& minecraft) : minecraft(minecraft), _openInventorySlot(minecraft.useTouchscreen()) {
glGenBuffers2(1, &_inventoryRc.vboId);
glGenBuffers2(1, &rcFeedbackInner.vboId);
glGenBuffers2(1, &rcFeedbackOuter.vboId);
//Gui::InvGuiScale = 1.0f / (int) (3 * Minecraft::width / 854);
}
Gui::~Gui()
{
Gui::~Gui() {
if (_slotFont)
delete _slotFont;
@@ -59,20 +54,16 @@ Gui::~Gui()
}
void Gui::render(float a, bool mouseFree, int xMouse, int yMouse) {
if (!minecraft->level || !minecraft->player)
if (!minecraft.level || !minecraft.getPlayer())
return;
//minecraft->gameRenderer->setupGuiScreen();
Font* font = minecraft->font;
Font* font = minecraft.getFont();
#ifdef PLATFORM_DESKTOP
const bool isTouchInterface = false;
#else
const bool isTouchInterface = minecraft->useTouchscreen();
#endif
const int screenWidth = (int)(minecraft->width * InvGuiScale);
const int screenHeight = (int)(minecraft->height * InvGuiScale);
const bool isTouchInterface = minecraft.useTouchscreen();
const int screenWidth = (int)(minecraft.getScreenWidth() * InvGuiScale);
const int screenHeight = (int)(minecraft.getScreenHeigth() * InvGuiScale);
blitOffset = -90;
renderProgressIndicator(isTouchInterface, screenWidth, screenHeight, a);
@@ -84,8 +75,9 @@ void Gui::render(float a, bool mouseFree, int xMouse, int yMouse) {
// F: 3
int ySlot = screenHeight - 16 - 3;
if (minecraft->gameMode->canHurtPlayer()) {
minecraft->textures->loadAndBindTexture("gui/icons.png");
if (!minecraft.options.getBooleanValue(OPTIONS_HIDEGUI)) {
if (minecraft.gameMode->canHurtPlayer()) {
minecraft.getTextures()->loadAndBindTexture("gui/icons.png");
Tesselator& t = Tesselator::instance;
t.beginOverride();
t.colorABGR(0xffffffff);
@@ -93,8 +85,9 @@ void Gui::render(float a, bool mouseFree, int xMouse, int yMouse) {
renderBubbles();
t.endOverrideAndDraw();
}
}
if(minecraft->player->getSleepTimer() > 0) {
if(minecraft.getPlayer()->getSleepTimer() > 0) {
glDisable(GL_DEPTH_TEST);
glDisable(GL_ALPHA_TEST);
@@ -103,18 +96,22 @@ void Gui::render(float a, bool mouseFree, int xMouse, int yMouse) {
glEnable(GL_ALPHA_TEST);
glEnable(GL_DEPTH_TEST);
}
if (!minecraft.options.getBooleanValue(OPTIONS_HIDEGUI)) {
renderToolBar(a, ySlot, screenWidth);
//font->drawShadow(APP_NAME, 2, 2, 0xffffffff);
//font->drawShadow("This is a demo, not the finished product", 2, 10 + 2, 0xffffffff);
#ifdef APPLE_DEMO_PROMOTION
font->drawShadow("Demo version", 2, 0 + 2, 0xffffffff);
#endif /*APPLE_DEMO_PROMOTION*/
glEnable(GL_BLEND);
bool isChatting = (minecraft->screen && (dynamic_cast<ChatScreen*>(minecraft->screen) || dynamic_cast<ConsoleScreen*>(minecraft->screen)));
unsigned int max = 10;
bool isChatting = false;
if (isChatting) {
int lineHeight = 9;
max = (screenHeight - 48) / lineHeight;
if (max < 1) max = 1;
int maxScroll = (int)guiMessages.size() - (int)max;
if (maxScroll < 0) maxScroll = 0;
if (chatScrollOffset > maxScroll) chatScrollOffset = maxScroll;
} else {
chatScrollOffset = 0;
}
renderChatMessages(screenHeight, max, isChatting, font);
#if !defined(RPI)
renderOnSelectItemNameText(screenWidth, font, ySlot);
@@ -123,9 +120,14 @@ void Gui::render(float a, bool mouseFree, int xMouse, int yMouse) {
renderDebugInfo();
#endif
// glPopMatrix2();
//
// glEnable(GL_ALPHA_TEST);
if (Keyboard::isKeyDown(Keyboard::KEY_TAB)) {
renderPlayerList(font, screenWidth, screenHeight);
}
if (minecraft->options.getBooleanValue(OPTIONS_RENDER_DEBUG))
renderDebugInfo();
}
glDisable(GL_BLEND);
glEnable2(GL_ALPHA_TEST);
}
@@ -186,14 +188,10 @@ void Gui::handleClick(int button, int x, int y) {
if (button != MouseAction::ACTION_LEFT) return;
int slot = getSlotIdAt(x, y);
if (slot != -1)
{
if (slot == (getNumSlots()-1))
{
if (slot != -1) {
if (_openInventorySlot && slot == (getNumSlots()-1)) {
minecraft->screenChooser.setScreen(SCREEN_BLOCKSELECTION);
}
else
{
} else {
minecraft->player->inventory->selectSlot(slot);
itemNameOverlayTime = 0;
}
@@ -202,6 +200,33 @@ void Gui::handleClick(int button, int x, int y) {
void Gui::handleKeyPressed(int key)
{
bool isChatting = (minecraft->screen && (dynamic_cast<ChatScreen*>(minecraft->screen) || dynamic_cast<ConsoleScreen*>(minecraft->screen)));
if (isChatting) {
// Allow scrolling the chat history with the mouse/keyboard when chat is open
if (key == 38) { // VK_UP
scrollChat(1);
return;
} else if (key == 40) { // VK_DOWN
scrollChat(-1);
return;
} else if (key == 33) { // VK_PRIOR (Page Up)
// Scroll by a page
int screenHeight = (int)(minecraft->height * InvGuiScale);
int maxVisible = (screenHeight - 48) / 9;
scrollChat(maxVisible);
return;
} else if (key == 34) { // VK_NEXT (Page Down)
int screenHeight = (int)(minecraft->height * InvGuiScale);
int maxVisible = (screenHeight - 48) / 9;
scrollChat(-maxVisible);
return;
}
}
if (key == Keyboard::KEY_F1) {
minecraft->options.toggle(OPTIONS_HIDEGUI);
}
if (key == 99)
{
if (minecraft->player->inventory->selected > 0)
@@ -220,6 +245,27 @@ void Gui::handleKeyPressed(int key)
{
minecraft->screenChooser.setScreen(SCREEN_BLOCKSELECTION);
}
else if (key == minecraft->options.getIntValue(OPTIONS_KEY_DROP))
{
minecraft->player->inventory->dropSlot(minecraft->player->inventory->selected, false);
}
}
void Gui::scrollChat(int delta) {
if (delta == 0)
return;
int screenHeight = (int)(minecraft->height * InvGuiScale);
int maxVisible = (screenHeight - 48) / 9;
if (maxVisible <= 0)
return;
int maxScroll = (int)guiMessages.size() - maxVisible;
if (maxScroll < 0) maxScroll = 0;
int desired = chatScrollOffset + delta;
if (desired < 0) desired = 0;
if (desired > maxScroll) desired = maxScroll;
chatScrollOffset = desired;
}
void Gui::tick() {
@@ -252,9 +298,22 @@ void Gui::addMessage(const std::string& _string) {
message.message = string;
message.ticks = 0;
guiMessages.insert(guiMessages.begin(), message);
while (guiMessages.size() > 30) {
// Keep a larger history so users can scroll through the full chat
const unsigned int MaxHistoryLines = 200;
while (guiMessages.size() > MaxHistoryLines) {
guiMessages.pop_back();
}
// If the user has scrolled up, keep their window fixed (new messages shift older ones down)
if (chatScrollOffset > 0) {
chatScrollOffset++;
}
}
void Gui::clearMessages() {
guiMessages.clear();
chatScrollOffset = 0;
}
void Gui::setNowPlaying(const std::string& string) {
@@ -266,7 +325,7 @@ void Gui::setNowPlaying(const std::string& string) {
void Gui::displayClientMessage(const std::string& messageId) {
//Language language = Language.getInstance();
//std::string languageString = language.getElement(messageId);
addMessage(std::string("Client message: ") + messageId);
addMessage(messageId);
}
void Gui::renderVignette(float br, int w, int h) {
@@ -347,9 +406,9 @@ void Gui::onConfigChanged( const Config& c ) {
// Create outer feedback circle
//
#ifdef ANDROID
const float mm = 12;
const float mm = 50; //20
#else
const float mm = 12;
const float mm = 50; //20
#endif
const float maxRadius = minecraft->pixelCalcUi.millimetersToPixels(mm);
const float radius = Mth::Min(80.0f/2, maxRadius);
@@ -395,10 +454,11 @@ void Gui::onConfigChanged( const Config& c ) {
//LOGI("x,y: %f, %f\n", xx, yy);
}
rcFeedbackInner = t.end(true, rcFeedbackInner.vboId);
if (c.minecraft->useTouchscreen()) {
// I'll bump this up to 6.
int num = 6; // without "..." dots
if (!c.minecraft->options.isJoyTouchArea && c.width > 480) {
if (!c.minecraft->options.getBooleanValue(OPTIONS_IS_JOY_TOUCH_AREA) && c.width > 480) {
while (num < Inventory::MAX_SELECTION_SIZE - 1) {
int x0, x1, y;
getSlotPos(0, x0, y);
@@ -452,9 +512,12 @@ void Gui::tickItemDrop()
// Handle item drop
static bool isCurrentlyActive = false;
isCurrentlyActive = false;
int slots = getNumSlots() - _openInventorySlot;
if (Mouse::isButtonDown(MouseAction::ACTION_LEFT)) {
int slot = getSlotIdAt(Mouse::getX(), Mouse::getY());
if (slot >= 0 && slot < getNumSlots()-1) {
if (slot >= 0 && slot < slots) {
if (slot != _currentDropSlot) {
_currentDropTicks = 0;
_currentDropSlot = slot;
@@ -505,7 +568,8 @@ void Gui::renderProgressIndicator( const bool isTouchInterface, const int screen
ItemInstance* currentItem = minecraft->player->inventory->getSelected();
bool bowEquipped = currentItem != NULL ? currentItem->getItem() == Item::bow : false;
bool itemInUse = currentItem != NULL ? currentItem->getItem() == minecraft->player->getUseItem()->getItem() : false;
if (!isTouchInterface || minecraft->options.isJoyTouchArea || (bowEquipped && itemInUse)) {
if ((!isTouchInterface || minecraft->options.getBooleanValue(OPTIONS_IS_JOY_TOUCH_AREA)
|| (bowEquipped && itemInUse)) && !minecraft->options.getBooleanValue(OPTIONS_HIDEGUI)) {
minecraft->textures->loadAndBindTexture("gui/icons.png");
glEnable(GL_BLEND);
glBlendFunc2(GL_ONE_MINUS_DST_COLOR, GL_ONE_MINUS_SRC_COLOR);
@@ -574,11 +638,14 @@ void Gui::renderHearts() {
int oh = minecraft->player->lastHealth;
random.setSeed(tickCount * 312871);
int xx = 2;//screenWidth / 2 - getNumSlots() * 10;
int screenWidth = (int)(minecraft->width * InvGuiScale);
int screenHeight = (int)(minecraft->height * InvGuiScale);
int xx = (minecraft->options.getBooleanValue(OPTIONS_BAR_ON_TOP)) ? screenWidth / 2 - getNumSlots() * 10 - 1 : 2;
int armor = minecraft->player->getArmorValue();
for (int i = 0; i < Player::MAX_HEALTH / 2; i++) {
int yo = 2;
int yo = (minecraft->options.getBooleanValue(OPTIONS_BAR_ON_TOP)) ? screenHeight - 32 : 2;
int ip2 = i + i + 1;
if (armor > 0) {
@@ -606,11 +673,15 @@ void Gui::renderHearts() {
void Gui::renderBubbles() {
if (minecraft->player->isUnderLiquid(Material::water)) {
int yo = 12;
int screenWidth = (int)(minecraft->width * InvGuiScale);
int screenHeight = (int)(minecraft->height * InvGuiScale);
int xx = (minecraft->options.getBooleanValue(OPTIONS_BAR_ON_TOP)) ? screenWidth / 2 - getNumSlots() * 10 - 1 : 2;
int yo = (minecraft->options.getBooleanValue(OPTIONS_BAR_ON_TOP)) ? screenHeight - 42 : 12;
int count = (int) std::ceil((minecraft->player->airSupply - 2) * 10.0f / Player::TOTAL_AIR_SUPPLY);
int extra = (int) std::ceil((minecraft->player->airSupply) * 10.0f / Player::TOTAL_AIR_SUPPLY) - count;
for (int i = 0; i < count + extra; i++) {
int xo = i * 8 + 2;
int xo = i * 8 + xx;
if (i < count) blit(xo, yo, 16, 9 * 2, 9, 9);
else blit(xo, yo, 16 + 9, 9 * 2, 9, 9);
}
@@ -626,20 +697,169 @@ void Gui::onLevelGenerated() {
}
void Gui::renderDebugInfo() {
static char buf[256];
float xx = minecraft->player->x;
float yy = minecraft->player->y - minecraft->player->heightOffset;
float zz = minecraft->player->z;
posTranslator.to(xx, yy, zz);
sprintf(buf, "pos: %3.1f, %3.1f, %3.1f\n", xx, yy, zz);
// FPS counter (updates once per second)
static float fps = 0.0f;
static float fpsLastTime = 0.0f;
static int fpsFrames = 0;
float now = getTimeS();
fpsFrames++;
if (now - fpsLastTime >= 1.0f) {
fps = fpsFrames / (now - fpsLastTime);
fpsFrames = 0;
fpsLastTime = now;
}
LocalPlayer* p = minecraft->player;
Level* lvl = minecraft->level;
// Position
float px = p->x, py = p->y - p->heightOffset, pz = p->z;
posTranslator.to(px, py, pz);
int bx = (int)floorf(px), by = (int)floorf(py), bz = (int)floorf(pz);
int cx = bx >> 4, cz = bz >> 4;
// Facing direction
float yMod = fmodf(p->yRot, 360.0f);
if (yMod < 0) yMod += 360.0f;
const char* facing;
const char* axis;
if (yMod < 45 || yMod >= 315) { facing = "South"; axis = "+Z"; }
else if (yMod < 135) { facing = "West"; axis = "-X"; }
else if (yMod < 225) { facing = "North"; axis = "-Z"; }
else { facing = "East"; axis = "+X"; }
// Biome
const char* biomeName = "unknown";
if (lvl) {
Biome* biome = lvl->getBiome(bx, bz);
if (biome) biomeName = biome->name.c_str();
}
// Time
long worldTime = lvl ? lvl->getTime() : 0;
long dayTime = worldTime % Level::TICKS_PER_DAY;
long day = worldTime / Level::TICKS_PER_DAY;
long seed = lvl ? lvl->getSeed() : 0;
// Build lines (NULL entry = blank gap)
static char ln[8][96];
sprintf(ln[0], "Minecraft PE 0.6.1 alpha (mcpe64)");
sprintf(ln[1], "%.1f fps", fps);
ln[2][0] = '\0'; // blank separator
sprintf(ln[3], "XYZ: %.3f / %.3f / %.3f", px, py, pz);
sprintf(ln[4], "Block: %d %d %d Chunk: %d %d", bx, by, bz, cx, cz);
sprintf(ln[5], "Facing: %s (%s) (%.1f / %.1f)", facing, axis, p->yRot, p->xRot);
sprintf(ln[6], "Biome: %s", biomeName);
sprintf(ln[7], "Day %ld Time: %ld Seed: %ld", day, dayTime, seed);
const int N = 8;
const float LH = (float)Font::DefaultLineHeight; // 10 font-pixels
const float MGN = 2.0f; // left/top margin in font-pixels
const float PAD = 2.0f; // horizontal padding for background
Font* font = minecraft->font;
// 1) Draw semi-transparent background boxes behind each line
for (int i = 0; i < N; i++) {
if (ln[i][0] == '\0') continue;
float w = (float)font->width(ln[i]);
float x0 = MGN - PAD;
float y0 = MGN + i * LH - 1.0f;
float x1 = MGN + w + PAD;
float y1 = MGN + (i + 1) * LH - 1.0f;
fill(x0, y0, x1, y1, 0x90000000);
}
// 2) Draw text (no extra scale — font coords are in GUI units, same as fill)
Tesselator& t = Tesselator::instance;
t.beginOverride();
t.scale2d(InvGuiScale, InvGuiScale);
minecraft->font->draw(buf, 2, 2, 0xffffff);
t.resetScale();
for (int i = 0; i < N; i++) {
if (ln[i][0] == '\0') continue;
float y = MGN + i * LH;
int col = (i == 0) ? 0xffFFFF55 : 0xffffffff; // title yellow, rest white
font->draw(ln[i], MGN, y, col);
}
t.endOverrideAndDraw();
}
void Gui::renderPlayerList(Font* font, int screenWidth, int screenHeight) {
// only show when in game, no other screen
// if (!minecraft->level) return;
// only show the overlay while connected to a multiplayer server
Level* level = minecraft->level;
if (!level) return;
if (!level->isClientSide) return;
std::vector<std::string> playerNames;
playerNames.reserve(level->players.size());
for (Player* player : level->players) {
if (!player) continue;
playerNames.push_back(player->name);
}
// is this check needed? if there are no players, the box won't render at all since height will be 0,
// but maybe we want to skip rendering entirely in that case
// if (playerNames.empty())
// return;
std::sort(playerNames.begin(), playerNames.end());
float maxNameWidth = 0.0f;
// find the longest name so we can size the box accordingly
for (const std::string& name : playerNames) {
float nameWidth = font->width(name);
if (nameWidth > maxNameWidth)
maxNameWidth = nameWidth;
}
// player count title
std::ostringstream titleStream;
titleStream << "Players (" << playerNames.size() << ")";
std::string titleText = titleStream.str();
float titleWidth = font->width(titleText);
if (titleWidth > maxNameWidth)
maxNameWidth = titleWidth;
const float padding = 4.0f;
const float lineHeight = (float)Font::DefaultLineHeight;
const float boxWidth = maxNameWidth + padding * 2;
const float boxHeight = (playerNames.size() + 1) * lineHeight + padding * 2;
const float boxLeft = (screenWidth - boxWidth) / 2.0f;
const float boxTop = 10.0f;
const float boxRight = boxLeft + boxWidth;
const float boxBottom = boxTop + boxHeight;
fill(boxLeft, boxTop, boxRight, boxBottom, 0x90000000);
float titleX = (screenWidth - titleWidth) / 2.0f;
float titleY = boxTop + padding;
// scale the text down slightly
// i think the gl scaling is the best for this
// oh my god this looks really bad OH GOD
//const float textScale = 0.8f;
//const float invTextScale = 1.0f / textScale;
//glPushMatrix2();
//glScalef2(textScale, textScale, 1);
// draw title
//font->draw(titleText, titleX * invTextScale, titleY * invTextScale, 0xFFFFFFFF);
font->draw(titleText, titleX, titleY, 0xFFFFFFFF);
// draw player names
// we should add ping icons here eventually, but for now just show names
float currentY = boxTop + padding + lineHeight;
for (const std::string& name : playerNames) {
font->draw(name, (boxLeft + padding), currentY, 0xFFDDDDDD);
currentY += lineHeight;
}
//glPopMatrix2();
}
void Gui::renderSleepAnimation( const int screenWidth, const int screenHeight ) {
int timer = minecraft->player->getSleepTimer();
float amount = (float) timer / (float) Player::SLEEP_DURATION;
@@ -670,6 +890,70 @@ void Gui::renderOnSelectItemNameText( const int screenWidth, Font* font, int ySl
}
}
// helper structure used by drawColoredString
struct ColorSegment {
std::string text;
uint32_t color;
};
// parse [tag] and [/tag] markers; tags may contain a color name (gold, green, etc.)
static void parseColorTags(const std::string& in, std::vector<ColorSegment>& out) {
uint32_t curColor = 0xffffff;
size_t pos = 0;
while (pos < in.size()) {
size_t open = in.find('[', pos);
if (open == std::string::npos) {
out.push_back({in.substr(pos), curColor});
break;
}
if (open > pos) {
out.push_back({in.substr(pos, open - pos), curColor});
}
size_t close = in.find(']', open);
if (close == std::string::npos) {
out.push_back({in.substr(open), curColor});
break;
}
std::string tag = in.substr(open + 1, close - open - 1);
if (!tag.empty() && tag[0] == '/') {
curColor = 0xffffff;
} else {
std::string lower;
lower.resize(tag.size());
std::transform(tag.begin(), tag.end(), lower.begin(), ::tolower);
if (lower.find("gold") != std::string::npos) curColor = 0xffd700;
else if (lower.find("green") != std::string::npos) curColor = 0x00ff00;
else if (lower.find("yellow") != std::string::npos) curColor = 0xffff00;
else if (lower.find("red") != std::string::npos) curColor = 0xff0000;
else if (lower.find("blue") != std::string::npos) curColor = 0x0000ff;
}
pos = close + 1;
}
}
void Gui::drawColoredString(Font* font, const std::string& text, float x, float y, int alpha) {
std::vector<ColorSegment> segs;
parseColorTags(text, segs);
float cx = x;
for (auto &s : segs) {
int color = s.color + (alpha << 24);
font->drawShadow(s.text, cx, y, color);
cx += font->width(s.text);
}
}
float Gui::getColoredWidth(Font* font, const std::string& text) {
std::vector<ColorSegment> segs;
parseColorTags(text, segs);
float w = 0;
for (auto &s : segs) {
w += font->width(s.text);
}
return w;
}
void Gui::renderChatMessages( const int screenHeight, unsigned int max, bool isChatting, Font* font ) {
// if (minecraft.screen instanceof ChatScreen) {
// max = 20;
@@ -685,9 +969,16 @@ void Gui::renderChatMessages( const int screenHeight, unsigned int max, bool isC
// // glScalef2(1.0f / ssc.scale, 1.0f / ssc.scale, 1);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
int baseY = screenHeight - 48;
for (unsigned int i = 0; i < guiMessages.size() && i < max; i++) {
if (guiMessages.at(i).ticks < 20 * 10 || isChatting) {
float t = guiMessages.at(i).ticks / (20 * 10.0f);
int start = chatScrollOffset;
if (start < 0) start = 0;
for (unsigned int i = 0; i < max; i++) {
unsigned int msgIdx = (unsigned int)start + i;
if (msgIdx >= guiMessages.size())
break;
GuiMessage& message = guiMessages.at(msgIdx);
if (message.ticks < 20 * 10 || isChatting) {
float t = message.ticks / (20 * 10.0f);
t = 1 - t;
t = t * 10;
if (t < 0) t = 0;
@@ -699,11 +990,18 @@ void Gui::renderChatMessages( const int screenHeight, unsigned int max, bool isC
if (alpha > 0) {
const float x = 2;
const float y = (float)(baseY - i * 9);
std::string msg = guiMessages.at(i).message;
std::string msg = message.message;
this->fill(x, y - 1, x + MAX_MESSAGE_WIDTH, y + 8, (alpha / 2) << 24);
glEnable(GL_BLEND);
font->drawShadow(msg, x, y, 0xffffff + (alpha << 24));
// special-case join/leave announcements
int baseColor = 0xffffff;
if (msg.find(" joined the game") != std::string::npos ||
msg.find(" left the game") != std::string::npos) {
baseColor = 0xffff00; // yellow
}
// replace previous logic; allow full colour tags now
Gui::drawColoredString(font, msg, x, y, alpha);
}
}
}
@@ -756,20 +1054,19 @@ void Gui::renderToolBar( float a, int ySlot, const int screenWidth ) {
t.beginOverride();
float x = baseItemX;
for (int i = 0; i < getNumSlots()-1; i++) {
int slots = getNumSlots() - _openInventorySlot;
for (int i = 0; i < slots; i++) {
renderSlot(i, (int)x, ySlot, a);
x += 20;
}
_inventoryNeedsUpdate = false;
//_inventoryRc = t.end(_inventoryRc.vboId);
//drawArrayVTC(_inventoryRc.vboId, _inventoryRc.vertexCount);
//renderSlotWatch.stop();
//renderSlotWatch.printEvery(100, "Render slots:");
//int x = screenWidth / 2 + getNumSlots() * 10 + (getNumSlots()-1) * 20 + 2;
if (_openInventorySlot) {
blit(screenWidth / 2 + 10 * getNumSlots() - 20 + 4, ySlot + 6, 242, 252, 14, 4, 14, 4);
}
minecraft->textures->loadAndBindTexture("gui/gui_blocks.png");
t.endOverrideAndDraw();
@@ -779,7 +1076,7 @@ void Gui::renderToolBar( float a, int ySlot, const int screenWidth ) {
glDisable2(GL_TEXTURE_2D);
t.beginOverride();
x = baseItemX;
for (int i = 0; i < getNumSlots()-1; i++) {
for (int i = 0; i < slots; i++) {
ItemRenderer::renderGuiItemDecorations(minecraft->player->inventory->getItem(i), x, (float)ySlot);
x += 20;
}
@@ -799,7 +1096,7 @@ void Gui::renderToolBar( float a, int ySlot, const int screenWidth ) {
t.beginOverride();
if (minecraft->gameMode->isSurvivalType()) {
x = baseItemX;
for (int i = 0; i < getNumSlots()-1; i++) {
for (int i = 0; i < slots; i++) {
ItemInstance* item = minecraft->player->inventory->getItem(i);
if (item && item->count >= 0)
renderSlotText(item, k*x, k*ySlot + 1, true, true);

View File

@@ -1,16 +1,15 @@
#ifndef NET_MINECRAFT_CLIENT_GUI__Gui_H__
#define NET_MINECRAFT_CLIENT_GUI__Gui_H__
#pragma once
//package net.minecraft.client.gui;
#include "GuiComponent.h"
#include "Font.h"
#include "../player/input/touchscreen/TouchAreaModel.h"
#include "../renderer/RenderChunk.h"
#include "../../util/Random.h"
#include "../IConfigListener.h"
#include "GuiComponent.hpp"
#include "Font.hpp"
#include "client/player/input/touchscreen/TouchAreaModel.hpp"
#include "client/renderer/RenderChunk.hpp"
#include "util/Random.hpp"
#include "client/IConfigListener.hpp"
class Minecraft;
class MinecraftClient;
class ItemInstance;
class Textures;
class Tesselator;
@@ -27,7 +26,7 @@ typedef std::vector<GuiMessage> GuiMessageList;
class Gui: public GuiComponent, IConfigListener
{
public:
Gui(Minecraft* minecraft);
Gui(MinecraftClient& minecraft);
~Gui();
int getSlotIdAt(int x, int y);
@@ -39,6 +38,7 @@ public:
void handleClick(int button, int x, int y);
void handleKeyPressed( int key );
void scrollChat(int delta);
void tick();
void render(float a, bool mouseFree, int xMouse, int yMouse);
@@ -47,6 +47,12 @@ public:
void renderChatMessages( const int screenHeight, unsigned int max, bool isChatting, Font* font );
// draw a string containing simple [color]...[/color] tags; color names are matched
// case-insensitively and default to white. alpha is applied to each segment.
// draw tagged string (ignores simple [color]…[/color] tags)
static void drawColoredString(Font* font, const std::string& text, float x, float y, int alpha);
static float getColoredWidth(Font* font, const std::string& text);
void renderOnSelectItemNameText( const int screenWidth, Font* font, int ySlot );
void renderSleepAnimation( const int screenWidth, const int screenHeight );
@@ -54,10 +60,12 @@ public:
void renderBubbles();
void renderHearts();
void renderDebugInfo();
void renderPlayerList(Font* font, int screenWidth, int screenHeight);
void renderProgressIndicator( const bool isTouchInterface, const int screenWidth, const int screenHeight, float a );
void addMessage(const std::string& string);
void clearMessages();
void postError(int errCode);
void onGraphicsReset();
@@ -81,42 +89,43 @@ private:
void tickItemDrop();
float cubeSmoothStep(float percentage, float min, float max);
public:
float progress;
float progress = 0.f;
std::string selectedName;
static float InvGuiScale;
static float GuiScale;
private:
int MAX_MESSAGE_WIDTH;
//ItemRenderer itemRenderer;
GuiMessageList guiMessages;
int chatScrollOffset = 0;
Random random;
Minecraft* minecraft;
int tickCount;
float itemNameOverlayTime;
MinecraftClient& minecraft;
int tickCount = 0;
float itemNameOverlayTime = 2;
std::string overlayMessageString;
int overlayMessageTime;
bool animateOverlayMessageColor;
int overlayMessageTime = 0;
bool animateOverlayMessageColor = false;
float tbr;
float tbr = 1.f;
RenderChunk _inventoryRc;
bool _inventoryNeedsUpdate;
bool _inventoryNeedsUpdate = true;
int _flashSlotId;
float _flashSlotStartTime;
int _flashSlotId = -1;
float _flashSlotStartTime = -1;
Font* _slotFont;
int _numSlots;
Font* _slotFont = nullptr;
int _numSlots = 4;
RenderChunk rcFeedbackOuter;
RenderChunk rcFeedbackInner;
// For dropping
static const float DropTicks;
float _currentDropTicks;
int _currentDropSlot;
float _currentDropTicks = -1;
int _currentDropSlot = -1;
bool _openInventorySlot;
};
#endif /*NET_MINECRAFT_CLIENT_GUI__Gui_H__*/

View File

@@ -1,8 +1,8 @@
#include "GuiComponent.h"
#include "GuiComponent.hpp"
#include "../renderer/Tesselator.h"
#include "../renderer/gles.h"
#include "Font.h"
#include "client/renderer/Tesselator.hpp"
#include "client/renderer/gles.hpp"
#include "Font.hpp"
GuiComponent::GuiComponent()

View File

@@ -1,5 +1,4 @@
#ifndef NET_MINECRAFT_CLIENT_GUI__GuiComponent_H__
#define NET_MINECRAFT_CLIENT_GUI__GuiComponent_H__
#pragma once
//package net.minecraft.client.gui;
@@ -31,4 +30,3 @@ protected:
};
#endif /*NET_MINECRAFT_CLIENT_GUI__GuiComponent_H__*/

View File

@@ -1,12 +1,12 @@
#include "Screen.h"
#include "components/Button.h"
#include "components/TextBox.h"
#include "../Minecraft.h"
#include "../renderer/Tesselator.h"
#include "../sound/SoundEngine.h"
#include "../../platform/input/Keyboard.h"
#include "../../platform/input/Mouse.h"
#include "../renderer/Textures.h"
#include "Screen.hpp"
#include "components/Button.hpp"
#include "components/TextBox.hpp"
#include <Minecraft.hpp>
#include "client/renderer/Tesselator.hpp"
#include "client/sound/SoundEngine.hpp"
#include "platform/input/Keyboard.hpp"
#include "platform/input/Mouse.hpp"
#include "client/renderer/Textures.hpp"
Screen::Screen()
: passEvents(false),
@@ -25,6 +25,12 @@ void Screen::render( int xm, int ym, float a )
Button* button = buttons[i];
button->render(minecraft, xm, ym);
}
// render any text boxes after buttons
for (unsigned int i = 0; i < textBoxes.size(); i++) {
TextBox* textbox = textBoxes[i];
textbox->render(minecraft, xm, ym);
}
}
void Screen::init( Minecraft* minecraft, int width, int height )
@@ -72,6 +78,14 @@ void Screen::updateEvents()
void Screen::mouseEvent()
{
const MouseAction& e = Mouse::getEvent();
// forward wheel events to subclasses
if (e.action == MouseAction::ACTION_WHEEL) {
int xm = e.x * width / minecraft->width;
int ym = e.y * height / minecraft->height - 1;
mouseWheel(e.dx, e.dy, xm, ym);
return;
}
if (!e.isButton())
return;
@@ -98,7 +112,7 @@ void Screen::keyboardEvent()
}
void Screen::keyboardTextEvent()
{
keyboardNewChar(Keyboard::getChar());
charPressed(Keyboard::getChar());
}
void Screen::renderBackground()
{
@@ -157,20 +171,28 @@ void Screen::keyPressed( int eventKey )
minecraft->setScreen(NULL);
//minecraft->grabMouse();
}
// pass key events to any text boxes first
for (auto& textbox : textBoxes) {
textbox->keyPressed(minecraft, eventKey);
}
#ifdef TABBING
if (minecraft->useTouchscreen())
return;
// "Tabbing" the buttons (walking with keys)
const int tabButtonCount = tabButtons.size();
if (!tabButtonCount)
return;
Options& o = minecraft->options;
if (eventKey == o.keyMenuNext.key)
if (eventKey == o.getIntValue(OPTIONS_KEY_MENU_NEXT))
if (++tabButtonIndex == tabButtonCount) tabButtonIndex = 0;
if (eventKey == o.keyMenuPrevious.key)
if (eventKey == o.getIntValue(OPTIONS_KEY_MENU_PREV))
if (--tabButtonIndex == -1) tabButtonIndex = tabButtonCount-1;
if (eventKey == o.keyMenuOk.key) {
if (eventKey == o.getIntValue(OPTIONS_KEY_MENU_OK)) {
Button* button = tabButtons[tabButtonIndex];
if (button->active) {
minecraft->soundEngine->playUI("random.click", 1, 1);
@@ -179,15 +201,24 @@ void Screen::keyPressed( int eventKey )
}
updateTabButtonSelection();
#endif
}
void Screen::charPressed(char inputChar) {
for (auto& textbox : textBoxes) {
textbox->charPressed(minecraft, inputChar);
}
}
void Screen::updateTabButtonSelection()
{
#ifdef TABBING
if (minecraft->useTouchscreen())
return;
for (unsigned int i = 0; i < tabButtons.size(); ++i)
tabButtons[i]->selected = (i == tabButtonIndex);
#endif
}
void Screen::mouseClicked( int x, int y, int buttonNum )
@@ -210,6 +241,11 @@ void Screen::mouseClicked( int x, int y, int buttonNum )
}
}
}
// let textboxes see the click regardless
for (auto& textbox : textBoxes) {
textbox->mouseClicked(minecraft, x, y, buttonNum);
}
}
void Screen::mouseReleased( int x, int y, int buttonNum )

View File

@@ -1,10 +1,9 @@
#ifndef NET_MINECRAFT_CLIENT_GUI__Screen_H__
#define NET_MINECRAFT_CLIENT_GUI__Screen_H__
#pragma once
//package net.minecraft.client.gui;
#include <vector>
#include "GuiComponent.h"
#include "GuiComponent.hpp"
class Font;
class Minecraft;
@@ -57,8 +56,11 @@ protected:
virtual void mouseClicked(int x, int y, int buttonNum);
virtual void mouseReleased(int x, int y, int buttonNum);
// mouse wheel movement (dx/dy are wheel deltas, xm/ym are GUI coords)
virtual void mouseWheel(int dx, int dy, int xm, int ym) {}
virtual void keyPressed(int eventKey);
virtual void keyboardNewChar(char inputChar) {}
virtual void charPressed(char inputChar);
public:
int width;
int height;
@@ -77,4 +79,3 @@ private:
Button* clickedButton;
};
#endif /*NET_MINECRAFT_CLIENT_GUI__Screen_H__*/

View File

@@ -1,11 +0,0 @@
#ifndef NET_MINECRAFT_CLIENT_GUI__TweenData_H__
#define NET_MINECRAFT_CLIENT_GUI__TweenData_H__
typedef struct TweenData {
float cur;
float dur;
float start;
float stop;
} TweenData;
#endif /*NET_MINECRAFT_CLIENT_GUI__TweenData_H__*/

9
src/client/gui/TweenData.hpp Executable file
View File

@@ -0,0 +1,9 @@
#pragma once
typedef struct TweenData {
float cur;
float dur;
float start;
float stop;
} TweenData;

View File

@@ -1,6 +1,6 @@
#include "Button.h"
#include "../../Minecraft.h"
#include "../../renderer/Textures.h"
#include "Button.hpp"
#include "client/Minecraft.hpp"
#include "client/renderer/Textures.hpp"
Button::Button(int id, const std::string& msg)
: GuiElement(true, true, 0, 0, 200, 24),
@@ -95,7 +95,7 @@ void Button::renderBg( Minecraft* minecraft, int xm, int ym )
}
bool Button::hovered(Minecraft* minecraft, int xm , int ym) {
return minecraft->useTouchscreen()? (_currentlyDown && isInside(xm, ym)) : false;
return minecraft->useTouchscreen()? (_currentlyDown && isInside(xm, ym)) : isInside(xm, ym);
}
bool Button::isInside( int xm, int ym ) {
@@ -143,7 +143,8 @@ TButton::TButton( int id, int x, int y, int w, int h, const std::string& msg )
void TButton::renderBg( Minecraft* minecraft, int xm, int ym )
{
bool hovered = active && (minecraft->useTouchscreen()? (_currentlyDown && xm >= x && ym >= y && xm < x + width && ym < y + height) : false);
bool hovered = active && (minecraft->useTouchscreen()? (_currentlyDown && xm >= x && ym >= y && xm < x + width && ym < y + height) : isInside(xm, ym));
// bool hovered = active && (_currentlyDown && isInside(xm, ym));
minecraft->textures->loadAndBindTexture("gui/touchgui.png");

View File

@@ -1,11 +1,10 @@
#ifndef NET_MINECRAFT_CLIENT_GUI_COMPONENTS__Button_H__
#define NET_MINECRAFT_CLIENT_GUI_COMPONENTS__Button_H__
#pragma once
//package net.minecraft.client.gui;
#include <string>
#include "GuiElement.h"
#include "../../Options.h"
#include "GuiElement.hpp"
#include "client/Options.hpp"
class Font;
class Minecraft;
@@ -77,4 +76,3 @@ public:
};
}
#endif /*NET_MINECRAFT_CLIENT_GUI_COMPONENTS__Button_H__*/

View File

@@ -1 +1 @@
#include "GuiElement.h"
#include "GuiElement.hpp"

View File

@@ -1,6 +1,5 @@
#ifndef NET_MINECRAFT_CLIENT_GUI__GButton_H__
#define NET_MINECRAFT_CLIENT_GUI__GButton_H__
#include "Button.h"
#pragma once
#include "Button.hpp"
class GButton: public Button {
typedef Button super;
@@ -52,4 +51,3 @@ private:
};
#endif /*NET_MINECRAFT_CLIENT_GUI__GButton_H__*/

View File

@@ -1,4 +1,4 @@
#include "GuiElement.h"
#include "GuiElement.hpp"
GuiElement::GuiElement( bool active/*=false*/, bool visible/*=true*/, int x /*= 0*/, int y /*= 0*/, int width/*=24*/, int height/*=24*/ )
: active(active),

View File

@@ -1,6 +1,5 @@
#ifndef NET_MINECRAFT_CLIENT_GUI__GuiElement_H__
#define NET_MINECRAFT_CLIENT_GUI__GuiElement_H__
#include "../GuiComponent.h"
#pragma once
#include "client/gui/GuiComponent.hpp"
class Tesselator;
class Minecraft;
@@ -9,13 +8,20 @@ class GuiElement : public GuiComponent {
public:
GuiElement(bool active=false, bool visible=true, int x = 0, int y = 0, int width=24, int height=24);
virtual ~GuiElement() {}
virtual void tick(Minecraft* minecraft) {}
virtual void render(Minecraft* minecraft, int xm, int ym) { }
virtual void setupPositions() {}
virtual void mouseClicked(Minecraft* minecraft, int x, int y, int buttonNum) {}
virtual void mouseReleased(Minecraft* minecraft, int x, int y, int buttonNum) {}
virtual void keyPressed(Minecraft* minecraft, int key) {}
virtual void charPressed(Minecraft* minecraft, char key) {}
virtual bool pointInside(int x, int y);
void setVisible(bool visible);
bool active;
bool visible;
int x;
@@ -24,4 +30,3 @@ public:
int height;
};
#endif /*NET_MINECRAFT_CLIENT_GUI__GuiElement_H__*/

View File

@@ -1,4 +1,4 @@
#include "GuiElementContainer.h"
#include "GuiElementContainer.hpp"
#include <algorithm>
GuiElementContainer::GuiElementContainer( bool active/*=false*/, bool visible/*=true*/, int x /*= 0*/, int y /*= 0*/, int width/*=24*/, int height/*=24*/ )
: GuiElement(active, visible, x, y, width, height) {
@@ -52,3 +52,15 @@ void GuiElementContainer::mouseReleased( Minecraft* minecraft, int x, int y, int
(*it)->mouseReleased(minecraft, x, y, buttonNum);
}
}
void GuiElementContainer::keyPressed(Minecraft* minecraft, int key) {
for(std::vector<GuiElement*>::iterator it = children.begin(); it != children.end(); ++it) {
(*it)->keyPressed(minecraft, key);
}
}
void GuiElementContainer::charPressed(Minecraft* minecraft, char key) {
for(std::vector<GuiElement*>::iterator it = children.begin(); it != children.end(); ++it) {
(*it)->charPressed(minecraft, key);
}
}

View File

@@ -1,6 +1,5 @@
#ifndef NET_MINECRAFT_CLIENT_GUI__GuiElementContainer_H__
#define NET_MINECRAFT_CLIENT_GUI__GuiElementContainer_H__
#include "GuiElement.h"
#pragma once
#include "GuiElement.hpp"
#include <vector>
class Tesselator;
class Minecraft;
@@ -17,11 +16,11 @@ public:
virtual void tick( Minecraft* minecraft );
virtual void mouseClicked( Minecraft* minecraft, int x, int y, int buttonNum );
virtual void mouseReleased( Minecraft* minecraft, int x, int y, int buttonNum );
virtual void keyPressed(Minecraft* minecraft, int key);
virtual void charPressed(Minecraft* minecraft, char key);
protected:
std::vector<GuiElement*> children;
};
#endif /*NET_MINECRAFT_CLIENT_GUI__GuiElementContainer_H__*/

View File

@@ -1,9 +1,10 @@
#include "ImageButton.h"
#include "../../renderer/Tesselator.h"
#include "../../Minecraft.h"
#include "../../../platform/log.h"
#include "../../../util/Mth.h"
#include "../../renderer/Textures.h"
#include "ImageButton.hpp"
#include "client/renderer/Tesselator.hpp"
#include "client/Minecraft.hpp"
#include "platform/log.hpp"
#include "util/Mth.hpp"
#include "client/renderer/Textures.hpp"
#include <client/Option.hpp>
ImageButton::ImageButton(int id, const std::string& msg)
@@ -41,7 +42,7 @@ void ImageButton::render(Minecraft* minecraft, int xm, int ym) {
//minecraft->textures->loadAndBindTexture("gui/gui.png");
glColor4f2(1, 1, 1, 1);
bool hovered = active && (minecraft->useTouchscreen()? (_currentlyDown && xm >= x && ym >= y && xm < x + width && ym < y + height) : false);
bool hovered = active && (minecraft->useTouchscreen()? (_currentlyDown && xm >= x && ym >= y && xm < x + width && ym < y + height) : isInside(xm, ym));
bool IsSecondImage = isSecondImage(hovered);
//printf("ButtonId: %d - Hovered? %d (cause: %d, %d, %d, %d, <> %d, %d)\n", id, hovered, x, y, x+w, y+h, xm, ym);
@@ -112,43 +113,17 @@ void ImageButton::render(Minecraft* minecraft, int xm, int ym) {
//
// A toggleable Button
//
OptionButton::OptionButton(const Options::Option* option)
: _option(option),
_isFloat(false),
super(ButtonId, "")
{
}
OptionButton::OptionButton(const Options::Option* option, float onValue, float offValue)
: _option(option),
_isFloat(true),
_onValue(onValue),
_offValue(offValue),
super(ButtonId, "")
{
}
bool OptionButton::isSecondImage(bool hovered) {
return _secondImage;
}
OptionButton::OptionButton(OptionId option) : m_optId(option), super(ButtonId, "") {}
void OptionButton::toggle(Options* options) {
if (_isFloat) {
options->set(_option, (Mth::abs(_current - _onValue) < 0.01f) ? _offValue : _onValue);
} else {
options->toggle(_option, 1);
}
options->toggle(m_optId);
// Update graphics here
updateImage(options);
}
void OptionButton::updateImage(Options* options) {
if (_isFloat) {
_current = options->getProgressValue(_option);
_secondImage = Mth::abs(_current - _onValue) < 0.01f;
} else {
_secondImage = options->getBooleanValue(_option);
}
_secondImage = options->getBooleanValue(m_optId);
}
void OptionButton::mouseClicked( Minecraft* minecraft, int x, int y, int buttonNum ) {

View File

@@ -1,7 +1,6 @@
#ifndef NET_MINECRAFT_CLIENT_GUI_COMPONENTS__ImageButton_H__
#define NET_MINECRAFT_CLIENT_GUI_COMPONENTS__ImageButton_H__
#pragma once
#include "Button.h"
#include "Button.hpp"
typedef struct IntRectangle {
IntRectangle()
@@ -77,29 +76,20 @@ class OptionButton: public ImageButton
{
typedef ImageButton super;
public:
OptionButton(const Options::Option* option);
OptionButton(const Options::Option* option, float onValue, float offValue);
OptionButton(OptionId optId);
void toggle(Options* options);
void updateImage(Options* options);
static const int ButtonId = 9999999;
protected:
bool isSecondImage(bool hovered);
bool isSecondImage(bool hovered) { return _secondImage; }
virtual void mouseClicked( Minecraft* minecraft, int x, int y, int buttonNum );
private:
const Options::Option* _option;
OptionId m_optId;
bool _secondImage;
// If not float, it's considered to be a boolean value
bool _isFloat;
float _onValue;
float _offValue;
float _current;
};
#endif /*NET_MINECRAFT_CLIENT_GUI_COMPONENTS__ImageButton_H__*/

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