Refactoring time

This commit is contained in:
Alula 2022-11-19 18:20:03 +01:00
parent 9fd04ed47a
commit 17e1156850
No known key found for this signature in database
GPG Key ID: 3E00485503A1D8BA
189 changed files with 4518 additions and 6994 deletions

View File

@ -1,9 +1,9 @@
[package]
name = "doukutsu-rs"
description = "A re-implementation of Cave Story (Doukutsu Monogatari) engine"
version = "0.99.0"
version = "0.100.0"
authors = ["Alula", "dawnDus"]
edition = "2018"
edition = "2021"
[lib]
crate-type = ["lib"]
@ -25,7 +25,7 @@ opt-level = 3
[package.metadata.bundle]
name = "doukutsu-rs"
identifier = "io.github.doukutsu_rs"
version = "0.99.0"
version = "0.100.0"
resources = ["data"]
copyright = "Copyright (c) 2020-2022 doukutsu-rs dev team"
category = "Game"
@ -33,15 +33,14 @@ osx_minimum_system_version = "10.12"
[features]
default = ["default-base", "backend-sdl", "render-opengl", "exe"]
default-base = ["scripting-lua", "ogg-playback", "netplay"]
default-base = ["ogg-playback"]
ogg-playback = ["lewton"]
backend-sdl = ["sdl2", "sdl2-sys"]
backend-glutin = ["winit", "glutin", "render-opengl"]
render-opengl = []
scripting-lua = ["lua-ffi"]
netplay = ["tokio", "serde_cbor"]
netplay = ["serde_cbor"]
editor = []
hooks = ["libc"]
exe = []
android = []
@ -51,42 +50,40 @@ android = []
#winit = { path = "./3rdparty/winit", optional = true, default_features = false, features = ["x11"] }
#sdl2 = { path = "./3rdparty/rust-sdl2", optional = true, features = ["unsafe_textures", "bundled", "static-link"] }
#sdl2-sys = { path = "./3rdparty/rust-sdl2/sdl2-sys", optional = true, features = ["bundled", "static-link"] }
bitvec = "0.20"
byteorder = "1.4"
case_insensitive_hashmap = "1.0.0"
chrono = "0.4"
cpal = "0.13"
cpal = "0.14"
directories = "3"
downcast = "0.11"
funty = "=1.1.0" # https://github.com/bitvecto-rs/bitvec/issues/105
glutin = { git = "https://github.com/doukutsu-rs/glutin.git", rev = "8dd457b9adb7dbac7ade337246b6356c784272d9", optional = true, default_features = false, features = ["x11"] }
imgui = "0.8.0"
image = { version = "0.23", default-features = false, features = ["png", "bmp"] }
#glutin = { git = "https://github.com/doukutsu-rs/glutin.git", rev = "8dd457b9adb7dbac7ade337246b6356c784272d9", optional = true, default_features = false, features = ["x11"] }
glutin = { version = "0.30", optional = true, default_features = false, features = ["x11"] }
imgui = "0.8"
image = { version = "0.24", default-features = false, features = ["png", "bmp"] }
itertools = "0.10"
lazy_static = "1.4.0"
lewton = { version = "0.10.2", optional = true }
libc = { version = "0.2", optional = true }
lazy_static = "1.4"
lewton = { version = "0.10", optional = true }
log = "0.4"
lua-ffi = { git = "https://github.com/doukutsu-rs/lua-ffi.git", rev = "e0b2ff5960f7ef9974aa9675cebe4907bee0134f", optional = true }
num-derive = "0.3.2"
num-traits = "0.2.12"
paste = "1.0.0"
pelite = "0.9.1"
num-derive = "0.3"
num-traits = "0.2"
paste = "1.0"
pelite = ">=0.9.2"
sdl2 = { git = "https://github.com/doukutsu-rs/rust-sdl2.git", rev = "95bcf63768abf422527f86da41da910649b9fcc9", optional = true, features = ["unsafe_textures", "bundled", "static-link"] }
sdl2-sys = { git = "https://github.com/doukutsu-rs/rust-sdl2.git", rev = "95bcf63768abf422527f86da41da910649b9fcc9", optional = true, features = ["bundled", "static-link"] }
serde = { version = "1", features = ["derive"] }
serde_derive = "1"
serde_cbor = { version = "0.11.2", optional = true }
serde_cbor = { version = "0.11", optional = true }
serde_json = "1.0"
simple_logger = { version = "1.16", features = ["colors", "threads"] }
strum = "0.20"
strum_macros = "0.20"
tokio = { version = "1.12.0", features = ["net"], optional = true }
strum = "0.24"
strum_macros = "0.24"
# remove and replace when drain_filter is in stable
vec_mut_scan = "0.4"
webbrowser = "0.5.5"
winit = { git = "https://github.com/alula/winit.git", rev = "6acf76ff192dd8270aaa119b9f35716c03685f9f", optional = true, default_features = false, features = ["x11"] }
xmltree = "0.10.3"
webbrowser = "0.8"
#winit = { git = "https://github.com/alula/winit.git", rev = "6acf76ff192dd8270aaa119b9f35716c03685f9f", optional = true, default_features = false, features = ["x11"] }
winit = { version = "0.27", optional = true, default_features = false, features = ["x11"] }
xmltree = "0.10"
[target.'cfg(target_os = "windows")'.dependencies]
winapi = { version = "0.3", features = ["winuser"] }
@ -95,10 +92,10 @@ winapi = { version = "0.3", features = ["winuser"] }
winres = "0.1"
[target.'cfg(target_os = "macos")'.dependencies]
objc = "0.2.7"
objc = "0.2"
[target.'cfg(target_os = "android")'.dependencies]
ndk = "0.3"
ndk-glue = "0.3"
ndk-sys = "0.2"
jni = "0.19"
ndk = "0.7"
ndk-glue = "0.7"
ndk-sys = "0.4"
jni = "0.20"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 276 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 447 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 456 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 562 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 621 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

View File

@ -1,197 +0,0 @@
{
"name": "English",
"font": "csfont.fnt",
"font_scale": "0.5",
"common": {
"name": "doukutsu-rs",
"back": "< Back",
"yes": "Yes",
"no": "No",
"on": "ON",
"off": "OFF"
},
"menus": {
"main_menu": {
"start": "Start Game",
"challenges": "Challenges",
"options": "Options",
"editor": "Editor",
"jukebox": "Jukebox",
"quit": "Quit"
},
"pause_menu": {
"resume": "Resume",
"retry": "Retry",
"options": "Options",
"title": "Title",
"title_confirm": "Title?",
"quit": "Quit",
"quit_confirm": "Quit?",
"add_player2": "Add Player 2",
"drop_player2": "Drop Player 2"
},
"save_menu": {
"new": "New Save",
"delete_info": "Press Right to Delete",
"delete_confirm": "Delete?",
"invalid_save": "Invalid Save"
},
"difficulty_menu": {
"title": "Select Difficulty",
"easy": "Easy",
"normal": "Normal",
"hard": "Hard"
},
"coop_menu": {
"title": "Select Number of Players",
"one": "Single Player",
"two": "Two Players"
},
"skin_menu": {
"title": "Select Player 2's appearance",
"label": "Appearance:"
},
"challenge_menu": {
"start": "Start",
"no_replay": "No Replay",
"replay_best": "Replay Best",
"replay_last": "Replay Last",
"delete_replay": "Delete Best Replay"
},
"options_menu": {
"graphics": "Graphics...",
"graphics_menu": {
"window_mode": {
"entry": "Display mode:",
"windowed": "Windowed",
"fullscreen": "Fullscreen"
},
"lighting_effects": "Lighting effects:",
"weapon_light_cone": "Weapon light cone:",
"screen_shake": {
"entry": "Screen shake intensity:",
"full": "1x",
"half": "0.5x",
"off": "Off"
},
"motion_interpolation": "Motion interpolation:",
"subpixel_scrolling": "Subpixel scrolling:",
"original_textures": "Original textures:",
"seasonal_textures": "Seasonal textures:",
"renderer": "Renderer:",
"vsync_mode": {
"entry": "V-Sync:",
"uncapped": "Uncapped",
"uncapped_desc": "V-Sync Off.",
"vsync": "Enabled",
"vsync_desc": "V-Sync On.",
"vrr_1x": "Variable Refresh Rate (1x)",
"vrr_1x_desc": "Uses (G-/Free)Sync if available.",
"vrr_2x": "Variable Refresh Rate (2x)",
"vrr_2x_desc": "Uses (G-/Free)Sync if available.",
"vrr_3x": "Variable Refresh Rate (3x)",
"vrr_3x_desc": "Uses (G-/Free)Sync if available."
}
},
"sound": "Sound...",
"sound_menu": {
"music_volume": "Music Volume",
"effects_volume": "Effects Volume",
"bgm_interpolation": {
"entry": "BGM Interpolation:",
"linear": "Linear",
"linear_desc": "Fast, similar to freeware on Vista+",
"cosine": "Cosine",
"cosine_desc": "Cosine interpolation",
"cubic": "Cubic",
"cubic_desc": "Cubic interpolation",
"linear_lp": "Linear+LP",
"linear_lp_desc": "Slowest, similar to freeware on XP",
"nearest": "Nearest",
"nearest_desc": "Fastest, lowest quality"
},
"soundtrack": "Soundtrack: {soundtrack}"
},
"controls": "Controls...",
"language": "Language...",
"behavior": "Behavior...",
"behavior_menu": {
"game_timing": {
"entry": "Game timing:",
"50tps": "50tps (freeware)",
"60tps": "60tps (CS+)"
},
"pause_on_focus_loss": "Pause on focus loss:",
"cutscene_skip_method": {
"entry": "Cutscene Skip:",
"hold": "Hold to Skip",
"fastforward": "Fast-Forward"
}
},
"links": "Links..."
},
"controls_menu": {
"select_player": {
"entry": "Select player:",
"player_1": "Player 1",
"player_2": "Player 2"
},
"controller": {
"entry": "Controller...",
"keyboard": "Keyboard"
},
"rebind": "Rebind...",
"rebind_menu": {
"up": "Up",
"down": "Down",
"left": "Left",
"right": "Right",
"jump": "Jump",
"shoot": "Shoot",
"prev_weapon": "Previous weapon",
"next_weapon": "Next weapon",
"inventory": "Inventory",
"map": "Map system",
"skip": "Skip",
"strafe": "Strafe",
"menu_ok": "Menu select/confirm",
"menu_back": "Menu back/cancel"
},
"rebind_confirm_menu": {
"title": "Press button for \"{control}\"",
"cancel": "(Esc to cancel)"
},
"rumble": "Rumble:",
"reset_confirm": "Reset...",
"reset_confirm_menu_title": "Reset controls?"
}
},
"soundtrack": {
"organya": "Organya",
"remastered": "Remastered",
"new": "New",
"famitracks": "Famitracks"
},
"game": {
"cutscene_skip": "Hold {key} to skip the cutscene"
}
}

View File

@ -1,187 +0,0 @@
{
"name": "Japanese",
"font": "csfontjp.fnt",
"font_scale": "0.5",
"common": {
"name": "doukutsu-rs",
"back": "< 戻る",
"yes": "はい",
"no": "いいえ",
"on": "オン",
"off": "オフ"
},
"menus": {
"main_menu": {
"start": "ゲームスタート",
"challenges": "チャレンジ",
"options": "オプション",
"editor": "レベルエディタ",
"jukebox": "ジュークボックス",
"quit": "辞める"
},
"pause_menu": {
"resume": "再開",
"retry": "リトライ",
"options": "設定",
"title": "メインメニュー",
"title_confirm": "メインメニュー?",
"quit": "辞める",
"quit_confirm": "辞める?",
"add_player2": "プレーヤー2を追加",
"drop_player2": "プレーヤー2を削除"
},
"save_menu": {
"new": "新しいデータ",
"delete_info": "右矢印キーで削除",
"delete_confirm": "消去?",
"invalid_save": "無効な保存"
},
"difficulty_menu": {
"title": "難易度選択",
"easy": "簡単",
"normal": "普通",
"hard": "難しい"
},
"coop_menu": {
"title": "プレイヤー数を選択",
"one": "1人プレイ",
"two": "2人プレイ"
},
"skin_menu": {
"title": "プレーヤー2の外観を選択します",
"label": "外観:"
},
"challenge_menu": {
"start": "スタート",
"no_replay": "ノーリプレイ",
"replay_best": "ベストプレイを再生",
"replay_last": "最後のプレイを再生",
"delete_replay": "ベストリプレイを削除"
},
"options_menu": {
"graphics": "グラフィック",
"graphics_menu": {
"window_mode": {
"entry": "画面表示:",
"windowed": "ウィンドウ",
"fullscreen": "フルスクリーン"
},
"lighting_effects": "ライティング効果:",
"weapon_light_cone": "兵器のライトコーン:",
"screen_shake": {
"entry": "画面の揺れ:",
"full": "1x",
"half": "0.5x",
"off": "オフ"
},
"motion_interpolation": "モーション補間:",
"subpixel_scrolling": "サブピクセルスクロール:",
"original_textures": "オリジナルテクスチャ:",
"seasonal_textures": "季節ものテクスチャ:",
"renderer": "レンダラ:",
"vsync_mode": {
"entry": "V-Sync:",
"uncapped": "Uncapped",
"uncapped_desc": "V-Sync Off.",
"vsync": "Enabled",
"vsync_desc": "V-Sync On.",
"vrr_1x": "Variable Refresh Rate (1x)",
"vrr_1x_desc": "Uses (G-/Free)Sync if available.",
"vrr_2x": "Variable Refresh Rate (2x)",
"vrr_2x_desc": "Uses (G-/Free)Sync if available.",
"vrr_3x": "Variable Refresh Rate (3x)",
"vrr_3x_desc": "Uses (G-/Free)Sync if available."
}
},
"sound": "サウンド",
"sound_menu": {
"music_volume": "BGM音量",
"effects_volume": "サウンド音量",
"bgm_interpolation": {
"entry": "BGM内挿",
"linear": "線形補間",
"linear_desc": "速い、フリーウェア版に近いVista+",
"cosine": "余弦",
"cosine_desc": "余弦補間",
"cubic": "立方体",
"cubic_desc": "立方体補間",
"linear_lp": "線形補間+LP",
"linear_lp_desc": "最も遅い、フリーウェア版に近いXP",
"nearest": "最近傍",
"nearest_desc": "最速、最低品質"
},
"soundtrack": "サウンドトラック: {soundtrack}"
},
"controls": "ボタン変更",
"language": "言語",
"behavior": "動作",
"behavior_menu": {
"game_timing": {
"entry": "ゲームのタイミング:",
"50tps": "50tps (freeware)",
"60tps": "60tps (CS+)"
},
"pause_on_focus_loss": "フォーカスが外れた時のポーズ:",
"cutscene_skip_method": {
"entry": "カットシーンをスキップ",
"hold": "を押し続け",
"fastforward": "はやおくり"
}
},
"links": "リンク"
},
"controls_menu": {
"select_player": {
"entry": "プレイヤーを選択:",
"player_1": "プレーヤー 1",
"player_2": "プレーヤー 2"
},
"controller": {
"entry": "コントローラ",
"keyboard": "キーボード"
},
"rebind": "再バインド",
"rebind_menu": {
"up": "うえ",
"down": "した",
"left": "ひだり",
"right": "みぎ",
"jump": "ジャンプ",
"shoot": "ショット",
"prev_weapon": "前の武器",
"next_weapon": "次の武器",
"inventory": "在庫",
"map": "マップシステム",
"skip": "スキップ",
"strafe": "ストレイフ",
"menu_ok": "メニュー選択OK",
"menu_back": "メニュー残す/キャンセル"
},
"rebind_confirm_menu": {
"title": "新しい「ジャンプ」ボタンを押す",
"cancel": "(Escキーを押してキャンセル)"
},
"rumble": "ランブル",
"reset_confirm": "リセット",
"reset_confirm_menu_title": "ボタンをリセットしますか?"
}
},
"soundtrack": {
"organya": "オルガーニャ",
"remastered": "リマスター",
"new": "新",
"famitracks": "ファミトラック"
},
"game": {
"cutscene_skip": "{key} を押し続け、カットシーンをスキップ"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 130 B

View File

@ -1,276 +0,0 @@
# AngelCode Bitmap Font Generator configuration file
fileVersion=1
# font settings
fontName=JF Dot k12x10
fontFile=JF-Dot-k12x10.ttf
charSet=0
fontSize=10
aa=1
scaleH=100
useSmoothing=0
isBold=0
isItalic=0
useUnicode=1
disableBoxChars=1
outputInvalidCharGlyph=1
dontIncludeKerningPairs=0
useHinting=1
renderFromOutline=0
useClearType=1
autoFitNumPages=0
autoFitFontSizeMin=0
autoFitFontSizeMax=0
# character alignment
paddingDown=0
paddingUp=0
paddingRight=0
paddingLeft=0
spacingHoriz=1
spacingVert=1
useFixedHeight=0
forceZero=0
widthPaddingFactor=0.00
# output file
outWidth=512
outHeight=512
outBitDepth=8
fontDescFormat=2
fourChnlPacked=0
textureFormat=png
textureCompression=0
alphaChnl=0
redChnl=4
greenChnl=4
blueChnl=4
invA=0
invR=0
invG=0
invB=0
# outline
outlineThickness=0
# selected chars
chars=32-126,160,167-168,176-177,180,182,215,247,913-929,931-937,945-961,963-969,1025,1040-1103,1105,8208
chars=8213,8216-8217,8229-8230,8251,8451,8470,8481,8491,8544-8553,8592-8595,8658,8660,8722,8730,8733-8734
chars=9312-9331,9472-9475,9484,9487-9488,9491-9492,9495-9496,9499-9501,9504,9507-9509,9512,9515-9516,9519
chars=9520,9523-9524,9527-9528,9531-9532,9535,9538,9547,9632-9633,9650-9651,9660-9661,9670-9671,9675,9678
chars=9679,9711,9733-9734,9792,9794,9834,9837,9839,12288-12291,12293-12309,12316-12317,12319,12353-12435
chars=12443-12446,12449-12534,12539-12542,12849-12850,12857,12964-12968,13059,13069,13076,13080,13090
chars=13091,13094-13095,13099,13110,13115,13129-13130,13133,13137,13143,13179-13182,13198-13199,13212
chars=13213-13214,13217,13252,13261,19968-19969,19971,19975-19979,19981-19982,19984-19985,19988-19993
chars=19998,20001,20006,20010,20013,20017-20018,20022,20024-20025,20027-20028,20031,20034-20035,20037
chars=20043,20045-20047,20053-20057,20061-20063,20066,20081,20083,20094,20096,20098,20101-20102,20104
chars=20105-20108,20110,20113-20114,20116-20117,20120-20121,20123-20124,20126-20130,20132-20134,20136
chars=20139-20142,20144,20147,20150,20154,20160-20162,20164,20166-20167,20170-20171,20173-20175,20180
chars=20181-20185,20189-20191,20195-20197,20205-20206,20208,20210,20214-20215,20219,20225,20233-20234
chars=20237-20241,20250,20252-20253,20271-20272,20276,20278,20280,20282,20284-20285,20291,20294-20295
chars=20301-20305,20307,20309,20311,20313-20318,20329,20335-20336,20339,20341-20342,20347-20348,20351
chars=20355,20358,20360,20363,20365,20367,20369,20374,20376,20379,20381,20384-20385,20395,20397-20399
chars=20405-20406,20415,20418-20420,20426,20430,20432-20433,20436,20439-20440,20442-20443,20445,20447
chars=20449,20451-20453,20462-20463,20467,20469-20470,20472,20474,20478,20485-20486,20489,20491,20493
chars=20495,20497-20498,20500,20502,20505-20506,20511,20513,20515-20518,20520-20525,20534,20537,20547
chars=20551-20553,20559-20560,20565-20566,20570,20572,20581,20588,20594,20596-20598,20600,20605,20608
chars=20613,20621,20625,20632-20634,20652-20653,20658-20661,20663,20670,20674,20677,20681-20682,20685
chars=20687,20689,20693-20694,20698,20702,20707,20709,20711,20717-20718,20725,20729,20731,20736-20738
chars=20740,20745,20754,20756-20758,20760,20762,20767,20769,20778,20786,20791,20794-20796,20799-20801
chars=20803-20809,20811-20814,20816,20818,20820,20826,20828,20834,20837,20840-20846,20849,20853-20856
chars=20860,20864,20866,20869-20870,20873-20874,20876-20877,20879-20883,20885-20887,20889,20896,20898
chars=20900-20902,20904-20908,20912-20919,20925,20932-20934,20937,20939-20941,20950,20955-20957,20960
chars=20961,20966-20967,20969-20970,20973,20976-20977,20981-20982,20984-20986,20989-20990,20992,20995
chars=20996,20998-21000,21002-21003,21006,21009,21012,21015,21021,21028-21029,21031,21033-21034,21038
chars=21040,21043,21046-21051,21059-21060,21063,21066-21069,21071,21076,21078,21083,21086,21091-21093
chars=21097-21098,21103-21109,21117,21119,21123,21127-21129,21133,21137-21138,21140,21147,21151-21152
chars=21155,21161-21165,21169,21172-21173,21177,21180,21182,21185,21187,21189,21191,21193,21197,21202
chars=21205,21207-21209,21213-21216,21218-21220,21222-21223,21234-21235,21237,21240-21242,21246-21247
chars=21249-21250,21253-21254,21256,21261,21263-21264,21269-21271,21273-21274,21277,21280-21281,21283
chars=21290,21295,21297,21299,21304-21307,21311-21313,21315,21317-21322,21325,21329-21332,21335-21336
chars=21338,21340,21342,21344,21350,21353,21358-21361,21363-21365,21367-21368,21371,21375,21378,21380
chars=21398,21400,21402,21407-21408,21413-21414,21416-21417,21421-21422,21424,21427,21430,21435,21442
chars=21443,21448-21454,21460,21462-21463,21465,21467,21471,21473-21477,21480-21491,21494-21496,21498
chars=21505,21507-21508,21512-21521,21531,21533,21535-21536,21542,21545,21547-21550,21558,21560-21561
chars=21563-21566,21568,21570,21574,21576-21578,21582,21585,21599,21608,21610,21616-21617,21619,21621
chars=21622-21623,21627-21629,21632,21636,21638,21643-21644,21646-21648,21650,21666,21668-21669,21672
chars=21675-21676,21679,21682-21683,21688,21692-21694,21696-21698,21700,21703-21705,21720,21729-21730
chars=21733-21734,21736-21737,21741-21742,21746,21754,21757,21764,21766-21767,21775-21776,21780,21782
chars=21806-21807,21809,21811,21816-21817,21822,21824,21828-21830,21836,21839,21843,21846-21847,21852
chars=21853,21859,21883-21884,21886,21888,21891-21892,21895,21897-21899,21912-21914,21916-21919,21927
chars=21928-21932,21934,21936,21942,21956-21957,21959,21972,21978,21980,21983,21987-21988,22007,22009
chars=22013-22014,22022,22025,22036,22038-22040,22043,22057,22063,22065-22066,22068,22070,22072,22082
chars=22092,22094,22096,22107,22116,22120,22122-22124,22132,22136,22138,22144,22150-22151,22154,22159
chars=22164,22176,22178,22181,22190,22196,22198,22204,22208-22211,22216,22222,22225,22227,22231-22232
chars=22234-22235,22238,22240,22243,22254,22256,22258-22259,22265-22266,22269,22271-22272,22275-22276
chars=22280-22281,22283,22285,22287,22290-22291,22294,22296,22300,22303,22310-22312,22317,22320,22327
chars=22328,22331,22336,22338,22343,22346,22350-22353,22369,22372,22374,22377-22378,22399,22402,22408
chars=22409,22411,22419,22432,22434-22436,22442,22448,22451,22464,22467,22470,22475,22478,22482-22484
chars=22486,22492,22495-22496,22499,22516,22519,22521-22522,22524,22528,22530,22533-22534,22538-22539
chars=22549,22553,22557,22561,22564,22570,22575-22577,22580-22581,22586,22589,22592-22593,22602-22603
chars=22609-22610,22612,22615-22618,22622,22626,22633,22635,22640,22642,22645,22649,22654,22659,22661
chars=22675,22679,22684,22687,22696,22699,22702,22707,22712-22715,22718,22721,22725,22727,22730,22732
chars=22737,22739,22741,22743-22745,22748,22750-22751,22756-22757,22763-22764,22766-22770,22775,22777
chars=22778-22781,22786,22793-22794,22799-22800,22805-22806,22808-22812,22818,22821,22823,22825-22830
chars=22833-22834,22839-22840,22846,22852,22855-22857,22862-22865,22868-22869,22871-22872,22874,22880
chars=22882,22885,22887-22890,22892,22894,22899-22900,22904,22909,22913-22916,22922,22925,22931,22934
chars=22937,22939,22941,22947,22949,22952,22956,22962,22969,22971,22974,22982,22985,22987,22992-22993
chars=22995-22996,23001-23002,23004,23013-23014,23016,23018-23019,23030,23035,23039,23041,23043,23049
chars=23057,23064,23066,23068,23071-23072,23077,23081,23087,23093-23094,23100,23104-23105,23110,23113
chars=23130,23138,23142,23146,23148,23167,23186,23194-23195,23228-23230,23233-23234,23241,23243-23244
chars=23248,23254-23255,23265,23267,23270,23273,23290-23291,23305,23307-23308,23318,23330,23338,23340
chars=23344,23346,23350,23358,23360,23363,23365,23376-23377,23380-23381,23383-23384,23386-23389,23391
chars=23395-23398,23401,23403,23408-23409,23411,23413,23416,23418,23424,23427,23429,23431-23433,23435
chars=23436-23437,23439,23445,23447-23453,23455,23458-23462,23470,23472,23475-23478,23480-23481,23487
chars=23490-23495,23497,23500,23504,23506-23508,23515,23517-23519,23521-23522,23524-23529,23531,23534
chars=23536,23539,23541-23542,23544,23546,23550-23551,23553-23554,23556-23563,23565-23567,23569,23571
chars=23574,23578,23584,23586,23588,23592,23597,23601,23608-23617,23621-23622,23624,23626-23627,23629
chars=23630-23633,23635,23637,23646,23648-23649,23652-23653,23660,23662-23663,23665,23670,23673,23692
chars=23696-23697,23700,23713,23720-23721,23723-23724,23729,23731,23734-23736,23739-23740,23742,23749
chars=23751,23769,23776-23777,23784-23786,23789,23791-23792,23798,23802-23803,23805,23815,23819,23822
chars=23825,23828-23835,23839,23842,23849,23883-23884,23886,23888,23890,23900,23913,23916,23919,23923
chars=23926,23938,23940,23943,23947-23948,23952,23965,23970,23980,23982,23991,23994,23996-23997,24009
chars=24012-24013,24018-24019,24022,24027,24029-24030,24033,24035,24037-24040,24043,24046,24049-24053
chars=24055,24059,24061-24062,24066-24067,24070,24075-24076,24081,24086,24089-24091,24093,24101,24107
chars=24109,24111-24112,24115,24118-24120,24125,24128,24131-24133,24135,24140,24142,24148-24149,24151
chars=24159,24161-24164,24178-24182,24184-24191,24193,24195-24196,24199,24202,24207,24213-24215,24218
chars=24220,24224,24230-24231,24235,24237,24245-24248,24257-24259,24264-24266,24271-24272,24275,24278
chars=24282-24283,24285,24287-24291,24296-24297,24300,24304-24305,24307-24308,24310-24312,24314-24316
chars=24318-24319,24321,24323-24324,24329-24333,24335-24337,24339-24344,24347,24351,24357-24359,24361
chars=24365,24367,24369,24373,24375-24376,24380,24382,24385,24392,24394,24396,24398,24401,24403,24406
chars=24407,24409,24412-24413,24417-24418,24422,24425-24429,24432-24433,24435,24439,24441,24444,24447
chars=24448-24453,24455-24456,24458-24460,24464-24467,24471-24473,24478,24480-24481,24488-24490,24493
chars=24494,24499-24500,24505,24508-24509,24515,24517,24524-24525,24534-24537,24540-24541,24544,24548
chars=24555,24560-24561,24565,24568,24571,24573,24575,24590-24592,24594,24597-24598,24601,24603-24605
chars=24608-24609,24613-24619,24623,24625,24634,24641-24643,24646,24650-24651,24653,24656,24658,24661
chars=24665-24666,24671-24672,24674-24677,24680-24685,24687-24688,24693,24695,24705,24707-24708,24713
chars=24715-24717,24722,24724,24726-24727,24730-24731,24735-24736,24739,24742-24743,24745-24746,24754
chars=24755-24758,24760,24764-24765,24773-24775,24785,24787,24792,24794,24796,24799-24801,24803,24807
chars=24808,24816-24817,24819-24820,24822-24823,24825-24827,24832-24833,24835,24838,24840-24841,24845
chars=24846-24847,24853,24858-24859,24863,24865,24871-24872,24876,24884,24892-24895,24898,24900,24903
chars=24904,24906-24910,24915,24917,24920-24922,24925,24927,24930-24931,24933,24935-24936,24939,24942
chars=24943-24945,24947-24951,24958,24962,24967,24970,24974,24976-24977,24980,24982,24985-24986,24996
chars=24999,25001,25003-25004,25006,25010,25014,25018,25022,25027,25030-25037,25040,25059,25062,25074
chars=25076,25078-25080,25082,25084-25088,25096-25098,25100-25102,25104-25106,25108,25110,25114-25115
chars=25117-25119,25121,25126,25130,25134-25136,25138-25140,25144,25147,25151-25153,25159-25161,25163
chars=25165-25166,25171,25173,25176,25179,25182,25184,25187,25192,25198,25201,25206,25209,25212,25214
chars=25215-25216,25218-25220,25225-25226,25233-25240,25243-25244,25246,25259-25260,25265,25269,25273
chars=25275-25277,25282,25285-25290,25292-25293,25295-25300,25303-25305,25307-25309,25312-25313,25324
chars=25325-25327,25329,25331,25333-25335,25342-25343,25345-25346,25351-25353,25356,25361,25369,25375
chars=25383-25384,25387,25391,25402,25405-25407,25417,25420-25421,25423-25424,25429,25431,25436,25447
chars=25448-25449,25451,25454,25458,25462-25463,25466-25467,25472,25475,25480-25481,25484,25486-25487
chars=25490,25494,25496,25499,25503-25507,25509,25511-25516,25522,25524-25525,25531,25534,25536,25539
chars=25540,25542,25545,25551-25552,25554,25558,25562-25563,25569,25571,25577,25582,25588,25590,25594
chars=25606,25613,25615,25619,25622-25623,25628,25638,25640,25644-25645,25652,25654,25658,25662,25666
chars=25678,25688,25703,25705,25711,25718,25720,25722,25731,25736,25746-25747,25749,25754,25758,25764
chars=25765,25769,25771,25773-25774,25776,25778,25785,25787-25788,25793-25794,25797,25799,25805,25810
chars=25812,25816,25818,25824-25827,25830-25831,25836,25839,25841-25842,25844,25846,25850,25853-25854
chars=25856,25861,25880,25884-25885,25891-25892,25898-25900,25903,25908-25913,25915,25918-25919,25925
chars=25928,25933,25935,25937,25941-25945,25949-25950,25954-25955,25958,25964,25968,25970,25972-25973
chars=25975-25976,25986-25987,25991-25993,25996,25998,26000-26001,26007,26009,26011-26012,26015,26017
chars=26020-26021,26023,26027-26029,26031-26032,26039,26041,26044-26045,26049,26051-26054,26059-26060
chars=26063,26066,26071,26073,26075,26080-26082,26085-26089,26092-26093,26097,26106-26107,26114-26115
chars=26118-26119,26122,26124,26126-26127,26131-26132,26140,26143-26144,26149,26151-26152,26157,26159
chars=26164-26166,26172,26175,26177-26180,26185,26187,26191,26194,26205-26207,26210,26212,26214-26217
chars=26222-26224,26228,26230,26234,26241,26243-26244,26247-26249,26254,26257,26262-26264,26269,26274
chars=26278,26283,26286,26292,26296-26297,26300,26302,26305,26308,26311,26313,26326,26329-26330,26332
chars=26333,26336,26342,26345,26352,26354-26357,26359-26361,26364-26368,26371,26376-26377,26379,26381
chars=26383,26388-26391,26395,26397-26399,26406-26408,26410-26414,26417,26420,26422-26424,26426,26429
chars=26431,26433,26438,26441,26446-26449,26451,26454,26457,26460,26462-26469,26474,26477,26479-26483
chars=26485,26487,26492,26494-26495,26501,26503,26505,26507-26508,26512,26517,26519,26522,26524-26525
chars=26528-26530,26534,26537,26543,26547-26548,26550-26553,26561,26564,26566,26570,26574-26577,26579
chars=26580,26584,26586,26589-26590,26594,26596,26599,26601,26604,26606-26607,26609,26611-26613,26619
chars=26622-26623,26626-26628,26643,26646-26647,26654,26657-26658,26665-26667,26674,26676,26680-26681
chars=26684-26685,26688-26691,26694,26696,26701-26702,26704-26705,26707-26708,26713,26716-26717,26719
chars=26723,26727,26740,26742-26743,26750-26751,26753,26755,26757,26765,26767,26771-26772,26775,26779
chars=26781,26783-26784,26786,26790-26792,26797,26799-26801,26803,26805-26806,26809-26810,26812,26820
chars=26822,26825-26827,26829,26834,26836-26837,26839-26840,26842,26847-26849,26851,26855,26862-26863
chars=26866,26873-26874,26880-26881,26884-26885,26888,26891-26895,26898,26905-26908,26913-26915,26917
chars=26918,26920,26922,26928,26932,26934,26937,26941,26943,26954,26963-26965,26969-26970,26972-26974
chars=26976-26978,26986-26987,26989-26991,26995-26997,26999-27001,27004-27006,27009-27010,27018,27022
chars=27025,27028-27029,27035-27036,27040,27047,27054,27057-27058,27060,27067,27070-27071,27073,27075
chars=27079,27082-27086,27088,27091,27096-27097,27101-27102,27111-27112,27115,27117,27122,27129,27131
chars=27133,27135,27138,27141,27146-27148,27154-27156,27159,27161,27163,27166-27167,27169-27171,27177
chars=27178-27179,27182,27189-27190,27192-27194,27197,27204,27207-27208,27211,27224-27225,27231,27233
chars=27234,27238,27250,27256,27263-27264,27268,27277-27278,27280,27287,27292,27296,27298-27299,27306
chars=27308,27310,27315,27320,27323,27329-27331,27345,27347,27354-27355,27358-27359,27368,27370,27386
chars=27387,27396-27397,27402,27410,27414,27421,27423-27425,27427,27431,27442,27447-27450,27453-27454
chars=27459,27463,27465,27468,27470,27472,27475-27476,27481,27483,27487,27489-27492,27494,27497-27498
chars=27503,27507-27508,27512-27513,27515,27519-27520,27523-27524,27526,27529-27531,27533,27541-27542
chars=27544,27550,27556,27562-27563,27567,27569-27573,27575,27578-27580,27583-27584,27589-27590,27595
chars=27597-27598,27602-27604,27608,27611,27615,27627-27628,27631,27635,27656,27663,27665,27667-27668
chars=27671,27675,27683-27684,27700,27703-27704,27710,27712-27714,27726,27728,27733,27735,27738,27741
chars=27742-27744,27746,27752,27754,27760,27762-27763,27770,27773-27774,27777-27779,27784,27788-27789
chars=27792,27794-27795,27798,27801-27803,27809-27810,27819,27822,27825,27827,27832-27839,27841,27844
chars=27845,27849-27850,27852,27859,27861,27863,27865,27867,27869,27873-27875,27877,27880,27882,27887
chars=27888-27889,27891,27915,27922,27927,27934,27941,27946,27963,27966,27969,27972-27973,27996,28006
chars=28009-28010,28014,28020,28023-28024,28040,28057,28079,28082,28092,28096,28129,28145,28147,28151
chars=28155,28165,28167-28169,28171,28187,28193,28198,28201,28204,28207,28246,28248,28263,28271,28286
chars=28287-28288,28304,28310,28316-28317,28322,28342,28357,28363,28369,28381-28382,28402,28404,28417
chars=28418,28431,28436,28448,28450,28459-28460,28500,28508,28511,28516,28526,28528,28548,28580,28608
chars=28609,28611,28641,28655,28716,28779,28783-28784,28796-28797,28809-28810,28814,28818,28844-28845
chars=28857-28858,28872,28954,28961,28966,28982,28988,29017,29031,29033,29038,29053,29066,29087,29105
chars=29123,29157,29165,29173,29190,29226,29238,29242,29245,29255-29256,29273,29275,29282,29287,29289
chars=29298,29305,29344,29356,29359,29366,29378,29401,29417,29420-29421,29436,29467,29471,29482-29483
chars=29486,29494,29503,29508,29539,29554,29572,29575,29577,29579,29645,29664,29677,29694,29699,29702
chars=29705,29730,29748,29790,29863,29872,29926,29942,29976,29983,29987,29992,30000-30003,30007,30010
chars=30011,30028,30033,30041,30044,30053,30058,30064,30067,30079,30094,30097,30123,30130,30142,30149
chars=30151,30169,30171,30185,30196,30202,30221,30274,30284,30290,30294,30330-30331,30333-30334,30340
chars=30342-30343,30382,30394,30399,30406,30410,30423,30427,30431,30435-30436,30439,30446,30450,30452
chars=30456,30462,30465,30473,30475-30476,30494-30496,30505,30522,30524,30528,30561,30563,30568,30609
chars=30636,30643,30652,30683,30690,30693,30697,30701,30703,30707,30722,30740-30741,30770,30772,30813
chars=30828,30849,30906,30913,30952,30990,31034,31036,31038,31048-31049,31062,31069-31070,31077,31080
chars=31085,31105,31119,31168-31169,31179,31185-31186,31192,31199,31209,31216,31227,31232,31243,31246
chars=31258,31278,31282,31292-31293,31295,31298,31309,31311,31339,31348,31350,31354,31361,31363,31379
chars=31391,31406,31435,31452,31456,31461,31471,31478,31481,31499,31505,31515,31520,31526,31532,31545
chars=31558,31560-31561,31563,31570,31572,31574,31623,31639,31649,31665,31672,31680,31684,31687,31689
chars=31761,31777,31807,31821,31840,31859,31881,31883,31890,31896,31911,31934,31958,31966,31975,31992
chars=31995,32000,32004-32005,32011,32013,32016,32020,32025-32027,32032,32034,32043,32047-32048,32051
chars=32057-32058,32066,32068,32070,32076,32080,32094,32097,32102,32113,32117-32118,32121,32153-32154
chars=32173,32177-32178,32180,32186-32187,32190-32191,32202,32207,32209-32210,32218,32224,32232-32233
chars=32239,32244,32257,32260,32283,32294,32302,32318,32321,32330-32331,32340,32368,32566,32608,32618
chars=32622,32624,32626,32645,32650,32654,32676,32680-32681,32701,32709,32716,32722,32724,32763-32764
chars=32769,32771,32773,32784,32791,32819,32854,32862,32865,32884,32887,32905,32908,32918,32925,32929
chars=32930,32933,32937-32938,32943,32946,32954,32963,32966,32972,32974,32990,32993,33016,33021,33026
chars=33029-33032,33050,33073,33075,33104,33107,33109,33131,33136,33144-33146,33178,33180-33181,33192
chars=33222,33235,33251,33256,33258,33261,33267-33268,33288,33292,33294,33296,33303,33307,33310-33311
chars=33322,33324,33337,33351,33382,33391,33394,33398,33437,33446,33455,33457,33459,33464,33469,33495
chars=33499,33509-33510,33521,33538,33540,33576,33590,33609,33618,33624,33655,33707,33733,33738,33740
chars=33747,33756,33775,33777,33804,33853,33865,33879,33883,33891,33900,33945,33976,33980,33988,33995
chars=34001,34030,34101,34109,34126,34180,34183,34196,34199,34214,34219-34220,34253,34276,34281,34299
chars=34311,34349,34382,34384,34394,34411,34425,34442,34503,34509,34521,34678,34701,34811,34821,34880
chars=34886,34892,34899,34903,34907,34909,34913,34915,34920,34928,34955,34966,34987,35009-35010,35013
chars=35023,35029,35036,35064,35069-35070,35079,35090,35186,35199,35201,35206-35207,35211,35215,35222
chars=35223,35226,35239,35242,35251,35282,35299,35302,35328,35330,35336,35338,35342,35347,35351-35352
chars=35357,35359,35363,35370,35373,35377,35379-35380,35386,35388,35408,35413,35422,35430,35433,35435
chars=35438,35440-35443,35463,35465,35468-35469,35475,35477,35480,35486,35488,35492,35500-35501,35504
chars=35506,35519,35527,35531,35542,35558,35565-35566,35576,35582,35584,35598,35609,35611,35613,35617
chars=35672,35676,35686,35696,35698,35703,35728,35895,35910,35914,35930,35937,35946,35980,35997-35998
chars=36000-36002,36007-36009,36011-36012,36015-36016,36020,36022-36024,36027-36028,36031-36032,36035
chars=36039,36042,36049,36059,36062,36064,36066,36074,36077,36092,36101,36104,36196,36198,36208,36212
chars=36215,36229,36234,36259,36275,36317,36321,36335,36339,36341,36362,36367,36468,36487,36490,36493
chars=36523,36554,36556-36557,36562,36575,36578,36600,36605,36611,36617,36628,36637,36649-36650,36664
chars=36676,36763,36766,36784-36786,36794-36796,36799,36804-36805,36814,36817,36820,36843,36848,36855
chars=36861,36864-36865,36867,36870,36879,36884,36889-36890,36893,36895-36896,36899,36910,36913-36914
chars=36920,36930,36933,36935,36938-36939,36941-36942,36947-36949,36960-36961,36963,36965,36969,36973
chars=36974,36981,36983-36984,36986,36989,36991,36996,37027,37030,37034,37048,37066,37070,37089,37096
chars=37101,37109,37111,37117,37197-37198,37202,37204,37218,37228,37237,37239-37240,37266,37276,37284
chars=37320,37324-37327,37329,37340-37341,37347,37351,37389,37428,37444,37474,37489,37504,37507,37509
chars=37528,37549,37613,37628,37679,37682,37707,37723,37749,37772,37782,37806,37857,37912,37969,38263
chars=38272,38275,38281,38283,38291,38306-38307,38309,38322,38343,38346,38360,38428,38442,38450,38459
chars=38463-38464,38477,38480,38498-38501,38506,38512,38515,38518,38520,38522,38525,38533-38534,38538
chars=38542-38543,38548,38553,38555-38556,38560,38563,38583,38588,38592,38596-38599,38609,38626-38627
chars=38632,38634,38640,38642,38646-38647,38651,38656,38663,38666,38686,38695,38706,38738,38742,38745
chars=38750,38754,38761,38772,38788,38867,38899,38907,38911,38913-38915,38917-38918,38920,38928-38929
chars=38931,38936,38956-38957,38967,38971-38972,38988-38990,38996-38997,39000,39006,39015,39080,39082
chars=39131,39135,39138,39151,39154,39156,39164-39166,39171,39173,39178,39180,39208,39318,39321,39340
chars=39348,39364-39366,39376,39378,39423,39438,39442-39443,39449,39472,39514,39592,39608,39640,39658
chars=39661,39706,39729,39740,39745-39746,39749,39764,39770,39791,39854,39881,40165,40169,40180,40335
chars=40372,40441,40474-40475,40478,40565,40568-40569,40573,40575,40577,40584,40587-40588,40593-40595
chars=40597,40599,40605,40607,40613-40614,40617-40618,40621,40632-40636,40638-40639,40644,40652-40656
chars=40658,40660,40664-40665,40667-40670,40672,40677,40680,40687,40692,40694-40695,40697,40699-40701
chars=40711-40712,40718,40723,40725,40736-40737,40748,40763,40766,40778-40779,40782-40783,40786,40788
chars=40799-40803,40806-40807,40810,40812,40818,40822-40823,40845,40853,40860-40861,40864,65281,65283
chars=65284-65286,65288-65374,65377-65439,65504-65507,65509
# imported icon images

Binary file not shown.

Before

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

View File

@ -1,330 +0,0 @@
use std::fmt::Debug;
use std::io::Cursor;
use std::io::ErrorKind;
use std::io::SeekFrom;
use std::path::{Component, Path, PathBuf};
use std::{fmt, io};
use crate::framework::error::GameError::FilesystemError;
use crate::framework::error::GameResult;
use crate::framework::vfs::{OpenOptions, VFile, VMetadata, VFS};
#[derive(Debug)]
pub struct BuiltinFile(Cursor<&'static [u8]>);
impl BuiltinFile {
pub fn from(buf: &'static [u8]) -> Box<dyn VFile> {
Box::new(BuiltinFile(Cursor::new(buf)))
}
}
impl io::Read for BuiltinFile {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.0.read(buf)
}
}
impl io::Seek for BuiltinFile {
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
self.0.seek(pos)
}
}
impl io::Write for BuiltinFile {
fn write(&mut self, _buf: &[u8]) -> io::Result<usize> {
Err(io::Error::new(ErrorKind::PermissionDenied, "Built-in file system is read-only."))
}
fn flush(&mut self) -> io::Result<()> {
Err(io::Error::new(ErrorKind::PermissionDenied, "Built-in file system is read-only."))
}
}
struct BuiltinMetadata {
is_dir: bool,
size: u64,
}
impl VMetadata for BuiltinMetadata {
fn is_dir(&self) -> bool {
self.is_dir
}
fn is_file(&self) -> bool {
!self.is_dir
}
fn len(&self) -> u64 {
self.size
}
}
#[derive(Clone, Debug)]
enum FSNode {
File(&'static str, &'static [u8]),
Directory(&'static str, Vec<FSNode>),
}
impl FSNode {
fn get_name(&self) -> &'static str {
match self {
FSNode::File(name, _) => name,
FSNode::Directory(name, _) => name,
}
}
fn to_file(&self) -> GameResult<Box<dyn VFile>> {
match self {
FSNode::File(_, buf) => Ok(BuiltinFile::from(buf)),
FSNode::Directory(name, _) => Err(FilesystemError(format!("{} is a directory.", name))),
}
}
fn to_metadata(&self) -> Box<dyn VMetadata> {
match self {
FSNode::File(_, buf) => Box::new(BuiltinMetadata { is_dir: false, size: buf.len() as u64 }),
FSNode::Directory(_, _) => Box::new(BuiltinMetadata { is_dir: true, size: 0 }),
}
}
}
pub struct BuiltinFS {
root: Vec<FSNode>,
}
impl BuiltinFS {
pub fn new() -> Self {
Self {
root: vec![FSNode::Directory(
"builtin",
vec![
FSNode::File("builtin_font.fnt", include_bytes!("builtin/builtin_font.fnt")),
FSNode::File("builtin_font_0.png", include_bytes!("builtin/builtin_font_0.png")),
FSNode::File("builtin_font_1.png", include_bytes!("builtin/builtin_font_1.png")),
FSNode::File("gamecontrollerdb.txt", include_bytes!("builtin/gamecontrollerdb.txt")),
FSNode::File(
"organya-wavetable-doukutsu.bin",
include_bytes!("builtin/organya-wavetable-doukutsu.bin"),
),
FSNode::File("touch.png", include_bytes!("builtin/touch.png")),
FSNode::Directory(
"builtin_data",
vec![
FSNode::File("buttons.png", include_bytes!("builtin/builtin_data/buttons.png")),
FSNode::File("triangles.png", include_bytes!("builtin/builtin_data/triangles.png")),
FSNode::Directory(
"headband",
vec![
FSNode::Directory(
"ogph",
vec![
FSNode::File(
"Casts.png",
include_bytes!("builtin/builtin_data/headband/ogph/Casts.png"),
),
FSNode::Directory(
"Npc",
vec![
FSNode::File(
"NpcGuest.png",
include_bytes!(
"builtin/builtin_data/headband/ogph/Npc/NpcGuest.png"
),
),
FSNode::File(
"NpcMiza.png",
include_bytes!(
"builtin/builtin_data/headband/ogph/Npc/NpcMiza.png"
),
),
FSNode::File(
"NpcRegu.png",
include_bytes!(
"builtin/builtin_data/headband/ogph/Npc/NpcRegu.png"
),
),
],
),
],
),
FSNode::Directory(
"plus",
vec![
FSNode::File(
"Casts.png",
include_bytes!("builtin/builtin_data/headband/plus/casts.png"),
),
FSNode::Directory(
"Npc",
vec![
FSNode::File(
"NpcGuest.png",
include_bytes!(
"builtin/builtin_data/headband/plus/npc/npcguest.png"
),
),
FSNode::File(
"NpcMiza.png",
include_bytes!(
"builtin/builtin_data/headband/plus/npc/npcmiza.png"
),
),
FSNode::File(
"NpcRegu.png",
include_bytes!(
"builtin/builtin_data/headband/plus/npc/npcregu.png"
),
),
],
),
],
),
],
),
FSNode::Directory(
"locale",
vec![
FSNode::File("en.json", include_bytes!("builtin/builtin_data/locale/en.json")),
FSNode::File("jp.json", include_bytes!("builtin/builtin_data/locale/jp.json")),
],
),
],
),
FSNode::Directory(
"shaders",
vec![
// FSNode::File("basic_150.vert.glsl", include_bytes!("builtin/shaders/basic_150.vert.glsl")),
// FSNode::File("water_150.frag.glsl", include_bytes!("builtin/shaders/water_150.frag.glsl")),
// FSNode::File("basic_es300.vert.glsl", include_bytes!("builtin/shaders/basic_es300.vert.glsl")),
// FSNode::File("water_es300.frag.glsl", include_bytes!("builtin/shaders/water_es300.frag.glsl")),
],
),
FSNode::Directory(
"lightmap",
vec![FSNode::File("spot.png", include_bytes!("builtin/lightmap/spot.png"))],
),
],
)],
}
}
fn get_node(&self, path: &Path) -> GameResult<FSNode> {
let mut iter = path.components().peekable();
if let Some(Component::RootDir) = iter.next() {
let mut curr_dir = &self.root;
if iter.peek().is_none() {
return Ok(FSNode::Directory("", self.root.clone()));
}
while let Some(comp) = iter.next() {
let comp_name = comp.as_os_str().to_string_lossy();
for file in curr_dir {
match file {
FSNode::File(name, _) if comp_name.eq(name) => {
return if iter.peek().is_some() {
Err(FilesystemError(format!("Expected a directory, found a file: {:?}", path)))
} else {
Ok(file.clone())
};
}
FSNode::Directory(name, contents) if comp_name.eq(name) => {
if iter.peek().is_some() {
curr_dir = contents;
break;
} else {
return Ok(file.clone());
}
}
_ => {}
}
}
}
} else {
return Err(FilesystemError("Path must be absolute.".to_string()));
}
Err(FilesystemError("File not found.".to_string()))
}
}
impl Debug for BuiltinFS {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(f, "<BuiltinFS>")
}
}
impl VFS for BuiltinFS {
fn open_options(&self, path: &Path, open_options: OpenOptions) -> GameResult<Box<dyn VFile>> {
if open_options.write || open_options.create || open_options.append || open_options.truncate {
let msg = format!("Cannot alter file {:?} in root {:?}, filesystem read-only", path, self);
return Err(FilesystemError(msg));
}
self.get_node(path)?.to_file()
}
fn mkdir(&self, _path: &Path) -> GameResult<()> {
Err(FilesystemError("Tried to make directory {} but FS is read-only".to_string()))
}
fn rm(&self, _path: &Path) -> GameResult<()> {
Err(FilesystemError("Tried to remove file {} but FS is read-only".to_string()))
}
fn rmrf(&self, _path: &Path) -> GameResult<()> {
Err(FilesystemError("Tried to remove file/dir {} but FS is read-only".to_string()))
}
fn exists(&self, path: &Path) -> bool {
self.get_node(path).is_ok()
}
fn metadata(&self, path: &Path) -> GameResult<Box<dyn VMetadata>> {
self.get_node(path).map(|v| v.to_metadata())
}
fn read_dir(&self, path: &Path) -> GameResult<Box<dyn Iterator<Item = GameResult<PathBuf>>>> {
match self.get_node(path) {
Ok(FSNode::Directory(_, contents)) => {
let mut vec = Vec::new();
for node in contents {
vec.push(Ok(PathBuf::from(node.get_name())))
}
Ok(Box::new(vec.into_iter()))
}
Ok(FSNode::File(_, _)) => Err(FilesystemError(format!("Expected a directory, found a file: {:?}", path))),
Err(e) => Err(e),
}
}
fn to_path_buf(&self) -> Option<PathBuf> {
None
}
}
#[test]
fn test_builtin_fs() {
let fs = BuiltinFS {
root: vec![
FSNode::File("test.txt", &[]),
FSNode::Directory(
"memes",
vec![
FSNode::File("nothing.txt", &[]),
FSNode::Directory("secret stuff", vec![FSNode::File("passwords.txt", b"12345678")]),
],
),
FSNode::File("test2.txt", &[]),
],
};
println!("{:?}", fs.get_node(Path::new("/")).unwrap());
println!("{:?}", fs.get_node(Path::new("/test.txt")).unwrap());
println!("{:?}", fs.get_node(Path::new("/memes")).unwrap());
println!("{:?}", fs.get_node(Path::new("/memes/nothing.txt")).unwrap());
println!("{:?}", fs.get_node(Path::new("/memes/secret stuff/passwords.txt")).unwrap());
}

View File

@ -3,12 +3,12 @@ use std::time::{SystemTime, UNIX_EPOCH};
use lazy_static::lazy_static;
use num_traits::{abs, Num};
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
use serde::de::{SeqAccess, Visitor};
use serde::ser::SerializeTupleStruct;
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
use crate::bitfield;
use crate::texture_set::G_MAG;
use crate::graphics::texture_set::G_MAG;
/// Multiply cave story degrees (0-255, which corresponds to 0°-360°) with this constant to get
/// respective value in radians.
@ -302,8 +302,8 @@ impl<T: Num + PartialOrd + Copy> Rect<T> {
impl<T: Num + PartialOrd + Copy + Serialize> Serialize for Rect<T> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
where
S: Serializer,
{
let mut state = serializer.serialize_tuple_struct("Rect", 4)?;
state.serialize_field(&self.left)?;

View File

@ -1,7 +1,10 @@
use crate::common::{Color, Rect};
use crate::frame::Frame;
use crate::stage::{BackgroundType, Stage, StageTexturePaths};
use crate::{graphics, Context, GameResult, SharedGameState};
use crate::framework::context::Context;
use crate::framework::error::GameResult;
use crate::framework::graphics;
use crate::game::frame::Frame;
use crate::game::shared_game_state::SharedGameState;
use crate::game::stage::{BackgroundType, Stage, StageTexturePaths};
pub struct Background {
pub tick: usize,

View File

@ -1,11 +1,11 @@
use crate::common::Rect;
use crate::entity::GameEntity;
use crate::frame::Frame;
use crate::framework::context::Context;
use crate::framework::error::GameResult;
use crate::npc::boss::BossNPC;
use crate::npc::list::NPCList;
use crate::shared_game_state::SharedGameState;
use crate::game::frame::Frame;
use crate::game::shared_game_state::SharedGameState;
use crate::game::npc::boss::BossNPC;
use crate::game::npc::list::NPCList;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]

View File

@ -1,11 +1,11 @@
use crate::common::{Color, Rect};
use crate::entity::GameEntity;
use crate::frame::Frame;
use crate::framework::context::Context;
use crate::framework::error::GameResult;
use crate::framework::graphics;
use crate::scripting::tsc::text_script::IllustrationState;
use crate::shared_game_state::SharedGameState;
use crate::game::frame::Frame;
use crate::game::shared_game_state::SharedGameState;
use crate::game::scripting::tsc::text_script::IllustrationState;
pub struct Credits {}

View File

@ -1,7 +1,7 @@
use crate::common::Rect;
use crate::shared_game_state::SharedGameState;
use crate::framework::context::Context;
use crate::framework::error::GameResult;
use crate::game::shared_game_state::SharedGameState;
#[derive(Debug, EnumIter, PartialEq, Eq, Hash, Copy, Clone)]
pub enum Alignment {

View File

@ -1,9 +1,9 @@
use crate::common::{FadeDirection, FadeState, Rect};
use crate::entity::GameEntity;
use crate::frame::Frame;
use crate::framework::context::Context;
use crate::framework::error::GameResult;
use crate::shared_game_state::SharedGameState;
use crate::game::frame::Frame;
use crate::game::shared_game_state::SharedGameState;
pub struct Fade;

View File

@ -2,12 +2,12 @@ use std::ops::Deref;
use crate::common::{Color, Rect};
use crate::entity::GameEntity;
use crate::frame::Frame;
use crate::framework::context::Context;
use crate::framework::error::GameResult;
use crate::graphics;
use crate::scripting::tsc::text_script::TextScriptExecutionState;
use crate::shared_game_state::SharedGameState;
use crate::framework::graphics;
use crate::game::frame::Frame;
use crate::game::shared_game_state::SharedGameState;
use crate::game::scripting::tsc::text_script::TextScriptExecutionState;
pub struct FallingIsland {}

View File

@ -1,10 +1,10 @@
use crate::common::{Color, Rect};
use crate::entity::GameEntity;
use crate::frame::Frame;
use crate::framework::context::Context;
use crate::framework::error::GameResult;
use crate::framework::graphics;
use crate::shared_game_state::SharedGameState;
use crate::game::frame::Frame;
use crate::game::shared_game_state::SharedGameState;
pub enum FlashState {
None,
@ -83,7 +83,7 @@ impl GameEntity<()> for Flash {
left: 0,
top: ((cen_y - width) * state.scale) as isize,
right: (state.canvas_size.0 * state.scale) as isize,
bottom: ((cen_y + width) * state.scale) as isize
bottom: ((cen_y + width) * state.scale) as isize,
};
graphics::draw_rect(ctx, rect, WHITE)?;
@ -93,7 +93,7 @@ impl GameEntity<()> for Flash {
left: ((cen_x - width) * state.scale) as isize,
top: 0,
right: ((cen_x + width) * state.scale) as isize,
bottom: (state.canvas_size.1 * state.scale) as isize
bottom: (state.canvas_size.1 * state.scale) as isize,
};
graphics::draw_rect(ctx, rect, WHITE)?;

View File

@ -1,14 +1,14 @@
use crate::common::Rect;
use crate::components::draw_common::{draw_number, Alignment};
use crate::components::draw_common::{Alignment, draw_number};
use crate::entity::GameEntity;
use crate::frame::Frame;
use crate::framework::context::Context;
use crate::framework::error::GameResult;
use crate::framework::graphics::screen_insets_scaled;
use crate::inventory::Inventory;
use crate::player::Player;
use crate::shared_game_state::SharedGameState;
use crate::weapon::WeaponType;
use crate::game::frame::Frame;
use crate::game::inventory::Inventory;
use crate::game::shared_game_state::SharedGameState;
use crate::game::player::Player;
use crate::game::weapon::WeaponType;
pub struct HUD {
pub alignment: Alignment,

View File

@ -1,16 +1,16 @@
use crate::common::Rect;
use crate::components::draw_common::{draw_number, Alignment};
use crate::components::draw_common::{Alignment, draw_number};
use crate::components::hud::HUD;
use crate::entity::GameEntity;
use crate::frame::Frame;
use crate::framework::context::Context;
use crate::framework::error::GameResult;
use crate::game::frame::Frame;
use crate::game::inventory::Inventory;
use crate::game::shared_game_state::SharedGameState;
use crate::input::touch_controls::TouchControlType;
use crate::inventory::Inventory;
use crate::player::Player;
use crate::scripting::tsc::text_script::{ScriptMode, TextScriptExecutionState};
use crate::shared_game_state::SharedGameState;
use crate::weapon::{WeaponLevel, WeaponType};
use crate::game::player::Player;
use crate::game::scripting::tsc::text_script::{ScriptMode, TextScriptExecutionState};
use crate::game::weapon::{WeaponLevel, WeaponType};
#[derive(Copy, Clone, PartialEq, Eq)]
#[repr(u8)]
@ -91,9 +91,9 @@ impl GameEntity<(&mut Context, &mut Player, &mut Inventory, &mut HUD)> for Inven
if state.control_flags.control_enabled()
&& (player.controller.trigger_inventory()
|| player.controller.trigger_menu_back()
|| (player.controller.trigger_menu_ok() && self.focus == InventoryFocus::Weapons)
|| (state.settings.touch_controls && state.touch_controls.consume_click_in(slot_rect)))
|| player.controller.trigger_menu_back()
|| (player.controller.trigger_menu_ok() && self.focus == InventoryFocus::Weapons)
|| (state.settings.touch_controls && state.touch_controls.consume_click_in(slot_rect)))
{
state.control_flags.set_ok_button_disabled(false);
self.exit(state, player, inventory, hud);

View File

@ -4,12 +4,12 @@ use crate::common::{Color, Rect};
use crate::framework::backend::{BackendTexture, SpriteBatchCommand};
use crate::framework::context::Context;
use crate::framework::error::GameResult;
use crate::graphics;
use crate::framework::graphics;
use crate::game::shared_game_state::SharedGameState;
use crate::game::stage::Stage;
use crate::input::touch_controls::TouchControlType;
use crate::player::Player;
use crate::scripting::tsc::text_script::TextScriptExecutionState;
use crate::shared_game_state::SharedGameState;
use crate::stage::Stage;
use crate::game::player::Player;
use crate::game::scripting::tsc::text_script::TextScriptExecutionState;
#[derive(Copy, Clone, Eq, PartialEq)]
pub enum MapSystemState {

View File

@ -1,17 +1,17 @@
use byteorder::{ReadBytesExt, WriteBytesExt, LE};
use byteorder::{LE, ReadBytesExt, WriteBytesExt};
use crate::common::Rect;
use crate::components::draw_common::{draw_number, draw_number_zeros, Alignment};
use crate::components::draw_common::{Alignment, draw_number, draw_number_zeros};
use crate::entity::GameEntity;
use crate::frame::Frame;
use crate::framework::context::Context;
use crate::framework::error::GameResult;
use crate::framework::filesystem;
use crate::framework::vfs::OpenOptions;
use crate::player::Player;
use crate::rng::RNG;
use crate::scripting::tsc::text_script::TextScriptExecutionState;
use crate::shared_game_state::{SharedGameState, TimingMode};
use crate::game::frame::Frame;
use crate::game::shared_game_state::{SharedGameState, TimingMode};
use crate::game::player::Player;
use crate::game::scripting::tsc::text_script::TextScriptExecutionState;
use crate::util::rng::RNG;
#[derive(Clone, Copy)]
pub struct NikumaruCounter {

View File

@ -1,9 +1,9 @@
use crate::common::{interpolate_fix9_scale, Rect};
use crate::entity::GameEntity;
use crate::frame::Frame;
use crate::framework::context::Context;
use crate::framework::error::GameResult;
use crate::shared_game_state::SharedGameState;
use crate::game::frame::Frame;
use crate::game::shared_game_state::SharedGameState;
#[derive(Debug, Copy, Clone)]
pub struct NumberPopup {

View File

@ -1,17 +1,17 @@
use std::io::{Cursor, Read};
use byteorder::{ReadBytesExt, WriteBytesExt, LE};
use byteorder::{LE, ReadBytesExt, WriteBytesExt};
use crate::entity::GameEntity;
use crate::frame::Frame;
use crate::framework::context::Context;
use crate::framework::error::GameResult;
use crate::framework::filesystem;
use crate::framework::keyboard::ScanCode;
use crate::framework::vfs::OpenOptions;
use crate::game::frame::Frame;
use crate::game::shared_game_state::{ReplayKind, ReplayState, SharedGameState};
use crate::input::replay_player_controller::{KeyState, ReplayController};
use crate::player::Player;
use crate::shared_game_state::{ReplayKind, ReplayState, SharedGameState};
use crate::game::player::Player;
#[derive(Clone)]
pub struct Replay {

View File

@ -1,13 +1,12 @@
use crate::framework::context::Context;
use crate::framework::error::GameResult;
use crate::common::Rect;
use crate::entity::GameEntity;
use crate::frame::Frame;
use crate::framework::context::Context;
use crate::framework::error::GameResult;
use crate::game::frame::Frame;
use crate::game::shared_game_state::SharedGameState;
use crate::input::touch_controls::TouchControlType;
use crate::player::Player;
use crate::shared_game_state::SharedGameState;
use crate::scripting::tsc::text_script::ScriptMode;
use crate::game::player::Player;
use crate::game::scripting::tsc::text_script::ScriptMode;
pub struct StageSelect {
pub current_teleport_slot: u8,

View File

@ -1,13 +1,12 @@
use crate::common::{Color, Rect};
use crate::engine_constants::AnimatedFace;
use crate::entity::GameEntity;
use crate::frame::Frame;
use crate::framework::context::Context;
use crate::framework::error::GameResult;
use crate::graphics;
use crate::graphics::draw_rect;
use crate::scripting::tsc::text_script::{ConfirmSelection, TextScriptExecutionState, TextScriptLine};
use crate::shared_game_state::SharedGameState;
use crate::framework::graphics;
use crate::game::frame::Frame;
use crate::game::shared_game_state::SharedGameState;
use crate::game::scripting::tsc::text_script::{ConfirmSelection, TextScriptExecutionState, TextScriptLine};
pub struct TextBoxes {
pub slide_in: u8,
@ -284,7 +283,7 @@ impl GameEntity<()> for TextBoxes {
};
x += left_pos + text_offset + 14.0;
draw_rect(
graphics::draw_rect(
ctx,
Rect::new_size(
(x * state.scale) as isize,

View File

@ -1,9 +1,9 @@
use crate::common::Rect;
use crate::frame::Frame;
use crate::framework::context::Context;
use crate::framework::error::GameResult;
use crate::shared_game_state::{SharedGameState, TileSize};
use crate::stage::{BackgroundType, Stage, StageTexturePaths};
use crate::game::frame::Frame;
use crate::game::shared_game_state::{SharedGameState, TileSize};
use crate::game::stage::{BackgroundType, Stage, StageTexturePaths};
pub struct Tilemap {
tick: u32,

View File

@ -1,18 +1,18 @@
use std::cell::RefCell;
use crate::common::{Color, Rect};
use crate::frame::Frame;
use crate::framework::backend::{BackendShader, SpriteBatchCommand, VertexData};
use crate::framework::context::Context;
use crate::framework::error::GameResult;
use crate::framework::graphics;
use crate::graphics::BlendMode;
use crate::map::{WaterParamEntry, WaterParams, WaterRegionType};
use crate::npc::list::NPCList;
use crate::physics::PhysicalEntity;
use crate::player::Player;
use crate::shared_game_state::SharedGameState;
use crate::stage::{BackgroundType, Stage};
use crate::framework::graphics::BlendMode;
use crate::game::frame::Frame;
use crate::game::map::{WaterParamEntry, WaterParams, WaterRegionType};
use crate::game::physics::PhysicalEntity;
use crate::game::shared_game_state::SharedGameState;
use crate::game::stage::{BackgroundType, Stage};
use crate::game::npc::list::NPCList;
use crate::game::player::Player;
const TENSION: f32 = 0.03;
const DAMPENING: f32 = 0.01;

View File

@ -1,11 +1,11 @@
use crate::common::{interpolate_fix9_scale, Direction, Rect};
use crate::common::{Direction, interpolate_fix9_scale, Rect};
use crate::entity::GameEntity;
use crate::frame::Frame;
use crate::framework::context::Context;
use crate::framework::error::GameResult;
use crate::player::{Player, TargetPlayer};
use crate::shared_game_state::SharedGameState;
use crate::weapon::bullet::{Bullet, BulletManager};
use crate::game::frame::Frame;
use crate::game::shared_game_state::SharedGameState;
use crate::game::player::{Player, TargetPlayer};
use crate::game::weapon::bullet::{Bullet, BulletManager};
pub struct WhimsicalStar {
pub star: [Star; 3],

View File

@ -4,12 +4,12 @@ use std::rc::Rc;
use imgui::{Image, MouseButton, Window, WindowFlags};
use crate::{Context, GameResult, graphics, I_MAG, SharedGameState};
use crate::common::{Color, Rect};
use crate::components::background::Background;
use crate::components::tilemap::{TileLayer, Tilemap};
use crate::frame::Frame;
use crate::stage::{Stage, StageTexturePaths};
use crate::{graphics, Context, GameResult, SharedGameState, I_MAG};
use crate::game::frame::Frame;
use crate::game::stage::{Stage, StageTexturePaths};
#[derive(Copy, Clone, Eq, PartialEq)]
pub enum CurrentTool {

View File

@ -1,7 +1,7 @@
use std::collections::HashMap;
use std::io::{BufRead, BufReader, Cursor, Read};
use byteorder::{ReadBytesExt, LE};
use byteorder::{LE, ReadBytesExt};
use case_insensitive_hashmap::CaseInsensitiveHashMap;
use xmltree::Element;
@ -12,11 +12,11 @@ use crate::framework::context::Context;
use crate::framework::error::GameResult;
use crate::framework::filesystem;
use crate::framework::gamepad::{Axis, Button};
use crate::game::settings::Settings;
use crate::game::shared_game_state::{FontData, Season};
use crate::i18n::Locale;
use crate::player::ControlMode;
use crate::scripting::tsc::text_script::TextScriptEncoding;
use crate::settings::Settings;
use crate::shared_game_state::{FontData, Season};
use crate::game::player::ControlMode;
use crate::game::scripting::tsc::text_script::TextScriptEncoding;
use crate::sound::pixtone::{Channel, Envelope, PixToneParameters, Waveform};
use crate::sound::SoundManager;

View File

@ -2,8 +2,8 @@ use std::fmt::Debug;
use std::marker::PhantomData;
use std::ops::Index;
use serde::de::{Error, SeqAccess, Visitor};
use serde::{Deserialize, Deserializer, Serialize};
use serde::de::{Error, SeqAccess, Visitor};
use crate::common::Rect;
use crate::macros::fmt::Formatter;
@ -14,8 +14,8 @@ pub struct SafeNPCRect<const T: usize>(pub [Rect<u16>; T]);
impl<const T: usize> Serialize for SafeNPCRect<T> {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
where
S: serde::Serializer,
{
self.0.serialize(serializer)
}
@ -31,8 +31,8 @@ impl<'de, const T: usize> Visitor<'de> for SafeNPCRectArrayVisitor<T> {
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
where
A: SeqAccess<'de>,
{
let mut rects = [Rect::default(); T];
for (i, rect) in rects.iter_mut().enumerate() {
@ -46,8 +46,8 @@ impl<'de, const T: usize> Visitor<'de> for SafeNPCRectArrayVisitor<T> {
impl<'de, const T: usize> Deserialize<'de> for SafeNPCRect<T> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
where
D: Deserializer<'de>,
{
deserializer.deserialize_seq(SafeNPCRectArrayVisitor(PhantomData)).map(SafeNPCRect)
}

View File

@ -1,8 +1,8 @@
use crate::common::interpolate_fix9_scale;
use crate::frame::Frame;
use crate::framework::context::Context;
use crate::framework::error::GameResult;
use crate::shared_game_state::SharedGameState;
use crate::game::frame::Frame;
use crate::game::shared_game_state::SharedGameState;
pub trait GameEntity<C> {
fn tick(&mut self, state: &mut SharedGameState, custom: C) -> GameResult;

View File

@ -1,127 +0,0 @@
use std::ops::Range;
use pelite::{
image::RT_BITMAP,
pe32::{headers::SectionHeaders, Pe, PeFile},
resources::{Directory, Entry, Name, Resources},
};
use crate::framework::error::{GameError::ParseError, GameResult};
#[derive(Debug)]
pub struct DataFile {
pub bytes: Vec<u8>,
pub name: String,
}
impl DataFile {
pub fn from(name: String, bytes: Vec<u8>) -> Self {
Self { name, bytes }
}
}
#[derive(Debug)]
pub struct ExeResourceDirectory {
pub name: String,
pub data_files: Vec<DataFile>,
}
impl ExeResourceDirectory {
pub fn new(name: String) -> Self {
Self { name, data_files: Vec::new() }
}
}
pub struct ExeParser<'a> {
pub resources: Resources<'a>,
pub section_headers: Box<&'a SectionHeaders>,
}
impl<'a> ExeParser<'a> {
pub fn from(file: &'a Vec<u8>) -> GameResult<Self> {
let pe = PeFile::from_bytes(file);
return match pe {
Ok(pe) => {
let resources = pe.resources();
if resources.is_err() {
return Err(ParseError("Failed to parse resources.".to_string()));
}
let section_headers = pe.section_headers();
Ok(Self { resources: resources.unwrap(), section_headers: Box::new(section_headers) })
}
Err(_) => Err(ParseError("Failed to parse PE file".to_string())),
};
}
pub fn get_resource_dir(&self, name: String) -> GameResult<ExeResourceDirectory> {
let mut dir_data = ExeResourceDirectory::new(name.to_owned());
let path = format!("/{}", name.to_owned());
let dir = self.resources.find_dir(&path);
return match dir {
Ok(dir) => {
self.read_dir(dir, &mut dir_data, "unknown".to_string());
Ok(dir_data)
}
Err(_) => return Err(ParseError("Failed to find resource directory.".to_string())),
};
}
pub fn get_bitmap_dir(&self) -> GameResult<ExeResourceDirectory> {
let mut dir_data = ExeResourceDirectory::new("Bitmap".to_string());
let root = self.resources.root().unwrap();
let dir = root.get_dir(Name::Id(RT_BITMAP.into()));
return match dir {
Ok(dir) => {
self.read_dir(dir, &mut dir_data, "unknown".to_string());
Ok(dir_data)
}
Err(_) => return Err(ParseError("Failed to open bitmap directory.".to_string())),
};
}
pub fn get_named_section_byte_range(&self, name: String) -> GameResult<Option<Range<u32>>> {
let section_header = self.section_headers.by_name(name.as_bytes());
return match section_header {
Some(section_header) => Ok(Some(section_header.file_range())),
None => Ok(None),
};
}
fn read_dir(&self, directory: Directory, dir_data: &mut ExeResourceDirectory, last_dir_name: String) {
for dir in directory.entries() {
let raw_entry = dir.entry();
if raw_entry.is_err() {
continue;
}
if let Entry::Directory(entry) = raw_entry.unwrap() {
let dir_name = dir.name();
let name = match dir_name {
Ok(name) => name.to_string(),
Err(_) => last_dir_name.to_owned(),
};
self.read_dir(entry, dir_data, name);
}
if let Entry::DataEntry(entry) = raw_entry.unwrap() {
let entry_bytes = entry.bytes();
if entry_bytes.is_err() {
continue;
}
let bytes = entry_bytes.unwrap();
let data_file = DataFile::from(last_dir_name.to_owned(), bytes.to_vec());
dir_data.data_files.push(data_file);
}
}
}
}

View File

@ -1,12 +1,12 @@
use imgui::DrawData;
use std::any::Any;
use imgui::DrawData;
use crate::common::{Color, Rect};
use crate::framework::context::Context;
use crate::framework::error::GameResult;
use crate::framework::graphics::BlendMode;
use crate::graphics::VSyncMode;
use crate::Game;
use crate::framework::graphics::{BlendMode, VSyncMode};
use crate::game::Game;
#[repr(C)]
#[derive(Copy, Clone)]
@ -102,14 +102,14 @@ pub fn init_backend(headless: bool, size_hint: (u16, u16)) -> GameResult<Box<dyn
}
#[cfg(all(feature = "backend-glutin"))]
{
return crate::framework::backend_glutin::GlutinBackend::new();
}
{
return crate::framework::backend_glutin::GlutinBackend::new();
}
#[cfg(feature = "backend-sdl")]
{
return crate::framework::backend_sdl2::SDL2Backend::new(size_hint);
}
{
return crate::framework::backend_sdl2::SDL2Backend::new(size_hint);
}
log::warn!("No backend compiled in, using null backend instead.");
crate::framework::backend_null::NullBackend::new()

View File

@ -4,12 +4,13 @@ use std::mem;
use std::rc::Rc;
use std::sync::Arc;
use glutin::{Api, ContextBuilder, GlProfile, GlRequest, PossiblyCurrent, WindowedContext};
use glutin::event::{ElementState, Event, TouchPhase, VirtualKeyCode, WindowEvent};
use glutin::event_loop::{ControlFlow, EventLoop};
use glutin::window::WindowBuilder;
use glutin::{Api, ContextBuilder, GlProfile, GlRequest, PossiblyCurrent, WindowedContext};
use imgui::{DrawCmdParams, DrawData, DrawIdx, DrawVert};
use crate::{Game, GAME_SUSPENDED};
use crate::common::Rect;
use crate::framework::backend::{Backend, BackendEventLoop, BackendRenderer, BackendTexture, SpriteBatchCommand};
use crate::framework::context::Context;
@ -18,7 +19,6 @@ use crate::framework::gl;
use crate::framework::keyboard::ScanCode;
use crate::framework::render_opengl::{GLContext, OpenGLRenderer};
use crate::input::touch_controls::TouchPoint;
use crate::{Game, GAME_SUSPENDED};
pub struct GlutinBackend;
@ -58,7 +58,7 @@ impl GlutinEventLoop {
let windowed_context = ContextBuilder::new();
let windowed_context = windowed_context.with_gl(GlRequest::Specific(Api::OpenGl, (3, 0)));
#[cfg(target_os = "android")]
let windowed_context = windowed_context.with_gl(GlRequest::Specific(Api::OpenGlEs, (2, 0)));
let windowed_context = windowed_context.with_gl(GlRequest::Specific(Api::OpenGlEs, (2, 0)));
let windowed_context = windowed_context
.with_gl_profile(GlProfile::Core)
@ -67,10 +67,10 @@ impl GlutinEventLoop {
.with_vsync(true);
#[cfg(target_os = "windows")]
{
use glutin::platform::windows::WindowBuilderExtWindows;
window = window.with_drag_and_drop(false);
}
{
use glutin::platform::windows::WindowBuilderExtWindows;
window = window.with_drag_and_drop(false);
}
window = window.with_title("doukutsu-rs");
@ -159,10 +159,10 @@ impl BackendEventLoop for GlutinEventLoop {
match event {
Event::WindowEvent { event: WindowEvent::CloseRequested, window_id }
if window_id == window.window().id() =>
{
state_ref.shutdown();
}
if window_id == window.window().id() =>
{
state_ref.shutdown();
}
Event::Resumed => {
{
let mut mutex = GAME_SUSPENDED.lock().unwrap();
@ -187,74 +187,74 @@ impl BackendEventLoop for GlutinEventLoop {
}
#[cfg(target_os = "android")]
unsafe {
unsafe {
window.surface_destroyed();
}
state_ref.sound_manager.pause();
}
Event::WindowEvent { event: WindowEvent::Resized(size), window_id }
if window_id == window.window().id() =>
{
if let Some(renderer) = &ctx.renderer {
if let Ok(imgui) = renderer.imgui() {
imgui.io_mut().display_size = [size.width as f32, size.height as f32];
if window_id == window.window().id() =>
{
if let Some(renderer) = &ctx.renderer {
if let Ok(imgui) = renderer.imgui() {
imgui.io_mut().display_size = [size.width as f32, size.height as f32];
}
ctx.real_screen_size = (size.width, size.height);
ctx.screen_size = get_scaled_size(size.width.max(1), size.height.max(1));
state_ref.handle_resize(ctx).unwrap();
}
ctx.real_screen_size = (size.width, size.height);
ctx.screen_size = get_scaled_size(size.width.max(1), size.height.max(1));
state_ref.handle_resize(ctx).unwrap();
}
}
Event::WindowEvent { event: WindowEvent::Touch(touch), window_id }
if window_id == window.window().id() =>
{
let mut controls = &mut state_ref.touch_controls;
let scale = state_ref.scale as f64;
let loc_x = (touch.location.x * ctx.screen_size.0 as f64 / ctx.real_screen_size.0 as f64) / scale;
let loc_y = (touch.location.y * ctx.screen_size.1 as f64 / ctx.real_screen_size.1 as f64) / scale;
if window_id == window.window().id() =>
{
let mut controls = &mut state_ref.touch_controls;
let scale = state_ref.scale as f64;
let loc_x = (touch.location.x * ctx.screen_size.0 as f64 / ctx.real_screen_size.0 as f64) / scale;
let loc_y = (touch.location.y * ctx.screen_size.1 as f64 / ctx.real_screen_size.1 as f64) / scale;
match touch.phase {
TouchPhase::Started | TouchPhase::Moved => {
if let Some(point) = controls.points.iter_mut().find(|p| p.id == touch.id) {
point.last_position = point.position;
point.position = (loc_x, loc_y);
} else {
controls.touch_id_counter = controls.touch_id_counter.wrapping_add(1);
match touch.phase {
TouchPhase::Started | TouchPhase::Moved => {
if let Some(point) = controls.points.iter_mut().find(|p| p.id == touch.id) {
point.last_position = point.position;
point.position = (loc_x, loc_y);
} else {
controls.touch_id_counter = controls.touch_id_counter.wrapping_add(1);
let point = TouchPoint {
id: touch.id,
touch_id: controls.touch_id_counter,
position: (loc_x, loc_y),
last_position: (0.0, 0.0),
};
controls.points.push(point);
let point = TouchPoint {
id: touch.id,
touch_id: controls.touch_id_counter,
position: (loc_x, loc_y),
last_position: (0.0, 0.0),
};
controls.points.push(point);
if touch.phase == TouchPhase::Started {
controls.clicks.push(point);
if touch.phase == TouchPhase::Started {
controls.clicks.push(point);
}
}
}
}
TouchPhase::Ended | TouchPhase::Cancelled => {
controls.points.retain(|p| p.id != touch.id);
controls.clicks.retain(|p| p.id != touch.id);
TouchPhase::Ended | TouchPhase::Cancelled => {
controls.points.retain(|p| p.id != touch.id);
controls.clicks.retain(|p| p.id != touch.id);
}
}
}
}
Event::WindowEvent { event: WindowEvent::KeyboardInput { input, .. }, window_id }
if window_id == window.window().id() =>
{
if let Some(keycode) = input.virtual_keycode {
if let Some(drs_scan) = conv_keycode(keycode) {
let key_state = match input.state {
ElementState::Pressed => true,
ElementState::Released => false,
};
if window_id == window.window().id() =>
{
if let Some(keycode) = input.virtual_keycode {
if let Some(drs_scan) = conv_keycode(keycode) {
let key_state = match input.state {
ElementState::Pressed => true,
ElementState::Released => false,
};
ctx.keyboard_context.set_key(drs_scan, key_state);
ctx.keyboard_context.set_key(drs_scan, key_state);
}
}
}
}
Event::RedrawRequested(id) if id == window.window().id() => {
{
let mutex = GAME_SUSPENDED.lock().unwrap();
@ -264,16 +264,16 @@ impl BackendEventLoop for GlutinEventLoop {
}
#[cfg(not(target_os = "android"))]
{
if let Err(err) = game.draw(ctx) {
log::error!("Failed to draw frame: {}", err);
{
if let Err(err) = game.draw(ctx) {
log::error!("Failed to draw frame: {}", err);
}
window.window().request_redraw();
}
window.window().request_redraw();
}
#[cfg(target_os = "android")]
request_android_redraw();
request_android_redraw();
}
Event::MainEventsCleared => {
if state_ref.shutdown {
@ -292,20 +292,20 @@ impl BackendEventLoop for GlutinEventLoop {
game.update(ctx).unwrap();
#[cfg(target_os = "android")]
{
match get_insets() {
Ok(insets) => {
ctx.screen_insets = insets;
{
match get_insets() {
Ok(insets) => {
ctx.screen_insets = insets;
}
Err(e) => {
log::error!("Failed to update insets: {}", e);
}
}
Err(e) => {
log::error!("Failed to update insets: {}", e);
}
}
if let Err(err) = game.draw(ctx) {
log::error!("Failed to draw frame: {}", err);
if let Err(err) = game.draw(ctx) {
log::error!("Failed to draw frame: {}", err);
}
}
}
if state_ref.next_scene.is_some() {
mem::swap(&mut game.scene, &mut state_ref.next_scene);
@ -320,7 +320,7 @@ impl BackendEventLoop for GlutinEventLoop {
});
}
fn new_renderer(&self, _ctx: *mut Context) -> GameResult<Box<dyn BackendRenderer>> {
fn new_renderer(&self, ctx: *mut Context) -> GameResult<Box<dyn BackendRenderer>> {
let mut imgui = imgui::Context::create();
imgui.io_mut().display_size = [640.0, 480.0];
@ -359,7 +359,7 @@ impl BackendEventLoop for GlutinEventLoop {
*user_data = Rc::into_raw(refs) as *mut c_void;
}
let gl_context = GLContext { gles2_mode: true, get_proc_address, swap_buffers, user_data };
let gl_context = GLContext { gles2_mode: true, is_sdl: false, get_proc_address, swap_buffers, user_data, ctx };
Ok(Box::new(OpenGLRenderer::new(gl_context, UnsafeCell::new(imgui))))
}

View File

@ -11,7 +11,7 @@ use crate::framework::backend::{
use crate::framework::context::Context;
use crate::framework::error::GameResult;
use crate::framework::graphics::BlendMode;
use crate::Game;
use crate::game::Game;
pub struct NullBackend;

View File

@ -7,9 +7,10 @@ use std::ptr::{null, null_mut};
use std::rc::Rc;
use std::time::{Duration, Instant};
use imgui::{ConfigFlags, DrawCmd, DrawData, DrawIdx, DrawVert, Key, MouseCursor, TextureId, Ui};
use imgui::internal::RawWrapper;
use imgui::sys::{ImGuiKey_Backspace, ImGuiKey_Delete, ImGuiKey_Enter};
use imgui::{ConfigFlags, DrawCmd, DrawData, DrawIdx, DrawVert, Key, MouseCursor, TextureId, Ui};
use sdl2::{controller, EventPump, GameControllerSubsystem, keyboard, pixels, Sdl, VideoSubsystem};
use sdl2::controller::GameController;
use sdl2::event::{Event, WindowEvent};
use sdl2::keyboard::Scancode;
@ -19,7 +20,6 @@ use sdl2::render::{Texture, TextureCreator, TextureQuery, WindowCanvas};
use sdl2::video::GLProfile;
use sdl2::video::Window;
use sdl2::video::WindowContext;
use sdl2::{controller, keyboard, pixels, EventPump, GameControllerSubsystem, Sdl, VideoSubsystem};
use crate::common::{Color, Rect};
use crate::framework::backend::{
@ -27,18 +27,15 @@ use crate::framework::backend::{
};
use crate::framework::context::Context;
use crate::framework::error::{GameError, GameResult};
use crate::framework::filesystem;
use crate::framework::gamepad::{Axis, Button};
use crate::framework::graphics::BlendMode;
use crate::framework::keyboard::ScanCode;
use crate::framework::render_opengl::{GLContext, OpenGLRenderer};
use crate::framework::ui::init_imgui;
use crate::graphics::VSyncMode;
use crate::shared_game_state::WindowMode;
use crate::Game;
use crate::GameError::RenderError;
use crate::GAME_SUSPENDED;
use super::filesystem;
use crate::game::Game;
use crate::game::GAME_SUSPENDED;
use crate::game::shared_game_state::WindowMode;
pub struct SDL2Backend {
context: Sdl,
@ -170,7 +167,7 @@ impl SDL2EventLoop {
window.resizable();
#[cfg(feature = "render-opengl")]
window.opengl();
window.opengl();
let window = window.build().map_err(|e| GameError::WindowError(e.to_string()))?;
let opengl_available = if let Ok(v) = std::env::var("CAVESTORY_NO_OPENGL") { v != "1" } else { true };
@ -212,7 +209,7 @@ impl BackendEventLoop for SDL2EventLoop {
loop {
#[cfg(target_os = "macos")]
unsafe {
unsafe {
use objc::*;
// no UB: fields are initialized by SDL_GetWindowWMInfo
@ -409,19 +406,19 @@ impl BackendEventLoop for SDL2EventLoop {
fn new_renderer(&self, ctx: *mut Context) -> GameResult<Box<dyn BackendRenderer>> {
#[cfg(feature = "render-opengl")]
{
let mut refs = self.refs.borrow_mut();
match refs.window.window().gl_create_context() {
Ok(gl_ctx) => {
refs.window.window().gl_make_current(&gl_ctx).map_err(|e| GameError::RenderError(e.to_string()))?;
refs.gl_context = Some(gl_ctx);
}
Err(err) => {
*self.opengl_available.borrow_mut() = false;
log::error!("Failed to initialize OpenGL context, falling back to SDL2 renderer: {}", err);
{
let mut refs = self.refs.borrow_mut();
match refs.window.window().gl_create_context() {
Ok(gl_ctx) => {
refs.window.window().gl_make_current(&gl_ctx).map_err(|e| GameError::RenderError(e.to_string()))?;
refs.gl_context = Some(gl_ctx);
}
Err(err) => {
*self.opengl_available.borrow_mut() = false;
log::error!("Failed to initialize OpenGL context, falling back to SDL2 renderer: {}", err);
}
}
}
}
#[cfg(feature = "render-opengl")]
if *self.opengl_available.borrow() {
@ -671,7 +668,7 @@ impl BackendRenderer for SDL2Renderer {
let sdl2_texture = texture
.as_any()
.downcast_ref::<SDL2Texture>()
.ok_or(RenderError("This texture was not created by SDL2 backend.".to_string()))?;
.ok_or(GameError::RenderError("This texture was not created by SDL2 backend.".to_string()))?;
unsafe {
if let Some(target) = &sdl2_texture.texture {
@ -866,7 +863,7 @@ impl BackendRenderer for SDL2Renderer {
texture
.as_any()
.downcast_ref::<SDL2Texture>()
.ok_or(RenderError("This texture was not created by SDL2 backend.".to_string()))?
.ok_or(GameError::RenderError("This texture was not created by SDL2 backend.".to_string()))?
.texture
.as_ref()
.map_or(null_mut(), |t| t.raw())

View File

@ -1,10 +1,10 @@
use crate::framework::backend::{init_backend, BackendRenderer};
use crate::framework::backend::{BackendRenderer, init_backend};
use crate::framework::error::GameResult;
use crate::framework::filesystem::Filesystem;
use crate::framework::gamepad::GamepadContext;
use crate::framework::graphics::VSyncMode;
use crate::framework::keyboard::KeyboardContext;
use crate::graphics::VSyncMode;
use crate::Game;
use crate::game::Game;
pub struct Context {
pub headless: bool,

View File

@ -3,8 +3,8 @@
use std::error::Error;
use std::fmt;
use std::string::FromUtf8Error;
use std::sync::mpsc::SendError;
use std::sync::{Arc, PoisonError};
use std::sync::mpsc::SendError;
/// An enum containing all kinds of game framework errors.
#[derive(Debug, Clone)]

View File

@ -160,7 +160,7 @@ impl Filesystem {
pub(crate) fn user_read_dir<P: AsRef<path::Path>>(
&self,
path: P,
) -> GameResult<Box<dyn Iterator<Item = path::PathBuf>>> {
) -> GameResult<Box<dyn Iterator<Item=path::PathBuf>>> {
let itr = self
.user_vfs
.read_dir(path.as_ref())?
@ -175,7 +175,7 @@ impl Filesystem {
pub(crate) fn read_dir<P: AsRef<path::Path>>(
&self,
path: P,
) -> GameResult<Box<dyn Iterator<Item = path::PathBuf>>> {
) -> GameResult<Box<dyn Iterator<Item=path::PathBuf>>> {
let itr = self
.vfs
.read_dir(path.as_ref())?
@ -303,7 +303,7 @@ pub fn user_is_dir<P: AsRef<path::Path>>(ctx: &Context, path: P) -> bool {
pub fn user_read_dir<P: AsRef<path::Path>>(
ctx: &Context,
path: P,
) -> GameResult<Box<dyn Iterator<Item = path::PathBuf>>> {
) -> GameResult<Box<dyn Iterator<Item=path::PathBuf>>> {
ctx.filesystem.user_read_dir(path)
}
@ -339,7 +339,7 @@ pub fn is_dir<P: AsRef<path::Path>>(ctx: &Context, path: P) -> bool {
/// in no particular order.
///
/// Lists the base directory if an empty path is given.
pub fn read_dir<P: AsRef<path::Path>>(ctx: &Context, path: P) -> GameResult<Box<dyn Iterator<Item = path::PathBuf>>> {
pub fn read_dir<P: AsRef<path::Path>>(ctx: &Context, path: P) -> GameResult<Box<dyn Iterator<Item=path::PathBuf>>> {
ctx.filesystem.read_dir(path)
}
@ -347,7 +347,7 @@ pub fn read_dir_find<P: AsRef<path::Path>>(
ctx: &Context,
roots: &Vec<String>,
path: P,
) -> GameResult<Box<dyn Iterator<Item = path::PathBuf>>> {
) -> GameResult<Box<dyn Iterator<Item=path::PathBuf>>> {
let mut files = Vec::new();
for root in roots {

View File

@ -3,10 +3,9 @@ use std::collections::{HashMap, HashSet};
use sdl2::controller::GameController;
use serde::{Deserialize, Serialize};
use crate::shared_game_state::SharedGameState;
use crate::{common::Rect, engine_constants::EngineConstants, framework::context::Context};
use crate::framework::error::GameResult;
use crate::game::shared_game_state::SharedGameState;
const QUAKE_RUMBLE_LOW_FREQ: u16 = 0x3000;
const QUAKE_RUMBLE_HI_FREQ: u16 = 0;

File diff suppressed because it is too large Load Diff

View File

@ -178,7 +178,7 @@ pub fn prepare_draw(ctx: &mut Context) -> GameResult {
pub fn supports_vertex_draw(ctx: &Context) -> GameResult<bool> {
if let Some(renderer) = ctx.renderer.as_ref() {
return Ok(renderer.supports_vertex_draw())
return Ok(renderer.supports_vertex_draw());
}
Err(GameError::RenderError("Rendering backend hasn't been initialized yet.".to_string()))

View File

@ -17,9 +17,9 @@ use crate::framework::error::GameError::RenderError;
use crate::framework::error::GameResult;
use crate::framework::gl;
use crate::framework::gl::types::*;
use crate::framework::graphics::BlendMode;
use crate::framework::graphics::{BlendMode, VSyncMode};
use crate::framework::util::{field_offset, return_param};
use crate::graphics::VSyncMode;
use crate::game::GAME_SUSPENDED;
pub struct GLContext {
pub gles2_mode: bool,
@ -774,7 +774,7 @@ impl BackendRenderer for OpenGLRenderer {
fn present(&mut self) -> GameResult {
{
let mutex = crate::GAME_SUSPENDED.lock().unwrap();
let mutex = GAME_SUSPENDED.lock().unwrap();
if *mutex {
return Ok(());
}
@ -826,7 +826,7 @@ impl BackendRenderer for OpenGLRenderer {
}
#[cfg(feature = "backend-sdl")]
unsafe {
unsafe {
let ctx = &mut *self.refs.ctx;
match mode {

View File

@ -5,11 +5,10 @@ use imgui::sys::*;
use crate::framework::context::Context;
use crate::framework::error::GameResult;
use crate::framework::graphics::{imgui_context, render_imgui};
use crate::graphics::prepare_imgui;
use crate::framework::graphics::{imgui_context, prepare_imgui, render_imgui};
use crate::game::shared_game_state::SharedGameState;
use crate::live_debugger::LiveDebugger;
use crate::scene::Scene;
use crate::shared_game_state::SharedGameState;
pub struct UI {
pub components: Components,
@ -23,11 +22,7 @@ pub struct Components {
pub fn init_imgui() -> GameResult<imgui::Context> {
let mut imgui = imgui::Context::create();
imgui.set_ini_filename(None);
imgui.fonts().add_font(&[
FontSource::DefaultFontData {
config: Some(FontConfig::default()),
},
]);
imgui.fonts().add_font(&[FontSource::DefaultFontData { config: Some(FontConfig::default()) }]);
imgui.style_mut().window_padding = [4.0, 6.0];
imgui.style_mut().frame_padding = [8.0, 6.0];
@ -109,16 +104,11 @@ pub fn init_imgui() -> GameResult<imgui::Context> {
impl UI {
pub fn new(_ctx: &mut Context) -> GameResult<Self> {
Ok(Self {
components: Components {
live_debugger: LiveDebugger::new(),
},
last_frame: Instant::now(),
})
Ok(Self { components: Components { live_debugger: LiveDebugger::new() }, last_frame: Instant::now() })
}
pub fn draw(&mut self, state: &mut SharedGameState, ctx: &mut Context, scene: &mut Box<dyn Scene>) -> GameResult {
let ctx2 = unsafe { &mut *(ctx as *const Context as *mut Context)};
let ctx2 = unsafe { &mut *(ctx as *const Context as *mut Context) };
let imgui = imgui_context(ctx)?;
let io = imgui.io_mut();
let now = Instant::now();

View File

@ -128,7 +128,7 @@ pub trait VFS: Debug {
fn metadata(&self, path: &Path) -> GameResult<Box<dyn VMetadata>>;
/// Retrieve all file and directory entries in the given directory.
fn read_dir(&self, path: &Path) -> GameResult<Box<dyn Iterator<Item = GameResult<PathBuf>>>>;
fn read_dir(&self, path: &Path) -> GameResult<Box<dyn Iterator<Item=GameResult<PathBuf>>>>;
/// Retrieve the actual location of the VFS root, if available.
fn to_path_buf(&self) -> Option<PathBuf>;
@ -376,7 +376,7 @@ impl VFS for PhysicalFS {
}
/// Retrieve the path entries in this path
fn read_dir(&self, path: &Path) -> GameResult<Box<dyn Iterator<Item = GameResult<PathBuf>>>> {
fn read_dir(&self, path: &Path) -> GameResult<Box<dyn Iterator<Item=GameResult<PathBuf>>>> {
self.create_root()?;
let p = self.to_absolute(path)?;
// This is inconvenient because path() returns the full absolute
@ -511,7 +511,7 @@ impl VFS for OverlayFS {
}
/// Retrieve the path entries in this path
fn read_dir(&self, path: &Path) -> GameResult<Box<dyn Iterator<Item = GameResult<PathBuf>>>> {
fn read_dir(&self, path: &Path) -> GameResult<Box<dyn Iterator<Item=GameResult<PathBuf>>>> {
// This is tricky 'cause we have to actually merge iterators together...
// Doing it the simple and stupid way works though.
let mut v = Vec::new();

View File

@ -1,6 +1,6 @@
use crate::common::{Condition, Direction, Rect, CDEG_RAD};
use crate::common::{CDEG_RAD, Condition, Direction, Rect};
use crate::engine_constants::EngineConstants;
use crate::rng::RNG;
use crate::util::rng::RNG;
#[derive(Debug, EnumIter, PartialEq, Eq, Hash, Copy, Clone)]
pub enum CaretType {

View File

@ -1,7 +1,7 @@
use crate::common::{fix9_scale, interpolate_fix9_scale};
use crate::rng::RNG;
use crate::shared_game_state::SharedGameState;
use crate::stage::Stage;
use crate::game::shared_game_state::SharedGameState;
use crate::game::stage::Stage;
use crate::util::rng::RNG;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]

View File

@ -1,10 +1,10 @@
use std::cmp::Ordering;
use crate::engine_constants::EngineConstants;
use crate::shared_game_state::SharedGameState;
use crate::weapon::{Weapon, WeaponLevel, WeaponType};
use crate::player::{Player, TargetPlayer};
use crate::weapon::bullet::BulletManager;
use crate::game::player::{Player, TargetPlayer};
use crate::game::shared_game_state::SharedGameState;
use crate::game::weapon::{Weapon, WeaponLevel, WeaponType};
use crate::game::weapon::bullet::BulletManager;
#[derive(Clone, Copy)]
/// (id, amount)

View File

@ -3,16 +3,16 @@ use std::io;
use std::io::{BufRead, BufReader, Cursor, Read};
use std::sync::Arc;
use byteorder::{ReadBytesExt, LE};
use byteorder::{LE, ReadBytesExt};
use crate::common::{Color, Rect};
use crate::encoding::read_cur_shift_jis;
use crate::framework::context::Context;
use crate::framework::error::GameError::ResourceLoadError;
use crate::framework::error::{GameError, GameResult};
use crate::framework::error::GameError::ResourceLoadError;
use crate::framework::filesystem;
use crate::shared_game_state::TileSize;
use crate::stage::{PxPackScroll, PxPackStageData, StageData};
use crate::game::shared_game_state::TileSize;
use crate::game::stage::{PxPackScroll, PxPackStageData, StageData};
use crate::util::encoding::read_cur_shift_jis;
static SUPPORTED_PXM_VERSIONS: [u8; 1] = [0x10];
static SUPPORTED_PXE_VERSIONS: [u8; 2] = [0, 0x10];
@ -211,7 +211,7 @@ impl Map {
log::warn!("Map attribute data is shorter than 256 bytes!");
}
} else if let Ok(mut attrib_data) =
filesystem::open_find(ctx, roots, ["Stage/", &tileset_fg, ".pxattr"].join(""))
filesystem::open_find(ctx, roots, ["Stage/", &tileset_fg, ".pxattr"].join(""))
{
attrib_data.read_exact(&mut magic)?;
@ -549,7 +549,7 @@ impl WaterParams {
}
pub fn load_from<R: io::Read>(&mut self, data: R) -> GameResult {
fn next_u8<'a>(s: &mut impl Iterator<Item = &'a str>, error_msg: &str) -> GameResult<u8> {
fn next_u8<'a>(s: &mut impl Iterator<Item=&'a str>, error_msg: &str) -> GameResult<u8> {
match s.next() {
None => Err(GameError::ParseError("Out of range.".to_string())),
Some(v) => v.trim().parse::<u8>().map_err(|_| GameError::ParseError(error_msg.to_string())),

329
src/game/mod.rs Normal file
View File

@ -0,0 +1,329 @@
use std::cell::UnsafeCell;
use std::path::PathBuf;
use std::sync::Mutex;
use std::time::{Duration, Instant};
use lazy_static::lazy_static;
use scripting::tsc::text_script::ScriptMode;
use crate::data::builtin_fs::BuiltinFS;
use crate::framework::context::Context;
use crate::framework::error::GameResult;
use crate::framework::filesystem::{mount_user_vfs, mount_vfs};
use crate::framework::graphics;
use crate::framework::graphics::VSyncMode;
use crate::framework::ui::UI;
use crate::framework::vfs::PhysicalFS;
use crate::game::shared_game_state::{Fps, SharedGameState, TimingMode};
use crate::graphics::texture_set::{G_MAG, I_MAG};
use crate::scene::loading_scene::LoadingScene;
use crate::scene::Scene;
pub mod caret;
pub mod frame;
pub mod inventory;
pub mod map;
pub mod physics;
pub mod profile;
pub mod settings;
pub mod shared_game_state;
pub mod stage;
pub mod npc;
pub mod player;
pub mod weapon;
pub mod scripting;
pub struct LaunchOptions {
pub server_mode: bool,
pub editor: bool,
}
lazy_static! {
pub static ref GAME_SUSPENDED: Mutex<bool> = Mutex::new(false);
}
pub struct Game {
pub(crate) scene: Option<Box<dyn Scene>>,
pub(crate) state: UnsafeCell<SharedGameState>,
ui: UI,
start_time: Instant,
last_tick: u128,
next_tick: u128,
pub(crate) loops: u32,
next_tick_draw: u128,
present: bool,
fps: Fps,
}
impl Game {
fn new(ctx: &mut Context) -> GameResult<Game> {
let s = Game {
scene: None,
ui: UI::new(ctx)?,
state: UnsafeCell::new(SharedGameState::new(ctx)?),
start_time: Instant::now(),
last_tick: 0,
next_tick: 0,
loops: 0,
next_tick_draw: 0,
present: true,
fps: Fps::new(),
};
Ok(s)
}
pub(crate) fn update(&mut self, ctx: &mut Context) -> GameResult {
if let Some(scene) = &mut self.scene {
let state_ref = unsafe { &mut *self.state.get() };
let speed =
if state_ref.textscript_vm.mode == ScriptMode::Map && state_ref.textscript_vm.flags.cutscene_skip() {
4.0 * state_ref.settings.speed
} else {
1.0 * state_ref.settings.speed
};
match state_ref.settings.timing_mode {
TimingMode::_50Hz | TimingMode::_60Hz => {
let last_tick = self.next_tick;
while self.start_time.elapsed().as_nanos() >= self.next_tick && self.loops < 10 {
if (speed - 1.0).abs() < 0.01 {
self.next_tick += state_ref.settings.timing_mode.get_delta() as u128;
} else {
self.next_tick += (state_ref.settings.timing_mode.get_delta() as f64 / speed) as u128;
}
self.loops += 1;
}
if self.loops == 10 {
log::warn!("Frame skip is way too high, a long system lag occurred?");
self.last_tick = self.start_time.elapsed().as_nanos();
self.next_tick =
self.last_tick + (state_ref.settings.timing_mode.get_delta() as f64 / speed) as u128;
self.loops = 0;
}
if self.loops != 0 {
scene.draw_tick(state_ref)?;
self.last_tick = last_tick;
}
for _ in 0..self.loops {
scene.tick(state_ref, ctx)?;
}
self.fps.tick_count = self.fps.tick_count.saturating_add(self.loops as u32);
}
TimingMode::FrameSynchronized => {
scene.tick(state_ref, ctx)?;
}
}
}
Ok(())
}
pub(crate) fn draw(&mut self, ctx: &mut Context) -> GameResult {
let state_ref = unsafe { &mut *self.state.get() };
match ctx.vsync_mode {
VSyncMode::Uncapped | VSyncMode::VSync => {
self.present = true;
}
_ => unsafe {
self.present = false;
let divisor = match ctx.vsync_mode {
VSyncMode::VRRTickSync1x => 1,
VSyncMode::VRRTickSync2x => 2,
VSyncMode::VRRTickSync3x => 3,
_ => std::hint::unreachable_unchecked(),
};
let delta = (state_ref.settings.timing_mode.get_delta() / divisor) as u64;
let now = self.start_time.elapsed().as_nanos();
if now > self.next_tick_draw + delta as u128 * 4 {
self.next_tick_draw = now;
}
while self.start_time.elapsed().as_nanos() >= self.next_tick_draw {
self.next_tick_draw += delta as u128;
self.present = true;
}
},
}
if !self.present {
std::thread::sleep(Duration::from_millis(2));
self.loops = 0;
return Ok(());
}
if ctx.headless {
self.loops = 0;
state_ref.frame_time = 1.0;
return Ok(());
}
if state_ref.settings.timing_mode != TimingMode::FrameSynchronized {
let mut elapsed = self.start_time.elapsed().as_nanos();
// Even with the non-monotonic Instant mitigation at the start of the event loop, there's still a chance of it not working.
// This check here should trigger if that happens and makes sure there's no panic from an underflow.
if elapsed < self.last_tick {
elapsed = self.last_tick;
}
let n1 = (elapsed - self.last_tick) as f64;
let n2 = (self.next_tick - self.last_tick) as f64;
state_ref.frame_time = if state_ref.settings.motion_interpolation { n1 / n2 } else { 1.0 };
}
unsafe {
G_MAG = if state_ref.settings.subpixel_coords { state_ref.scale } else { 1.0 };
I_MAG = state_ref.scale;
}
self.loops = 0;
graphics::prepare_draw(ctx)?;
graphics::clear(ctx, [0.0, 0.0, 0.0, 1.0].into());
if let Some(scene) = &mut self.scene {
scene.draw(state_ref, ctx)?;
if state_ref.settings.touch_controls {
state_ref.touch_controls.draw(
state_ref.canvas_size,
state_ref.scale,
&state_ref.constants,
&mut state_ref.texture_set,
ctx,
)?;
}
if state_ref.settings.fps_counter {
self.fps.act(state_ref, ctx, self.start_time.elapsed().as_nanos())?;
}
self.ui.draw(state_ref, ctx, scene)?;
}
graphics::present(ctx)?;
Ok(())
}
}
pub fn init(options: LaunchOptions) -> GameResult {
let _ = simple_logger::SimpleLogger::new()
.without_timestamps()
.with_colors(true)
.with_level(log::Level::Info.to_level_filter())
.init();
#[cfg(not(target_os = "android"))]
let resource_dir = if let Ok(data_dir) = std::env::var("CAVESTORY_DATA_DIR") {
PathBuf::from(data_dir)
} else {
let mut resource_dir = std::env::current_exe()?;
if resource_dir.file_name().is_some() {
let _ = resource_dir.pop();
}
#[cfg(target_os = "macos")]
{
let mut bundle_dir = resource_dir.clone();
let _ = bundle_dir.pop();
let mut bundle_exec_dir = bundle_dir.clone();
let mut csplus_data_dir = bundle_dir.clone();
let _ = csplus_data_dir.pop();
let _ = csplus_data_dir.pop();
let mut csplus_data_base_dir = csplus_data_dir.clone();
csplus_data_base_dir.push("data");
csplus_data_base_dir.push("base");
bundle_exec_dir.push("MacOS");
bundle_dir.push("Resources");
if bundle_exec_dir.is_dir() && bundle_dir.is_dir() {
log::info!("Running in macOS bundle mode");
if csplus_data_base_dir.is_dir() {
log::info!("Cave Story+ Steam detected");
resource_dir = csplus_data_dir;
} else {
resource_dir = bundle_dir;
}
}
}
resource_dir.push("data");
resource_dir
};
#[cfg(not(target_os = "android"))]
log::info!("Resource directory: {:?}", resource_dir);
log::info!("Initializing engine...");
let mut context = Context::new();
#[cfg(not(target_os = "android"))]
mount_vfs(&mut context, Box::new(PhysicalFS::new(&resource_dir, true)));
#[cfg(not(target_os = "android"))]
let project_dirs = match directories::ProjectDirs::from("", "", "doukutsu-rs") {
Some(dirs) => dirs,
None => {
use crate::framework::error::GameError;
return Err(GameError::FilesystemError(String::from("No valid home directory path could be retrieved.")));
}
};
#[cfg(target_os = "android")]
{
let mut data_path =
PathBuf::from(ndk_glue::native_activity().internal_data_path().to_string_lossy().to_string());
let mut user_path = data_path.clone();
data_path.push("data");
user_path.push("saves");
let _ = std::fs::create_dir_all(&data_path);
let _ = std::fs::create_dir_all(&user_path);
log::info!("Android data directories: data_path={:?} user_path={:?}", &data_path, &user_path);
mount_vfs(&mut context, Box::new(PhysicalFS::new(&data_path, true)));
mount_user_vfs(&mut context, Box::new(PhysicalFS::new(&user_path, false)));
}
#[cfg(not(target_os = "android"))]
{
if crate::framework::filesystem::open(&context, "/.drs_localstorage").is_ok() {
let mut user_dir = resource_dir.clone();
user_dir.push("_drs_profile");
let _ = std::fs::create_dir_all(&user_dir);
mount_user_vfs(&mut context, Box::new(PhysicalFS::new(&user_dir, false)));
} else {
mount_user_vfs(&mut context, Box::new(PhysicalFS::new(project_dirs.data_local_dir(), false)));
}
}
mount_vfs(&mut context, Box::new(BuiltinFS::new()));
if options.server_mode {
log::info!("Running in server mode...");
context.headless = true;
}
let game = UnsafeCell::new(Game::new(&mut context)?);
let state_ref = unsafe { &mut *((&mut *game.get()).state.get()) };
#[cfg(feature = "scripting-lua")]
{
state_ref.lua.update_refs(unsafe { (&*game.get()).state.get() }, &mut context as *mut Context);
}
state_ref.next_scene = Some(Box::new(LoadingScene::new()));
context.run(unsafe { &mut *game.get() })?;
Ok(())
}

View File

@ -1,9 +1,10 @@
use crate::common::Direction;
use crate::npc::list::NPCList;
use crate::npc::NPC;
use crate::player::Player;
use crate::rng::RNG;
use crate::{GameResult, SharedGameState};
use crate::framework::error::GameResult;
use crate::game::npc::list::NPCList;
use crate::game::npc::NPC;
use crate::game::player::Player;
use crate::game::shared_game_state::SharedGameState;
use crate::util::rng::RNG;
impl NPC {
pub(crate) fn tick_n254_helicopter(&mut self, state: &mut SharedGameState, npc_list: &NPCList) -> GameResult {

View File

@ -1,14 +1,14 @@
use num_traits::clamp;
use crate::caret::CaretType;
use crate::common::{Direction, CDEG_RAD};
use crate::common::{CDEG_RAD, Direction};
use crate::framework::error::GameResult;
use crate::npc::list::NPCList;
use crate::npc::NPC;
use crate::player::Player;
use crate::rng::RNG;
use crate::shared_game_state::SharedGameState;
use crate::stage::Stage;
use crate::game::caret::CaretType;
use crate::game::npc::list::NPCList;
use crate::game::npc::NPC;
use crate::game::player::Player;
use crate::game::shared_game_state::SharedGameState;
use crate::game::stage::Stage;
use crate::util::rng::RNG;
impl NPC {
pub(crate) fn tick_n009_balrog_falling_in(

View File

@ -1,9 +1,8 @@
use crate::framework::error::GameResult;
use crate::common::Direction;
use crate::npc::NPC;
use crate::rng::RNG;
use crate::shared_game_state::SharedGameState;
use crate::framework::error::GameResult;
use crate::game::npc::NPC;
use crate::game::shared_game_state::SharedGameState;
use crate::util::rng::RNG;
impl NPC {
pub(crate) fn tick_n113_professor_booster(&mut self, state: &mut SharedGameState) -> GameResult {

View File

@ -1,11 +1,10 @@
use crate::framework::error::GameResult;
use crate::caret::CaretType;
use crate::common::Direction;
use crate::npc::NPC;
use crate::player::Player;
use crate::rng::RNG;
use crate::shared_game_state::SharedGameState;
use crate::framework::error::GameResult;
use crate::game::caret::CaretType;
use crate::game::npc::NPC;
use crate::game::player::Player;
use crate::game::shared_game_state::SharedGameState;
use crate::util::rng::RNG;
impl NPC {
pub(crate) fn tick_n093_chaco(&mut self, state: &mut SharedGameState, players: [&mut Player; 2]) -> GameResult {

View File

@ -2,11 +2,11 @@ use num_traits::{abs, clamp};
use crate::common::Direction;
use crate::framework::error::GameResult;
use crate::npc::list::NPCList;
use crate::npc::NPC;
use crate::player::Player;
use crate::rng::RNG;
use crate::shared_game_state::SharedGameState;
use crate::game::npc::list::NPCList;
use crate::game::npc::NPC;
use crate::game::player::Player;
use crate::game::shared_game_state::SharedGameState;
use crate::util::rng::RNG;
impl NPC {
pub(crate) fn tick_n029_cthulhu(&mut self, state: &mut SharedGameState, players: [&mut Player; 2]) -> GameResult {

View File

@ -1,14 +1,14 @@
use num_traits::{abs, clamp};
use crate::caret::CaretType;
use crate::common::{Direction, Rect};
use crate::framework::error::GameResult;
use crate::npc::list::NPCList;
use crate::npc::NPC;
use crate::player::{Player, TargetPlayer};
use crate::rng::RNG;
use crate::shared_game_state::SharedGameState;
use crate::weapon::bullet::BulletManager;
use crate::game::caret::CaretType;
use crate::game::npc::list::NPCList;
use crate::game::npc::NPC;
use crate::game::player::{Player, TargetPlayer};
use crate::game::shared_game_state::SharedGameState;
use crate::game::weapon::bullet::BulletManager;
use crate::util::rng::RNG;
impl NPC {
pub(crate) fn tick_n117_curly(
@ -581,12 +581,12 @@ impl NPC {
} else {
self.x = parent.x
+ if parent.direction == Direction::Left {
self.direction = Direction::Left;
-0x1000
} else {
self.direction = Direction::Right;
0x1000
};
self.direction = Direction::Left;
-0x1000
} else {
self.direction = Direction::Right;
0x1000
};
self.y = parent.y;
self.anim_num = 0;
}
@ -675,12 +675,12 @@ impl NPC {
} else {
self.x = parent.x
+ if parent.direction == Direction::Left {
self.direction = Direction::Left;
-0x1000
} else {
self.direction = Direction::Right;
0x1000
};
self.direction = Direction::Left;
-0x1000
} else {
self.direction = Direction::Right;
0x1000
};
self.y = parent.y;
self.anim_num = 0;
}

View File

@ -1,11 +1,11 @@
use crate::common::{Direction, Rect, CDEG_RAD};
use crate::common::{CDEG_RAD, Direction, Rect};
use crate::framework::error::GameResult;
use crate::npc::list::NPCList;
use crate::npc::NPC;
use crate::player::Player;
use crate::rng::RNG;
use crate::shared_game_state::SharedGameState;
use crate::stage::Stage;
use crate::game::npc::list::NPCList;
use crate::game::npc::NPC;
use crate::game::player::Player;
use crate::game::shared_game_state::SharedGameState;
use crate::game::stage::Stage;
use crate::util::rng::RNG;
impl NPC {
pub(crate) fn tick_n139_doctor(&mut self, state: &mut SharedGameState) -> GameResult {

View File

@ -1,14 +1,14 @@
use num_traits::{abs, clamp};
use crate::caret::CaretType;
use crate::common::{Direction, Rect, CDEG_RAD};
use crate::common::{CDEG_RAD, Direction, Rect};
use crate::framework::error::GameResult;
use crate::npc::list::NPCList;
use crate::npc::NPC;
use crate::player::{Player, TargetPlayer};
use crate::rng::RNG;
use crate::shared_game_state::SharedGameState;
use crate::weapon::bullet::BulletManager;
use crate::game::caret::CaretType;
use crate::game::npc::list::NPCList;
use crate::game::npc::NPC;
use crate::game::player::{Player, TargetPlayer};
use crate::game::shared_game_state::SharedGameState;
use crate::game::weapon::bullet::BulletManager;
use crate::util::rng::RNG;
impl NPC {
pub(crate) fn tick_n002_behemoth(&mut self, state: &mut SharedGameState, npc_list: &NPCList) -> GameResult {

View File

@ -2,10 +2,10 @@ use num_traits::clamp;
use crate::common::Direction;
use crate::framework::error::GameResult;
use crate::npc::NPC;
use crate::player::Player;
use crate::rng::RNG;
use crate::shared_game_state::SharedGameState;
use crate::game::npc::NPC;
use crate::game::player::Player;
use crate::game::shared_game_state::SharedGameState;
use crate::util::rng::RNG;
impl NPC {
pub(crate) fn tick_n059_eye_door(&mut self, state: &mut SharedGameState, players: [&mut Player; 2]) -> GameResult {

View File

@ -1,13 +1,13 @@
use num_traits::abs;
use num_traits::clamp;
use crate::caret::CaretType;
use crate::common::{Direction, Rect};
use crate::framework::error::GameResult;
use crate::npc::{NPCList, NPC};
use crate::player::Player;
use crate::rng::RNG;
use crate::shared_game_state::SharedGameState;
use crate::game::caret::CaretType;
use crate::game::npc::{NPC, NPCList};
use crate::game::player::Player;
use crate::game::shared_game_state::SharedGameState;
use crate::util::rng::RNG;
impl NPC {
pub(crate) fn tick_n024_power_critter(
@ -834,7 +834,7 @@ impl NPC {
&& self.action_num != 3
&& self.action_counter > 10
&& ((self.shock > 0)
|| (abs(self.x - player.x) < 0x14000 && abs(self.y - player.y) < 0x8000) && self.rng.range(0..50) == 2)
|| (abs(self.x - player.x) < 0x14000 && abs(self.y - player.y) < 0x8000) && self.rng.range(0..50) == 2)
{
self.direction = if self.x >= player.x { Direction::Left } else { Direction::Right };
self.action_num = 10;
@ -1176,7 +1176,7 @@ impl NPC {
&& self.action_num != 3
&& self.action_counter > 10
&& ((self.shock > 0)
|| (abs(self.x - player.x) < 0x14000 && abs(self.y - player.y) < 0x8000) && self.rng.range(0..50) == 2)
|| (abs(self.x - player.x) < 0x14000 && abs(self.y - player.y) < 0x8000) && self.rng.range(0..50) == 2)
{
self.direction = if self.x >= player.x { Direction::Left } else { Direction::Right };
self.action_num = 10;
@ -1219,9 +1219,9 @@ impl NPC {
let player = self.get_closest_player_mut(players);
if self.shock != 0
|| (player.x < self.x + 0xc000
&& player.x > self.x - 0xc000
&& player.y < self.y + 0x4000
&& player.y > self.y - 0xc000)
&& player.x > self.x - 0xc000
&& player.y < self.y + 0x4000
&& player.y > self.y - 0xc000)
{
self.action_num = 10;
}

View File

@ -1,11 +1,12 @@
use crate::caret::CaretType;
use crate::common::Direction;
use crate::npc::list::NPCList;
use crate::npc::NPC;
use crate::player::Player;
use crate::rng::RNG;
use crate::stage::Stage;
use crate::{GameResult, SharedGameState};
use crate::framework::error::GameResult;
use crate::game::caret::CaretType;
use crate::game::npc::list::NPCList;
use crate::game::npc::NPC;
use crate::game::player::Player;
use crate::game::shared_game_state::SharedGameState;
use crate::game::stage::Stage;
use crate::util::rng::RNG;
impl NPC {
pub(crate) fn tick_n337_numahachi(&mut self, state: &mut SharedGameState) -> GameResult {
@ -264,7 +265,7 @@ impl NPC {
if (player.y > self.y - 0x14000 && player.y < self.y + 0x14000)
&& ((self.direction == Direction::Left && player.x > self.x - 0x28000 && player.x < self.x)
|| (self.direction != Direction::Left && player.x > self.x && player.x < self.x + 0x28000))
|| (self.direction != Direction::Left && player.x > self.x && player.x < self.x + 0x28000))
{
self.action_num = 10;
}
@ -511,9 +512,9 @@ impl NPC {
let player = self.get_closest_player_ref(&players);
if self.action_counter > 20
&& ((self.direction == Direction::Left && self.x <= player.x + 0x4000)
|| (self.direction == Direction::Up && self.y <= player.y + 0x4000)
|| (self.direction == Direction::Right && self.x <= player.x - 0x4000)
|| (self.direction == Direction::Bottom && self.y <= player.y - 0x4000))
|| (self.direction == Direction::Up && self.y <= player.y + 0x4000)
|| (self.direction == Direction::Right && self.x <= player.x - 0x4000)
|| (self.direction == Direction::Bottom && self.y <= player.y - 0x4000))
{
self.action_num = 10
}

View File

@ -1,10 +1,10 @@
use crate::common::{Direction, CDEG_RAD};
use crate::common::{CDEG_RAD, Direction};
use crate::framework::error::GameResult;
use crate::npc::list::NPCList;
use crate::npc::NPC;
use crate::player::Player;
use crate::rng::RNG;
use crate::shared_game_state::SharedGameState;
use crate::game::npc::list::NPCList;
use crate::game::npc::NPC;
use crate::game::player::Player;
use crate::game::shared_game_state::SharedGameState;
use crate::util::rng::RNG;
impl NPC {
pub(crate) fn tick_n083_igor_cutscene(&mut self, state: &mut SharedGameState) -> GameResult {

View File

@ -1,10 +1,9 @@
use crate::framework::error::GameResult;
use crate::caret::CaretType;
use crate::common::Direction;
use crate::npc::NPC;
use crate::rng::RNG;
use crate::shared_game_state::SharedGameState;
use crate::framework::error::GameResult;
use crate::game::caret::CaretType;
use crate::game::npc::NPC;
use crate::game::shared_game_state::SharedGameState;
use crate::util::rng::RNG;
impl NPC {
pub(crate) fn tick_n298_intro_doctor(&mut self, state: &mut SharedGameState) -> GameResult {

View File

@ -1,11 +1,11 @@
use crate::caret::CaretType;
use crate::common::Direction;
use crate::framework::error::GameResult;
use crate::npc::list::NPCList;
use crate::npc::NPC;
use crate::player::Player;
use crate::rng::RNG;
use crate::shared_game_state::SharedGameState;
use crate::game::caret::CaretType;
use crate::game::npc::list::NPCList;
use crate::game::npc::NPC;
use crate::game::player::Player;
use crate::game::shared_game_state::SharedGameState;
use crate::util::rng::RNG;
impl NPC {
pub(crate) fn tick_n241_critter_red(

View File

@ -1,11 +1,11 @@
use crate::caret::CaretType;
use crate::common::{Direction, CDEG_RAD};
use crate::common::{CDEG_RAD, Direction};
use crate::framework::error::GameResult;
use crate::npc::list::NPCList;
use crate::npc::NPC;
use crate::player::Player;
use crate::rng::RNG;
use crate::shared_game_state::SharedGameState;
use crate::game::caret::CaretType;
use crate::game::npc::list::NPCList;
use crate::game::npc::NPC;
use crate::game::player::Player;
use crate::game::shared_game_state::SharedGameState;
use crate::util::rng::RNG;
impl NPC {
pub(crate) fn tick_n147_critter_purple(

View File

@ -4,13 +4,13 @@ use num_traits::{abs, clamp};
use crate::common::Direction;
use crate::framework::error::GameResult;
use crate::npc::list::NPCList;
use crate::npc::NPC;
use crate::player::{Player, TargetPlayer};
use crate::rng::RNG;
use crate::shared_game_state::SharedGameState;
use crate::stage::Stage;
use crate::weapon::bullet::BulletManager;
use crate::game::npc::list::NPCList;
use crate::game::npc::NPC;
use crate::game::player::{Player, TargetPlayer};
use crate::game::shared_game_state::SharedGameState;
use crate::game::stage::Stage;
use crate::game::weapon::bullet::BulletManager;
use crate::util::rng::RNG;
impl NPC {
pub(crate) fn tick_n069_pignon(&mut self, state: &mut SharedGameState) -> GameResult {

View File

@ -1,16 +1,16 @@
use std::hint::unreachable_unchecked;
use crate::caret::CaretType;
use crate::common::{Direction, Rect};
use crate::components::flash::Flash;
use crate::framework::error::GameResult;
use crate::npc::boss::BossNPC;
use crate::npc::list::NPCList;
use crate::npc::{NPCLayer, NPC};
use crate::player::Player;
use crate::rng::RNG;
use crate::shared_game_state::{GameDifficulty, SharedGameState};
use crate::stage::Stage;
use crate::game::caret::CaretType;
use crate::game::npc::{NPC, NPCLayer};
use crate::game::npc::boss::BossNPC;
use crate::game::npc::list::NPCList;
use crate::game::player::Player;
use crate::game::shared_game_state::{GameDifficulty, SharedGameState};
use crate::game::stage::Stage;
use crate::util::rng::RNG;
impl NPC {
pub(crate) fn tick_n000_null(&mut self) -> GameResult {
@ -624,9 +624,9 @@ impl NPC {
self.action_counter += 1;
if self.action_counter > 10
&& (self.flags.hit_left_wall()
|| self.flags.hit_right_wall()
|| self.flags.hit_bottom_wall()
|| self.flags.in_water())
|| self.flags.hit_right_wall()
|| self.flags.hit_bottom_wall()
|| self.flags.in_water())
{
// hit something
self.cond.set_alive(false);
@ -2180,11 +2180,11 @@ impl NPC {
npc.cond.set_alive(true);
npc.x = self.x
+ if player.equip.has_booster_2_0() {
self.rng.range(-14..14)
} else {
self.rng.range(-11..11)
} * state.tile_size.as_int()
* 0x200;
self.rng.range(-14..14)
} else {
self.rng.range(-11..11)
} * state.tile_size.as_int()
* 0x200;
npc.y = player.y - 0x1C000;
npc.direction = if self.rng.range(0..10) & 1 != 0 { Direction::Left } else { Direction::Right };

View File

@ -2,17 +2,17 @@ use std::hint::unreachable_unchecked;
use num_traits::clamp;
use crate::caret::CaretType;
use crate::common::{Direction, CDEG_RAD};
use crate::common::{CDEG_RAD, Direction};
use crate::components::flash::Flash;
use crate::framework::error::GameResult;
use crate::npc::boss::BossNPC;
use crate::npc::list::NPCList;
use crate::npc::NPC;
use crate::player::Player;
use crate::rng::RNG;
use crate::shared_game_state::SharedGameState;
use crate::stage::Stage;
use crate::game::caret::CaretType;
use crate::game::npc::boss::BossNPC;
use crate::game::npc::list::NPCList;
use crate::game::npc::NPC;
use crate::game::player::Player;
use crate::game::shared_game_state::SharedGameState;
use crate::game::stage::Stage;
use crate::util::rng::RNG;
impl NPC {
pub(crate) fn tick_n066_misery_bubble(&mut self, state: &mut SharedGameState, npc_list: &NPCList) -> GameResult {
@ -845,10 +845,10 @@ impl NPC {
if let Some(parent) = self.get_parent_ref_mut(npc_list) {
self.x = parent.x
+ self.action_counter as i32 * ((self.action_counter2 as f64 * CDEG_RAD).cos() * -512.0) as i32
/ 4;
/ 4;
self.y = parent.y
+ self.action_counter as i32 * ((self.action_counter2 as f64 * CDEG_RAD).sin() * -512.0) as i32
/ 4;
/ 4;
if parent.action_num == 151 {
self.action_num = 10;

28
src/game/npc/ai/mod.rs Normal file
View File

@ -0,0 +1,28 @@
pub(crate) mod balcony;
pub(crate) mod balrog;
pub(crate) mod booster;
pub(crate) mod chaco;
pub(crate) mod characters;
pub(crate) mod curly;
pub(crate) mod doctor;
pub(crate) mod egg_corridor;
pub(crate) mod first_cave;
pub(crate) mod grasstown;
pub(crate) mod hell;
pub(crate) mod igor;
pub(crate) mod intro;
pub(crate) mod last_cave;
pub(crate) mod maze;
pub(crate) mod mimiga_village;
pub(crate) mod misc;
pub(crate) mod misery;
pub(crate) mod outer_wall;
pub(crate) mod pickups;
pub(crate) mod plantation;
pub(crate) mod quote;
pub(crate) mod sand_zone;
pub(crate) mod santa;
pub(crate) mod sue;
pub(crate) mod toroko;
pub(crate) mod weapon_trail;
pub(crate) mod wind_fortress;

View File

@ -2,11 +2,11 @@ use num_traits::abs;
use crate::common::Direction;
use crate::framework::error::GameResult;
use crate::npc::list::NPCList;
use crate::npc::NPC;
use crate::player::Player;
use crate::rng::RNG;
use crate::shared_game_state::SharedGameState;
use crate::game::npc::list::NPCList;
use crate::game::npc::NPC;
use crate::game::player::Player;
use crate::game::shared_game_state::SharedGameState;
use crate::util::rng::RNG;
impl NPC {
pub(crate) fn tick_n212_sky_dragon(

View File

@ -1,9 +1,9 @@
use crate::common::Direction;
use crate::framework::error::GameResult;
use crate::npc::NPC;
use crate::rng::RNG;
use crate::shared_game_state::SharedGameState;
use crate::stage::{Stage, BackgroundType};
use crate::game::npc::NPC;
use crate::game::shared_game_state::SharedGameState;
use crate::game::stage::{BackgroundType, Stage};
use crate::util::rng::RNG;
impl NPC {
pub(crate) fn tick_n001_experience(&mut self, state: &mut SharedGameState, stage: &mut Stage) -> GameResult {

View File

@ -1,11 +1,11 @@
use crate::caret::CaretType;
use crate::common::{Direction, CDEG_RAD};
use crate::common::{CDEG_RAD, Direction};
use crate::framework::error::GameResult;
use crate::npc::list::NPCList;
use crate::npc::NPC;
use crate::player::Player;
use crate::rng::RNG;
use crate::shared_game_state::SharedGameState;
use crate::game::caret::CaretType;
use crate::game::npc::list::NPCList;
use crate::game::npc::NPC;
use crate::game::player::Player;
use crate::game::shared_game_state::SharedGameState;
use crate::util::rng::RNG;
impl NPC {
pub(crate) fn tick_n220_shovel_brigade(&mut self, state: &mut SharedGameState) -> GameResult {

View File

@ -1,11 +1,10 @@
use crate::framework::error::GameResult;
use crate::common::Direction;
use crate::npc::list::NPCList;
use crate::npc::NPC;
use crate::player::Player;
use crate::rng::RNG;
use crate::shared_game_state::SharedGameState;
use crate::framework::error::GameResult;
use crate::game::npc::list::NPCList;
use crate::game::npc::NPC;
use crate::game::player::Player;
use crate::game::shared_game_state::SharedGameState;
use crate::util::rng::RNG;
impl NPC {
pub fn tick_n111_quote_teleport_out(

View File

@ -1,14 +1,14 @@
use num_traits::{abs, clamp};
use crate::caret::CaretType;
use crate::common::{Direction, CDEG_RAD};
use crate::common::{CDEG_RAD, Direction};
use crate::framework::error::GameResult;
use crate::npc::list::NPCList;
use crate::npc::NPC;
use crate::player::Player;
use crate::rng::RNG;
use crate::shared_game_state::SharedGameState;
use crate::weapon::bullet::BulletManager;
use crate::game::caret::CaretType;
use crate::game::npc::list::NPCList;
use crate::game::npc::NPC;
use crate::game::player::Player;
use crate::game::shared_game_state::SharedGameState;
use crate::game::weapon::bullet::BulletManager;
use crate::util::rng::RNG;
impl NPC {
pub(crate) fn tick_n044_polish(&mut self, state: &mut SharedGameState, npc_list: &NPCList) -> GameResult {

View File

@ -2,10 +2,10 @@ use num_traits::abs;
use crate::common::Direction;
use crate::framework::error::GameResult;
use crate::npc::NPC;
use crate::player::Player;
use crate::rng::RNG;
use crate::shared_game_state::SharedGameState;
use crate::game::npc::NPC;
use crate::game::player::Player;
use crate::game::shared_game_state::SharedGameState;
use crate::util::rng::RNG;
impl NPC {
pub(crate) fn tick_n040_santa(&mut self, state: &mut SharedGameState, players: [&mut Player; 2]) -> GameResult {

View File

@ -1,12 +1,12 @@
use crate::common::Direction;
use crate::framework::error::GameResult;
use crate::npc::boss::BossNPC;
use crate::npc::list::NPCList;
use crate::npc::NPC;
use crate::player::Player;
use crate::rng::RNG;
use crate::shared_game_state::SharedGameState;
use crate::stage::Stage;
use crate::game::npc::boss::BossNPC;
use crate::game::npc::list::NPCList;
use crate::game::npc::NPC;
use crate::game::player::Player;
use crate::game::shared_game_state::SharedGameState;
use crate::game::stage::Stage;
use crate::util::rng::RNG;
impl NPC {
pub fn tick_n042_sue(

View File

@ -1,12 +1,12 @@
use crate::caret::CaretType;
use crate::common::Direction;
use crate::framework::error::GameResult;
use crate::npc::list::NPCList;
use crate::npc::NPC;
use crate::player::Player;
use crate::rng::RNG;
use crate::shared_game_state::SharedGameState;
use crate::weapon::bullet::BulletManager;
use crate::game::caret::CaretType;
use crate::game::npc::list::NPCList;
use crate::game::npc::NPC;
use crate::game::player::Player;
use crate::game::shared_game_state::SharedGameState;
use crate::game::weapon::bullet::BulletManager;
use crate::util::rng::RNG;
impl NPC {
pub(crate) fn tick_n060_toroko(&mut self, state: &mut SharedGameState, players: [&mut Player; 2]) -> GameResult {

View File

@ -1,11 +1,10 @@
use crate::framework::error::GameResult;
use crate::npc::NPC;
use crate::shared_game_state::SharedGameState;
use crate::common::Direction;
use crate::framework::error::GameResult;
use crate::game::npc::NPC;
use crate::game::shared_game_state::SharedGameState;
impl NPC {
pub(crate) fn tick_n127_machine_gun_trail_l2(&mut self, state: &mut SharedGameState ) -> GameResult {
pub(crate) fn tick_n127_machine_gun_trail_l2(&mut self, state: &mut SharedGameState) -> GameResult {
self.anim_counter += 1;
if self.anim_counter > 0 {
self.anim_counter = 0;
@ -30,7 +29,7 @@ impl NPC {
Ok(())
}
pub(crate) fn tick_n128_machine_gun_trail_l3(&mut self, state: &mut SharedGameState ) -> GameResult {
pub(crate) fn tick_n128_machine_gun_trail_l3(&mut self, state: &mut SharedGameState) -> GameResult {
self.anim_counter += 1;
if self.anim_counter > 0 {
self.anim_counter = 0;

View File

@ -1,11 +1,11 @@
use crate::caret::CaretType;
use crate::common::{Direction, CDEG_RAD};
use crate::common::{CDEG_RAD, Direction};
use crate::framework::error::GameResult;
use crate::npc::list::NPCList;
use crate::npc::NPC;
use crate::player::Player;
use crate::rng::RNG;
use crate::shared_game_state::SharedGameState;
use crate::game::caret::CaretType;
use crate::game::npc::list::NPCList;
use crate::game::npc::NPC;
use crate::game::player::Player;
use crate::game::shared_game_state::SharedGameState;
use crate::util::rng::RNG;
impl NPC {
// Gaudi from room 2

View File

@ -1,13 +1,12 @@
use crate::common::{CDEG_RAD, Direction, Rect};
use crate::framework::error::GameResult;
use crate::caret::CaretType;
use crate::common::{Direction, Rect, CDEG_RAD};
use crate::npc::boss::BossNPC;
use crate::npc::list::NPCList;
use crate::npc::NPC;
use crate::player::Player;
use crate::rng::RNG;
use crate::shared_game_state::SharedGameState;
use crate::game::caret::CaretType;
use crate::game::npc::boss::BossNPC;
use crate::game::npc::list::NPCList;
use crate::game::npc::NPC;
use crate::game::player::Player;
use crate::game::shared_game_state::SharedGameState;
use crate::util::rng::RNG;
impl NPC {
pub(crate) fn tick_n108_balfrog_projectile(&mut self, state: &mut SharedGameState) -> GameResult {

View File

@ -1,14 +1,14 @@
use crate::caret::CaretType;
use crate::common::{Direction, Rect, CDEG_RAD};
use crate::common::{CDEG_RAD, Direction, Rect};
use crate::components::flash::Flash;
use crate::framework::error::GameResult;
use crate::npc::boss::BossNPC;
use crate::npc::list::NPCList;
use crate::npc::NPC;
use crate::player::Player;
use crate::rng::RNG;
use crate::shared_game_state::SharedGameState;
use crate::stage::Stage;
use crate::game::caret::CaretType;
use crate::game::npc::boss::BossNPC;
use crate::game::npc::list::NPCList;
use crate::game::npc::NPC;
use crate::game::player::Player;
use crate::game::shared_game_state::SharedGameState;
use crate::game::stage::Stage;
use crate::util::rng::RNG;
impl NPC {
pub(crate) fn tick_n331_ballos_bone_projectile(&mut self, state: &mut SharedGameState) -> GameResult {

View File

@ -1,13 +1,13 @@
use crate::caret::CaretType;
use crate::common::{Direction, CDEG_RAD};
use crate::common::{CDEG_RAD, Direction};
use crate::framework::error::GameResult;
use crate::npc::boss::BossNPC;
use crate::npc::list::NPCList;
use crate::npc::NPC;
use crate::player::Player;
use crate::rng::RNG;
use crate::shared_game_state::SharedGameState;
use crate::stage::Stage;
use crate::game::caret::CaretType;
use crate::game::npc::boss::BossNPC;
use crate::game::npc::list::NPCList;
use crate::game::npc::NPC;
use crate::game::player::Player;
use crate::game::shared_game_state::SharedGameState;
use crate::game::stage::Stage;
use crate::util::rng::RNG;
impl NPC {
pub(crate) fn tick_n178_core_blade_projectile(&mut self, state: &mut SharedGameState) -> GameResult {
@ -93,7 +93,7 @@ impl BossNPC {
let mut flag = false;
// i will refactor that one day
#[allow(mutable_transmutes)]
let flash_counter: &mut u16 = unsafe { std::mem::transmute(&self.parts[19].action_counter3) };
let flash_counter: &mut u16 = unsafe { std::mem::transmute(&self.parts[19].action_counter3) };
match self.parts[0].action_num {
0 => {

View File

@ -1,11 +1,11 @@
use crate::common::{Direction, Rect};
use crate::framework::error::GameResult;
use crate::npc::boss::BossNPC;
use crate::npc::list::NPCList;
use crate::npc::NPC;
use crate::rng::RNG;
use crate::shared_game_state::SharedGameState;
use crate::stage::Stage;
use crate::game::npc::boss::BossNPC;
use crate::game::npc::list::NPCList;
use crate::game::npc::NPC;
use crate::game::shared_game_state::SharedGameState;
use crate::game::stage::Stage;
use crate::util::rng::RNG;
impl NPC {
pub(crate) fn tick_n325_heavy_press_lightning(

View File

@ -1,11 +1,11 @@
use crate::common::{Direction, Rect};
use crate::framework::error::GameResult;
use crate::npc::boss::BossNPC;
use crate::npc::list::NPCList;
use crate::npc::NPC;
use crate::player::Player;
use crate::rng::RNG;
use crate::shared_game_state::SharedGameState;
use crate::game::npc::boss::BossNPC;
use crate::game::npc::list::NPCList;
use crate::game::npc::NPC;
use crate::game::player::Player;
use crate::game::shared_game_state::SharedGameState;
use crate::util::rng::RNG;
impl NPC {
pub(crate) fn tick_n196_ironhead_wall(&mut self, state: &mut SharedGameState) -> GameResult {

View File

@ -1,18 +1,18 @@
use std::mem::{transmute, MaybeUninit};
use std::mem::{MaybeUninit, transmute};
use std::ops::Deref;
use crate::common::{interpolate_fix9_scale, Direction};
use crate::common::{Direction, interpolate_fix9_scale};
use crate::components::flash::Flash;
use crate::entity::GameEntity;
use crate::frame::Frame;
use crate::framework::context::Context;
use crate::framework::error::GameResult;
use crate::npc::list::NPCList;
use crate::npc::NPC;
use crate::player::Player;
use crate::shared_game_state::SharedGameState;
use crate::stage::Stage;
use crate::weapon::bullet::BulletManager;
use crate::game::frame::Frame;
use crate::game::npc::list::NPCList;
use crate::game::npc::NPC;
use crate::game::player::Player;
use crate::game::shared_game_state::SharedGameState;
use crate::game::stage::Stage;
use crate::game::weapon::bullet::BulletManager;
pub mod balfrog;
pub mod ballos;

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