+12
-1
README.md
+12
-1
README.md
···
25
25
- renaming `steam_id_remote` dictionnary key to `remote_steam_id` to fix network spam detection that resulted in timeouts
26
26
- prevent the game from crashing when saving the options by not setting any values to `OS.windowed_borderless` because setting a value to it crashes the game somehow
27
27
28
+
29
+
## How to install a mod?
30
+
31
+
When running the software for the first time and building webfishing, you'll notice that a `mods` folder has appeared in the folder where the installer is.
32
+
33
+
In order to install a mod, just copy a mod folder in it, a mod folder has a `manifest.json` file in it.
34
+
35
+
After that, run the installer again ! It will tell you in the terminal if the mod is installed or if something went wrong.
36
+
37
+
Here's a small mod list : [link to the mod list](modlist.md)
38
+
28
39
## How to make a mod?
29
40
30
41
As you can see in the `example_mods` folder, a mod has typically two folders and a single `manifest.json` file having the following structure:
31
-
```json
42
+
```jsonc
32
43
{
33
44
"name": "Ship Mod", // Mod name
34
45
"author": "Estym", // Author
+20
-29
example_mods/ship/patch/player.patch
+20
-29
example_mods/ship/patch/player.patch
···
1
-
diff --git a/webfishing/Scenes/Entities/Player/player.gd b/Users/evann/Godot/Webfishing/Scenes/Entities/Player/player.gd
2
-
index 3879ff8..cc20048 100644
3
-
--- a/webfishing/Scenes/Entities/Player/player.gd
4
-
+++ b/Users/evann/Godot/Webfishing/Scenes/Entities/Player/player.gd
5
-
@@ -30,6 +30,7 @@ export var NPC_cosmetics = {"species": "species_cat", "pattern": "pattern_none"
1
+
diff --git a/player.gd b/player copie.gd
2
+
index c84af29..4cb41f9 100644
3
+
--- a/player.gd
4
+
+++ b/player copie.gd
5
+
@@ -23,6 +23,7 @@ const PARTICLE_DATA = {
6
+
"music": preload("res://Scenes/Particles/music_particle.tscn"),
7
+
"kiss": preload("res://Scenes/Particles/kiss.tscn"),
8
+
}
9
+
+var ship_mod_instance = preload("res://Mods/Ship/ship.gd").new()
10
+
11
+
export (NodePath) var hand_sprite_node
12
+
export (NodePath) var hand_bone_node
13
+
@@ -31,6 +32,7 @@ export var NPC_cosmetics = {"species": "species_cat", "pattern": "pattern_none"
6
14
export var NPC_name = "NPC Test"
7
15
export var NPC_title = "npc title here"
8
16
9
-
+var ship_mod_instance = preload("res://Mods/Ship/ship.gd").new()
17
+
+
10
18
var camera_zoom = 5.0
11
19
12
20
var direction = Vector3()
13
-
@@ -341,6 +342,7 @@ func _process(delta):
14
-
15
-
func _controlled_process(delta):
16
-
_get_input()
17
-
+
18
-
_process_movement(delta)
19
-
_process_timers()
20
-
_interact_check()
21
-
@@ -480,7 +482,7 @@ func _process_timers():
22
-
23
-
func _get_input():
24
-
direction = Vector3.ZERO
25
-
-
26
-
+
27
-
if Input.is_action_just_released("primary_action"): _primary_action_release()
28
-
if Input.is_action_pressed("primary_action"): _primary_action_hold()
29
-
else: primary_hold_timer = 0
30
-
@@ -538,8 +540,10 @@ func _get_input():
21
+
@@ -531,6 +533,10 @@ func _get_input():
31
22
32
23
mouse_look = false
33
24
34
25
+ if ship_mod_instance.is_sitting_on_ship(self):
35
26
+ ship_mod_instance.process_ship(self, get_world())
36
27
+ return
28
+
+
37
29
if sitting: return
38
-
-
30
+
39
31
if Input.is_action_pressed("move_forward"): direction -= cam_base.transform.basis.z
40
-
if Input.is_action_pressed("move_back"): direction += cam_base.transform.basis.z
41
-
if Input.is_action_pressed("move_right"): direction += cam_base.transform.basis.x
42
-
@@ -1405,16 +1409,6 @@ func _create_prop(ref, offset = Vector3(0, 1, 0), restrict_to_one = false):
32
+
@@ -1389,17 +1395,6 @@ func _create_prop(ref, offset = Vector3(0, 1, 0), restrict_to_one = false):
33
+
PlayerData.emit_signal("_prop_update")
43
34
return false
44
35
45
-
36
+
-
46
37
- if $detection_zones / prop_detect.get_overlapping_bodies().size() > 0 or not is_on_floor() or not $detection_zones / prop_ray.is_colliding():
47
38
- PlayerData._send_notification("invalid prop placement", 1)
48
39
- return false
+7
modlist.md
+7
modlist.md
+140
-66
src/main.rs
+140
-66
src/main.rs
···
1
-
mod utils;
2
-
mod patches;
3
1
mod mods;
2
+
mod patches;
3
+
mod utils;
4
4
5
+
use asky::Text;
6
+
use async_std::fs::create_dir;
7
+
use godot_pck::structs::PCK;
5
8
use std::env::{current_exe, set_current_dir};
6
9
use std::fs::File;
7
10
use std::io::{Read, Write};
8
11
use std::path::Path;
9
-
use std::process::Command;
12
+
use std::process::{exit, Command};
10
13
use std::time::Duration;
11
-
use asky::Text;
12
-
use async_std::fs::create_dir;
13
14
use steamlocate::SteamDir;
14
15
use sudo::RunningAs;
15
16
use sysinfo::ProcessesToUpdate;
16
-
use godot_pck::structs::PCK;
17
17
18
18
static WEBFISHING_APPID: u32 = 3146520;
19
19
20
20
async fn install_webfishing(location: &SteamDir) {
21
21
let steam_location = location.path();
22
-
let acf_path = steam_location.join("steamapps").join(format!("appmanifest_{}.acf", WEBFISHING_APPID));
22
+
let acf_path = steam_location
23
+
.join("steamapps")
24
+
.join(format!("appmanifest_{}.acf", WEBFISHING_APPID));
23
25
24
26
println!("Creating Webfishing ACF");
25
-
File::create(acf_path).unwrap().write(include_str!("../res/webfishing.acf").as_bytes()).expect("could not write acf");
27
+
File::create(acf_path)
28
+
.unwrap()
29
+
.write(include_str!("../res/webfishing.acf").as_bytes())
30
+
.expect("could not write acf");
26
31
27
32
println!("Waiting for steam to close");
28
33
let mut system = sysinfo::System::new_all();
···
40
45
}
41
46
42
47
println!("Steam launched, downloading webfishing");
43
-
let download_path = steam_location.join("steamapps").join("downloading").join(format!("{}", WEBFISHING_APPID));
48
+
let download_path = steam_location
49
+
.join("steamapps")
50
+
.join("downloading")
51
+
.join(format!("{}", WEBFISHING_APPID));
44
52
45
53
while Path::exists(download_path.as_path()) {
46
54
println!("Downloading webfishing...");
···
50
58
51
59
async fn download_godot_steam_template() {
52
60
println!("Downloading GodotSteam template...");
53
-
let res = reqwest::get("https://github.com/GodotSteam/GodotSteam/releases/download/v3.27/macos-g36-s160-gs327.zip").await.expect("Could not download godotsteam template");
61
+
let res = reqwest::get(
62
+
"https://codeberg.org/godotsteam/godotsteam/releases/download/v3.24/macos-g353-s159-gs324.zip",
63
+
)
64
+
.await
65
+
.expect("Could not download godotsteam template");
54
66
let body = res.bytes().await.expect("Could not read body");
55
67
56
-
let mut file = File::create("build/godot_steam_template.zip").expect("Could not create godotsteam template");
57
-
file.write_all(&body).expect("Could not write godotsteam template");
68
+
let mut file = File::create("build/godot_steam_template_324.zip")
69
+
.expect("Could not create godotsteam template");
70
+
file.write_all(&body)
71
+
.expect("Could not write godotsteam template");
58
72
}
59
73
60
74
async fn download_gd_decomp() {
···
69
83
Command::new("unzip")
70
84
.arg("decompiler.zip")
71
85
.current_dir("build")
72
-
.output().expect("Could not unzip godotsteam template");
86
+
.output()
87
+
.expect("Could not unzip godotsteam template");
73
88
}
74
89
75
90
fn build_webfishing_macos(webfishing_path: &Path) {
76
91
let template_path = Path::new("build/osx_template.app");
92
+
77
93
Command::new("rm")
78
94
.current_dir(template_path)
79
-
.arg("Contents/MacOS/godot_osx_debug.64")
80
-
.output().expect("Could not remove delete godot_osx_debug.64");
95
+
.arg("Contents/MacOS/godot_osx_debug.universal")
96
+
.output()
97
+
.expect("Could not remove delete godot_osx_debug.universal");
81
98
82
99
Command::new("mv")
83
100
.current_dir(template_path)
84
-
.arg("Contents/MacOS/godot_osx_release.64")
101
+
.arg("Contents/MacOS/godot_osx_release.universal")
85
102
.arg("Contents/MacOS/webfishing")
86
-
.output().expect("Could not rename godot_osc_release.64");
103
+
.output()
104
+
.expect("Could not rename godot_osc_release.universal");
87
105
88
-
let mut steamappid = File::create(template_path.join("Contents").join("MacOS").join("steam_appid.txt")).expect("could not create steam_appid.txt file");
89
-
steamappid.write(include_str!("../res/steam_appid.txt").as_bytes()).expect("could not write steam_appid.txt");
106
+
let mut steamappid = File::create(
107
+
template_path
108
+
.join("Contents")
109
+
.join("MacOS")
110
+
.join("steam_appid.txt"),
111
+
)
112
+
.expect("could not create steam_appid.txt file");
113
+
steamappid
114
+
.write(include_str!("../res/steam_appid.txt").as_bytes())
115
+
.expect("could not write steam_appid.txt");
90
116
91
117
Command::new("cp")
92
118
.arg(webfishing_path.join("webfishing.exe"))
93
-
.arg(template_path.join("Contents").join("Resources").join("webfishing.pck"))
94
-
.output().expect("Could not copy webfishing.exe");
119
+
.arg(
120
+
template_path
121
+
.join("Contents")
122
+
.join("Resources")
123
+
.join("webfishing.pck"),
124
+
)
125
+
.output()
126
+
.expect("Could not copy webfishing.exe");
95
127
96
-
let mut info_plist = File::create(template_path.join("Contents").join("Info.plist")).expect("Could not open Info.plist");
97
-
info_plist.write_all(include_str!("../res/Info.plist").as_bytes()).expect("could not write Info.plist");
128
+
let mut info_plist = File::create(template_path.join("Contents").join("Info.plist"))
129
+
.expect("Could not open Info.plist");
130
+
info_plist
131
+
.write_all(include_str!("../res/Info.plist").as_bytes())
132
+
.expect("could not write Info.plist");
98
133
99
134
Command::new("mv")
100
135
.arg(template_path)
101
136
.arg(Path::new("build/webfishing.app"))
102
-
.output().expect("Could not copy webfishing.app");
137
+
.output()
138
+
.expect("Could not copy webfishing.app");
139
+
}
140
+
141
+
fn sign_webfishing() {
142
+
Command::new("xattr")
143
+
.arg("-cr")
144
+
.arg("build/webfishing.app")
145
+
.output()
146
+
.expect("Could not execute xattr");
147
+
148
+
Command::new("rm")
149
+
.arg("build/signing-step")
150
+
.output()
151
+
.expect("Could not remove signing-step file");
152
+
153
+
println!("Webfishing is in the build folder !");
154
+
155
+
Text::new("Press Enter to quit")
156
+
.prompt()
157
+
.expect("Could not confirm to quit");
158
+
159
+
103
160
}
104
161
105
162
#[tokio::main]
106
163
async fn main() {
107
-
set_current_dir(current_exe().unwrap().parent().expect("Could not get current dir")).expect("Could not set current dir");
164
+
if sudo::check() == RunningAs::Root && Path::new("build/signing-step").exists() {
165
+
sign_webfishing();
166
+
exit(0);
167
+
}
168
+
169
+
set_current_dir(
170
+
current_exe()
171
+
.unwrap()
172
+
.parent()
173
+
.expect("Could not get current dir"),
174
+
)
175
+
.expect("Could not set current dir");
108
176
if !Path::exists("build".as_ref()) {
109
177
println!("Creating build folder");
110
-
create_dir("build").await.expect("could not create build folder");
178
+
create_dir("build")
179
+
.await
180
+
.expect("could not create build folder");
111
181
}
112
182
113
183
let location = SteamDir::locate().expect("could not locate steam directory");
···
118
188
install_webfishing(&location).await;
119
189
}
120
190
121
-
let (app, library) = location.find_app(WEBFISHING_APPID).unwrap().unwrap();
191
+
let (app, library) = location.find_app(WEBFISHING_APPID).unwrap().unwrap();
122
192
123
193
if !Path::exists("build/decompiler.zip".as_ref()) {
124
194
download_gd_decomp().await;
125
195
}
126
196
127
-
if !Path::exists("build/godot_steam_template.zip".as_ref()) {
197
+
if !Path::exists("build/godot_steam_template_324.zip".as_ref()) {
128
198
download_godot_steam_template().await;
129
199
}
130
200
131
-
if !Path::exists("build/macos.zip".as_ref()) {
132
-
println!("Unzipping template");
133
-
Command::new("unzip")
134
-
.arg("-o")
135
-
.arg("godot_steam_template.zip")
136
-
.current_dir("./build")
137
-
.output().expect("Could not unzip godot_steam_template.zip");
138
-
}
201
+
println!("Unzipping template 1/2");
202
+
Command::new("unzip")
203
+
.arg("-o")
204
+
.arg("godot_steam_template_324.zip")
205
+
.current_dir("./build")
206
+
.output()
207
+
.expect("Could not unzip godot_steam_template_324.zip");
139
208
140
-
if !Path::exists("build/osx_template.app".as_ref()) && !Path::exists("build/webfishing.app".as_ref()) {
141
-
println!("Unzipping template");
142
-
Command::new("unzip")
143
-
.arg("-o")
144
-
.arg("macos.zip")
145
-
.current_dir("./build")
146
-
.output()
147
-
.expect("Could not unzip macos.zip");
148
-
}
209
+
Command::new("mv")
210
+
.arg("build/godot_steam_template_324/macos.zip")
211
+
.arg("build/macos.zip")
212
+
.current_dir("./build")
213
+
.output()
214
+
.expect("Could not copy godot_steam_template_324/macos.zip");
149
215
216
+
println!("Unzipping template 2/2");
217
+
Command::new("unzip")
218
+
.arg("-o")
219
+
.arg("macos.zip")
220
+
.current_dir("./build")
221
+
.output()
222
+
.expect("Could not unzip macos.zip");
150
223
151
224
let binding = library.resolve_app_dir(&app);
152
225
let webfishing_path = binding.as_path();
···
154
227
build_webfishing_macos(webfishing_path);
155
228
}
156
229
157
-
if sudo::check()!= RunningAs::Root {
158
-
let _ = create_dir("build/webfishing-export").await;
159
-
let mut bytes = vec![];
160
-
File::open(webfishing_path.join("webfishing.exe")).unwrap().read_to_end(&mut bytes).unwrap();
161
-
let mut pck = PCK::from_bytes(&*bytes).unwrap();
230
+
let _ = create_dir("build/webfishing-export").await;
231
+
let mut bytes = vec![];
232
+
File::open(webfishing_path.join("webfishing.exe"))
233
+
.unwrap()
234
+
.read_to_end(&mut bytes)
235
+
.unwrap();
236
+
let mut pck = PCK::from_bytes(&*bytes).unwrap();
162
237
163
-
patches::steam_network_patch::patch(&mut pck).await;
164
-
patches::options_menu_patch::patch(&mut pck).await;
165
-
mods::mods::process_mods(&mut pck);
166
-
println!("Root permissions needed to sign webfishing");
238
+
patches::steam_network_patch::patch(&mut pck).await;
239
+
patches::options_menu_patch::patch(&mut pck).await;
240
+
mods::mods::process_mods(&mut pck);
167
241
168
-
let bytes = &pck.to_bytes();
169
-
File::create("build/webfishing.app/Contents/Resources/webfishing.pck").unwrap().write(bytes).expect("Could not write to webfishing.pck");
170
-
}
242
+
let bytes = &pck.to_bytes();
243
+
File::create("build/webfishing.app/Contents/Resources/webfishing.pck")
244
+
.unwrap()
245
+
.write(bytes)
246
+
.expect("Could not write to webfishing.pck");
171
247
172
-
sudo::escalate_if_needed().expect("Could not escalate to sign the app");
248
+
File::create("build/signing-step").expect("Could not create signing step file");
173
249
174
-
Command::new("xattr")
175
-
.arg("-cr")
176
-
.arg("build/webfishing.app")
177
-
.output()
178
-
.expect("Could not execute xattr");
179
-
180
-
println!("Webfishing is in the build folder !");
250
+
if sudo::check() != RunningAs::Root {
251
+
println!("In order to sign the app, you need to be root");
252
+
sudo::escalate_if_needed().expect("Could not escalate");
253
+
exit(1);
254
+
}
181
255
182
-
Text::new("Press Enter to quit").prompt().expect("Could not confirm to quit");
256
+
sign_webfishing();
183
257
}
+1
-1
src/patches/steam_network_patch.rs
+1
-1
src/patches/steam_network_patch.rs
···
24
24
script.read_to_string(&mut script_txt).await.expect("Cannot read script");
25
25
drop(script);
26
26
27
-
let patched_script = script_txt.replace("steam_id_remote", "remote_steam_id");
27
+
let patched_script = script_txt.replace(".LOBBY_COMPARISON_EQUAL_TO_GREATER_THAN", ".OBBY_COMPARISON_EQUAL_TO_GREATER_THAN");
28
28
let mut script = File::create(SCRIPT_PATH).await.expect("Cannot open script");
29
29
script.write_all(patched_script.as_bytes()).await.expect("Cannot write");
30
30
drop(script);