···2525- renaming `steam_id_remote` dictionnary key to `remote_steam_id` to fix network spam detection that resulted in timeouts
2626- 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
27272828+## How to make a mod?
2929+3030+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:
3131+```json
3232+{
3333+ "name": "Ship Mod", // Mod name
3434+ "author": "Estym", // Author
3535+3636+ "pck_info": { // (Optional)
3737+ "directory": "pck", // Relative folder path to where the mod resources are
3838+ "resource_prefix": "res://Mods/Ship/" // Resource path prefix for the mod resources
3939+ },
4040+4141+ "mod_patches": [ // Array of patches
4242+ {
4343+ "resource": "res://Scenes/Entities/Player/player.gdc", // Resource to patch
4444+ "patch_file": "patch/player.patch" // relative file path to the patch file
4545+ }
4646+ ],
4747+4848+ "deps": [] // Dependencies for the mod (Optional)
4949+}
5050+```
5151+5252+### Notes:
5353+- The patch files are made by using `$ git diff [original_file] [modded_file] > file.patch`
5454+2855## Credits
29563057[@vimaexd](https://github.com/vimaexd) for their blog post !
···11+diff --git a/webfishing/Scenes/Entities/Player/player.gd b/Users/evann/Godot/Webfishing/Scenes/Entities/Player/player.gd
22+index 3879ff8..cc20048 100644
33+--- a/webfishing/Scenes/Entities/Player/player.gd
44++++ b/Users/evann/Godot/Webfishing/Scenes/Entities/Player/player.gd
55+@@ -30,6 +30,7 @@ export var NPC_cosmetics = {"species": "species_cat", "pattern": "pattern_none"
66+ export var NPC_name = "NPC Test"
77+ export var NPC_title = "npc title here"
88+99++var ship_mod_instance = preload("res://Mods/Ship/ship.gd").new()
1010+ var camera_zoom = 5.0
1111+1212+ var direction = Vector3()
1313+@@ -341,6 +342,7 @@ func _process(delta):
1414+1515+ func _controlled_process(delta):
1616+ _get_input()
1717++
1818+ _process_movement(delta)
1919+ _process_timers()
2020+ _interact_check()
2121+@@ -480,7 +482,7 @@ func _process_timers():
2222+2323+ func _get_input():
2424+ direction = Vector3.ZERO
2525+-
2626++
2727+ if Input.is_action_just_released("primary_action"): _primary_action_release()
2828+ if Input.is_action_pressed("primary_action"): _primary_action_hold()
2929+ else: primary_hold_timer = 0
3030+@@ -538,8 +540,10 @@ func _get_input():
3131+3232+ mouse_look = false
3333+3434++ if ship_mod_instance.is_sitting_on_ship(self):
3535++ ship_mod_instance.process_ship(self, get_world())
3636++ return
3737+ if sitting: return
3838+-
3939+ if Input.is_action_pressed("move_forward"): direction -= cam_base.transform.basis.z
4040+ if Input.is_action_pressed("move_back"): direction += cam_base.transform.basis.z
4141+ if Input.is_action_pressed("move_right"): direction += cam_base.transform.basis.x
4242+@@ -1405,16 +1409,6 @@ func _create_prop(ref, offset = Vector3(0, 1, 0), restrict_to_one = false):
4343+ return false
4444+4545+4646+- if $detection_zones / prop_detect.get_overlapping_bodies().size() > 0 or not is_on_floor() or not $detection_zones / prop_ray.is_colliding():
4747+- PlayerData._send_notification("invalid prop placement", 1)
4848+- return false
4949+-
5050+-
5151+- if prop_ids.size() > 4:
5252+- PlayerData._send_notification("prop limit reached", 1)
5353+- return false
5454+-
5555+-
5656+ var item = PlayerData._find_item_code(ref)
5757+ var data = Globals.item_data[item["id"]]["file"]
5858+ var ver_offset = Vector3(0, 1.0, 0) * (1.0 - player_scale)
+42
example_mods/ship/pck/ship.gd
···11+extends Node
22+33+var ship
44+# Declare member variables here. Examples:
55+# var a = 2
66+# var b = "text"
77+var entity_node
88+99+# Called when the node enters the scene tree for the first time.
1010+func _ready():
1111+1212+ pass # Replace with function body.
1313+1414+func process_ship(player, world):
1515+ var entities = player.get_parent()
1616+ for i in entities.get_children():
1717+ if i.actor_type == "table":
1818+ if Input.is_key_pressed(KEY_SHIFT):
1919+ i.translation.y += 0.05
2020+ i.packet_cooldown = 0
2121+ i._network_share()
2222+ elif Input.is_key_pressed(KEY_CONTROL):
2323+ i.translation.y -= 0.05
2424+ i.packet_cooldown = 0
2525+ i._network_share()
2626+2727+2828+func get_prop_by_ref(ref):
2929+ for obj in PlayerData.inventory:
3030+ if obj.ref == ref:
3131+ return obj
3232+ return null
3333+3434+func is_sitting_on_ship(player):
3535+3636+ for prop in PlayerData.props_placed:
3737+ var obj = get_prop_by_ref(prop.ref)
3838+ if obj != null && obj.id == 'prop_table':
3939+ ship = obj
4040+ return player.sitting
4141+ return false;
4242+