Compare commits

..

No commits in common. "master" and "0.4" have entirely different histories.
master ... 0.4

9 changed files with 1257 additions and 727 deletions

View File

@ -24,34 +24,3 @@ initial release
- bbcode enabled globally
- intrusive bbcode separated
- custom name bbcode
0.5
----
- update to webfishing 1.09
- bbcode stuff only to lucystools users
- intrusive bbcode now client toggle
- lots of stuff removed due to 1.09 having it already!
- panel stays closed if closed, open if open
0.5.1
----
- Lure 4.1.0 compatibility
- log fixes
- spawn fixes
0.6.0
----
- custom text color (bbcode qol)
- experimental color bug bbcode
- better (actually somewhat working) bbcode filtering
0.6.1
----
- menu doesn't auto-open if it was closed
0.7.0
----
- update to webfishing 1.10
- bbcode stuff only to lucystools users, color bug was patched
- LucysLib 0.1.0 dependency
- custom lobby code

View File

@ -2,145 +2,109 @@ extends Control
var MANAGER
const LucysLib_t = preload("res://mods/LucysLib/main.gd")
const BBCode_t = preload("res://mods/LucysLib/bbcode.gd")
func setup():
if MANAGER.DEBUG: print("[LUCYSTOOLS MENU] Setup...")
get_node("%lucy_bbcode").pressed = MANAGER.allow_bbcode
get_node("%lucy_punchback").pressed = MANAGER.do_punchback
get_node("%lucy_servername").text = MANAGER.custom_server_name
get_node("%lucy_servername_preview").bbcode_text = MANAGER.custom_server_name
get_node("%lucy_servername_preview").bbcode_text = MANAGER.custom_server_name + "'s Lobby"
get_node("%lucy_servermsg").text = MANAGER.server_join_message
var srv_m_bb: BBCode_t.BBCodeTag = MANAGER.LucysLib.BBCode.parse_bbcode_text(MANAGER.server_join_message)
get_node("%lucy_servermsg_preview").bbcode_text = srv_m_bb.get_full(MANAGER.allowed_bb)
get_node("%lucy_servermsg_preview2").bbcode_text = srv_m_bb.get_stripped()
get_node("%lucy_servermsg_preview").bbcode_text = MANAGER.server_join_message
get_node("%lucy_fpackets").value = MANAGER.frame_packets
get_node("%lucy_bpackets").value = MANAGER.bulk_packets
get_node("%lucy_binterval").value = MANAGER.bulk_interval
get_node("%lucy_finterval").value = MANAGER.full_interval
get_node("%lucy_intbbcode").pressed = MANAGER.allow_intrusive_bbcode
get_node("%lucy_chatcolor_bool").pressed = MANAGER.custom_color_enabled
get_node("%lucy_chatcolor").color = Color(MANAGER.custom_color)
get_node("%lucy_chatcolor_bool2").pressed = MANAGER.custom_text_color_enabled
get_node("%lucy_chatcolor2").color = Color(MANAGER.custom_text_color)
get_node("%lucy_lobbycode").text = MANAGER.custom_lobbycode
get_node("%lucy_name").text = MANAGER.custom_name
var tag_container = get_node("%bbcode_tags")
var new_btn
for v in BBCode_t.TAG_TYPE.values():
if v == BBCode_t.TAG_TYPE.ROOT or v == BBCode_t.TAG_TYPE.NULL: continue
new_btn = CheckBox.new()
new_btn.text = BBCode_t.TAG_TYPE.keys()[v]
new_btn.connect("pressed",self,"_tags_changed")
tag_container.add_child(new_btn)
update()
func update():
if MANAGER.DEBUG: print("[LUCYSTOOLS MENU] Update...")
var tag_type
for tag_btn in get_node("%bbcode_tags").get_children():
tag_type = BBCode_t.TAG_TYPE[tag_btn.text]
tag_btn.pressed = tag_type in MANAGER.allowed_bb
if MANAGER.DEBUG: print("[LUCYSTOOLS M UPDATE] " + tag_btn.text + " " + str(tag_type) + " " + str(tag_btn.pressed))
get_node("%lucy_srv_allow_bbcode").text = "Yes" if MANAGER.srv_allow_bbcode else "No"
_on_lucy_name_text_changed(MANAGER.custom_name)
func _tags_changed():
if MANAGER.DEBUG: print("[LUCYSTOOLS MENU] Tags changed...")
var tag_type
var allowed = []
for tag_btn in get_node("%bbcode_tags").get_children():
tag_type = BBCode_t.TAG_TYPE[tag_btn.text]
if tag_btn.pressed: allowed.append(tag_type)
if MANAGER.DEBUG: print("[LUCYSTOOLS M _TAGS_CHANGED]" + tag_btn.text + " " + str(tag_type) + " " + str(tag_btn.pressed))
MANAGER.allowed_bb = allowed
func _on_lucy_name_text_changed(new_text):
if MANAGER.DEBUG: print("[LUCYSTOOLS MENU] Name text changed...")
var result: BBCode_t.BBCodeTag = MANAGER.LucysLib.BBCode.parse_bbcode_text(new_text)
var result = MANAGER.bbcode_process(new_text)
#print("[fin] ", result.fin)
#print("[tags] ", result.tags)
#print("[stripped] ", result.stripped)
var net_name = Network.STEAM_USERNAME.replace("[", "").replace("]", "")
var good = result.get_stripped() == net_name
get_node("%lucy_name_preview").bbcode_text = result.get_full(MANAGER.allowed_bb)
var lol_steam_username = Network.STEAM_USERNAME.replace("[", "").replace("]", "")
var good = result.stripped == lol_steam_username
get_node("%lucy_name_preview").bbcode_text = result.fin
get_node("%lucy_namegood").bbcode_text = "[color=green]Good[/color]" if good else "[color=red]Bad[/color]"
MANAGER.custom_name_enabled = good
MANAGER.custom_name = new_text if good else ""
MANAGER.custom_name = result.fin
func _ready():
print("[LUCYSTOOLS] Menu Ready")
print("[LUCY] Menu Ready")
MANAGER = $"/root/LucyLucysTools"
visible = MANAGER.lucys_menu_visible
var can_spawn = (Network.GAME_MASTER or Network.PLAYING_OFFLINE) and MANAGER.ingame
get_node("%lucy_raincloud").disabled = not can_spawn
get_node("%lucy_meteor").disabled = not can_spawn
get_node("%lucy_void").disabled = not can_spawn
get_node("%lucy_freezerain").disabled = not can_spawn
get_node("%lucy_clearrain").disabled = not can_spawn
get_node("%lucy_clearmeteor").disabled = not can_spawn
get_node("%lucy_lobbyrefresh").disabled = not can_spawn
get_node("%lucy_bbcode").disabled = MANAGER.host_required and not Network.GAME_MASTER
get_node("%lucy_raincloud").disabled = not Network.GAME_MASTER or not MANAGER.ingame
get_node("%lucy_meteor").disabled = not Network.GAME_MASTER or not MANAGER.ingame
get_node("%lucy_freezerain").disabled = not Network.GAME_MASTER or not MANAGER.ingame
get_node("%lucy_clearrain").disabled = not Network.GAME_MASTER or not MANAGER.ingame
get_node("%lucy_clearmeteor").disabled = not Network.GAME_MASTER or not MANAGER.ingame
func _input(event):
if event is InputEventKey and event.scancode == KEY_F5 && event.pressed:
visible = !visible
print("[LUCYSTOOLS] Menu visble: ", visible)
MANAGER.lucys_menu_visible = visible
print("[LUCY] Menu visble: ", visible)
if event is InputEventKey and event.scancode == KEY_F6 && event.pressed:
var name = Steam.getLobbyData(Network.STEAM_LOBBY_ID, "name")
var lname = Steam.getLobbyData(Network.STEAM_LOBBY_ID, "lobby_name")
var nm = Steam.getNumLobbyMembers(Network.STEAM_LOBBY_ID)
var code = Steam.getLobbyData(Network.STEAM_LOBBY_ID, "code")
var type = Steam.getLobbyData(Network.STEAM_LOBBY_ID, "type")
var bbname = Steam.getLobbyData(Network.STEAM_LOBBY_ID, "bbcode_lobby_name")
var lobby_dat = {"name": name, "lobby_name":lname, "bbcode_lobby_name":bbname, "nm": nm, "code": code, "type": type}
print("[LUCYSTOOLS] LOBBY ", lobby_dat)
var lobby_dat = {"name": name, "nm": nm, "code": code, "type": type}
print("[LUCY] LOBBY ", lobby_dat)
func _on_lucy_bbcode_toggled(button_pressed):
MANAGER.allow_bbcode = button_pressed
func _on_lucy_punchback_toggled(button_pressed):
MANAGER.do_punchback = button_pressed
func _on_lucy_servername_text_changed(new_text):
get_node("%lucy_servername_preview").bbcode_text = new_text
get_node("%lucy_servername_preview").bbcode_text = new_text + "'s Lobby"
MANAGER.custom_server_name = new_text
func _on_lucy_servermsg_text_changed(new_text):
var srv_m_bb: BBCode_t.BBCodeTag = MANAGER.LucysLib.BBCode.parse_bbcode_text(new_text)
get_node("%lucy_servermsg_preview").bbcode_text = srv_m_bb.get_full(MANAGER.allowed_bb)
get_node("%lucy_servermsg_preview2").bbcode_text = srv_m_bb.get_stripped()
get_node("%lucy_servermsg_preview").bbcode_text = new_text
MANAGER.server_join_message = new_text
func _on_lucy_fpackets_value_changed(value):
MANAGER.frame_packets = value
func _on_lucy_bpackets_value_changed(value):
MANAGER.bulk_packets = value
func _on_lucy_binterval_value_changed(value):
MANAGER.bulk_interval = value
func _on_lucy_finterval_value_changed(value):
MANAGER.full_interval = value
func _on_lucy_chatcolor_bool_toggled(button_pressed):
MANAGER.custom_color_enabled = button_pressed
func _on_lucy_chatcolor_color_changed(color):
MANAGER.custom_color = color
func _on_lucy_chatcolor_bool2_toggled(button_pressed):
MANAGER.custom_text_color_enabled = button_pressed
func _on_lucy_chatcolor2_color_changed(color):
MANAGER.custom_text_color = color
func _on_lucy_intbbcode_toggled(button_pressed):
MANAGER.allow_intrusive_bbcode = button_pressed
func _on_lucy_bug_bb_toggled(button_pressed):
MANAGER.bug_bbcode = button_pressed
func _on_lucy_srv_bbcode_toggled(button_pressed):
if (not Network.GAME_MASTER and not Network.PLAYING_OFFLINE): return
MANAGER.srv_bbcode = button_pressed
func _on_lucy_lobbycode_text_changed(new_text):
MANAGER.custom_lobbycode = new_text
func _on_lucy_raincloud_pressed():
if not MANAGER.ingame or (not Network.GAME_MASTER and not Network.PLAYING_OFFLINE): return
print("[LUCYSTOOLS] Spawning raincloud")
if not MANAGER.ingame: return
print("[LUCY] Spawning raincloud")
var player = MANAGER.get_player()
var pos = Vector3(player.global_transform.origin.x, 42, player.global_transform.origin.z)
var zone = player.current_zone
Network._sync_create_actor("raincloud", pos, zone, - 1, Network.STEAM_ID)
func _on_lucy_meteor_pressed():
if not MANAGER.ingame or (not Network.GAME_MASTER and not Network.PLAYING_OFFLINE): return
if not MANAGER.ingame: return
if get_tree().get_nodes_in_group("meteor").size() > 10: return
print("[LUCYSTOOLS] Spawning meteor")
print("[LUCY] Spawning meteor")
var player_pos = MANAGER.get_player().global_transform.origin
var dist = INF
var point = null
@ -154,45 +118,27 @@ func _on_lucy_meteor_pressed():
Network._sync_create_actor("fish_spawn_alien", pos, zone, - 1, Network.STEAM_ID)
func _on_lucy_freezerain_pressed():
if not MANAGER.ingame or (not Network.GAME_MASTER and not Network.PLAYING_OFFLINE): return
print("[LUCYSTOOLS] Freezing rain")
if not MANAGER.ingame or not Network.GAME_MASTER: return
print("[LUCY] Freezing rain")
for cloud in get_tree().get_nodes_in_group("raincloud"):
if cloud.controlled == true:
cloud.speed = 0
cloud.decay = false
func _on_lucy_clearrain_pressed():
if not MANAGER.ingame or (not Network.GAME_MASTER and not Network.PLAYING_OFFLINE): return
print("[LUCYSTOOLS] Clearing rain")
if not MANAGER.ingame or not Network.GAME_MASTER: return
print("[LUCY] Clearing rain")
for cloud in get_tree().get_nodes_in_group("raincloud"):
cloud._deinstantiate(true)
func _on_lucy_clearchat_pressed():
Network._wipe_chat()
Network.GAMECHAT = ""
Network.LOCAL_GAMECHAT = ""
Network.emit_signal("_chat_update")
func _on_lucy_clearmeteor_pressed():
if not MANAGER.ingame or (not Network.GAME_MASTER and not Network.PLAYING_OFFLINE): return
print("[LUCYSTOOLS] Clearing meteor")
if not MANAGER.ingame or not Network.GAME_MASTER: return
print("[LUCY] Clearing meteor")
for meteor in get_tree().get_nodes_in_group("meteor"):
meteor._deinstantiate(true)
func _on_lucy_void_pressed():
if not MANAGER.ingame or (not Network.GAME_MASTER and not Network.PLAYING_OFFLINE): return
if get_tree().get_nodes_in_group("void_portal").size() > 10: return
print("[LUCYSTOOLS] Spawning void")
var player_pos = MANAGER.get_player().global_transform.origin
var dist = INF
var point = null
for n in get_tree().get_nodes_in_group("hidden_spot"):
var node_dist = n.global_transform.origin.distance_to(player_pos)
if node_dist < dist:
dist = node_dist
point = n
var zone = "main_zone"
var pos = point.global_transform.origin
Network._sync_create_actor("void_portal", pos, zone, - 1, Network.STEAM_ID)
func _on_lucy_lobbyrefresh_pressed():
if not MANAGER.ingame or (not Network.GAME_MASTER and not Network.PLAYING_OFFLINE): return
MANAGER.inject_lobby_data(1,Network.STEAM_LOBBY_ID)

View File

@ -4,107 +4,112 @@
[node name="lucys_menu" type="Control"]
margin_right = 800.0
margin_bottom = 400.0
margin_bottom = 329.0
script = ExtResource( 1 )
[node name="PanelContainer" type="PanelContainer" parent="."]
anchor_right = 1.0
anchor_bottom = 1.0
margin_bottom = 150.0
margin_bottom = 71.0
[node name="VBoxContainer" type="VBoxContainer" parent="PanelContainer"]
margin_left = 7.0
margin_top = 7.0
margin_right = 793.0
margin_bottom = 543.0
margin_bottom = 393.0
[node name="Label" type="Label" parent="PanelContainer/VBoxContainer"]
margin_right = 786.0
margin_bottom = 14.0
text = "Lucy's Options 0.7.0 - F5 to Toggle Menu"
text = "Lucy's Options - F5 to Toggle Menu"
[node name="HSeparator" type="HSeparator" parent="PanelContainer/VBoxContainer"]
margin_top = 18.0
margin_right = 786.0
margin_bottom = 22.0
[node name="Label4" type="Label" parent="PanelContainer/VBoxContainer"]
[node name="HFlowContainer" type="HFlowContainer" parent="PanelContainer/VBoxContainer"]
margin_top = 26.0
margin_right = 786.0
margin_bottom = 40.0
text = "BBCode is only visible to LucysTools-compatible users. Allowed BBCode tags:"
margin_bottom = 66.0
rect_pivot_offset = Vector2( -141, -49 )
[node name="bbcode_tags" type="HFlowContainer" parent="PanelContainer/VBoxContainer"]
[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/HFlowContainer"]
margin_top = 13.0
margin_right = 138.0
margin_bottom = 27.0
text = "Allow BBCode (Client)"
[node name="lucy_bbcode" type="CheckButton" parent="PanelContainer/VBoxContainer/HFlowContainer"]
unique_name_in_owner = true
margin_top = 44.0
margin_left = 142.0
margin_right = 218.0
margin_bottom = 40.0
[node name="Label3" type="Label" parent="PanelContainer/VBoxContainer/HFlowContainer"]
margin_left = 222.0
margin_top = 13.0
margin_right = 471.0
margin_bottom = 27.0
text = "Allow Intrusive BBCode (requires Host)"
[node name="lucy_intbbcode" type="CheckButton" parent="PanelContainer/VBoxContainer/HFlowContainer"]
unique_name_in_owner = true
margin_left = 475.0
margin_right = 551.0
margin_bottom = 40.0
[node name="Label2" type="Label" parent="PanelContainer/VBoxContainer/HFlowContainer"]
margin_left = 555.0
margin_top = 13.0
margin_right = 690.0
margin_bottom = 27.0
text = "Punch back on Punch"
[node name="lucy_punchback" type="CheckButton" parent="PanelContainer/VBoxContainer/HFlowContainer"]
unique_name_in_owner = true
margin_left = 694.0
margin_right = 770.0
margin_bottom = 40.0
[node name="HFlowContainer3" type="HFlowContainer" parent="PanelContainer/VBoxContainer"]
margin_top = 70.0
margin_right = 786.0
margin_bottom = 44.0
margin_bottom = 84.0
rect_pivot_offset = Vector2( -141, -49 )
[node name="HSeparator2" type="HSeparator" parent="PanelContainer/VBoxContainer"]
margin_top = 48.0
margin_right = 786.0
margin_bottom = 52.0
[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/HFlowContainer3"]
margin_right = 199.0
margin_bottom = 14.0
text = "Host Allows Intrusive BBCode: "
[node name="HFlowContainer" type="HFlowContainer" parent="PanelContainer/VBoxContainer"]
margin_top = 56.0
[node name="lucy_srv_allow_bbcode" type="Label" parent="PanelContainer/VBoxContainer/HFlowContainer3"]
unique_name_in_owner = true
margin_left = 203.0
margin_right = 221.0
margin_bottom = 14.0
text = "No"
[node name="HSeparator3" type="HSeparator" parent="PanelContainer/VBoxContainer"]
margin_top = 88.0
margin_right = 786.0
margin_bottom = 80.0
margin_bottom = 92.0
[node name="HFlowContainer4" type="HFlowContainer" parent="PanelContainer/VBoxContainer"]
margin_top = 96.0
margin_right = 786.0
margin_bottom = 120.0
rect_pivot_offset = Vector2( -141, -49 )
[node name="Label5" type="Label" parent="PanelContainer/VBoxContainer/HFlowContainer"]
[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/HFlowContainer4"]
margin_top = 5.0
margin_right = 135.0
margin_bottom = 19.0
text = "Punch back on Punch"
[node name="lucy_punchback" type="CheckBox" parent="PanelContainer/VBoxContainer/HFlowContainer"]
unique_name_in_owner = true
margin_left = 139.0
margin_right = 163.0
margin_bottom = 24.0
[node name="HSeparator3" type="HSeparator" parent="PanelContainer/VBoxContainer"]
margin_top = 84.0
margin_right = 786.0
margin_bottom = 88.0
[node name="HFlowContainer3" type="HFlowContainer" parent="PanelContainer/VBoxContainer"]
margin_top = 92.0
margin_right = 786.0
margin_bottom = 116.0
rect_pivot_offset = Vector2( -141, -49 )
[node name="Label5" type="Label" parent="PanelContainer/VBoxContainer/HFlowContainer3"]
margin_top = 5.0
margin_right = 127.0
margin_bottom = 19.0
text = "Custom Lobby Code"
[node name="lucy_lobbycode" type="LineEdit" parent="PanelContainer/VBoxContainer/HFlowContainer3"]
unique_name_in_owner = true
margin_left = 131.0
margin_right = 786.0
margin_bottom = 24.0
size_flags_horizontal = 3
max_length = 6
expand_to_text_length = true
placeholder_text = "Code (1-6 characters)"
[node name="Label2" type="Label" parent="PanelContainer/VBoxContainer"]
margin_top = 120.0
margin_right = 786.0
margin_bottom = 134.0
text = "Custom Server Name - Shown without BBCode for normal users"
[node name="HFlowContainer4" type="HFlowContainer" parent="PanelContainer/VBoxContainer"]
margin_top = 138.0
margin_right = 786.0
margin_bottom = 162.0
rect_pivot_offset = Vector2( -141, -49 )
text = "Custom Server Name"
[node name="lucy_servername" type="LineEdit" parent="PanelContainer/VBoxContainer/HFlowContainer4"]
unique_name_in_owner = true
margin_left = 139.0
margin_right = 786.0
margin_bottom = 24.0
size_flags_horizontal = 3
@ -112,9 +117,9 @@ expand_to_text_length = true
placeholder_text = "Name"
[node name="HFlowContainer6" type="HFlowContainer" parent="PanelContainer/VBoxContainer"]
margin_top = 166.0
margin_top = 124.0
margin_right = 786.0
margin_bottom = 180.0
margin_bottom = 138.0
rect_pivot_offset = Vector2( -141, -49 )
[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/HFlowContainer6"]
@ -134,24 +139,25 @@ text = "'s Lobby"
scroll_active = false
[node name="HSeparator4" type="HSeparator" parent="PanelContainer/VBoxContainer"]
margin_top = 184.0
margin_top = 142.0
margin_right = 786.0
margin_bottom = 188.0
[node name="Label3" type="Label" parent="PanelContainer/VBoxContainer"]
margin_top = 192.0
margin_right = 786.0
margin_bottom = 206.0
text = "Server Join Message - Will be shown without BBCode for people without LucysTools"
margin_bottom = 146.0
[node name="HFlowContainer5" type="HFlowContainer" parent="PanelContainer/VBoxContainer"]
margin_top = 210.0
margin_top = 150.0
margin_right = 786.0
margin_bottom = 234.0
margin_bottom = 174.0
rect_pivot_offset = Vector2( -141, -49 )
[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/HFlowContainer5"]
margin_top = 5.0
margin_right = 127.0
margin_bottom = 19.0
text = "Server Join Message"
[node name="lucy_servermsg" type="LineEdit" parent="PanelContainer/VBoxContainer/HFlowContainer5"]
unique_name_in_owner = true
margin_left = 131.0
margin_right = 786.0
margin_bottom = 24.0
size_flags_horizontal = 3
@ -159,39 +165,19 @@ expand_to_text_length = true
placeholder_text = "Message"
[node name="HFlowContainer7" type="HFlowContainer" parent="PanelContainer/VBoxContainer"]
margin_top = 238.0
margin_top = 178.0
margin_right = 786.0
margin_bottom = 252.0
margin_bottom = 192.0
rect_pivot_offset = Vector2( -141, -49 )
[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/HFlowContainer7"]
margin_right = 109.0
margin_right = 145.0
margin_bottom = 14.0
text = "Normal Preview: "
text = "Join Message Preview: "
[node name="lucy_servermsg_preview" type="RichTextLabel" parent="PanelContainer/VBoxContainer/HFlowContainer7"]
unique_name_in_owner = true
margin_left = 113.0
margin_right = 786.0
margin_bottom = 14.0
size_flags_horizontal = 3
bbcode_enabled = true
scroll_active = false
[node name="HFlowContainer10" type="HFlowContainer" parent="PanelContainer/VBoxContainer"]
margin_top = 256.0
margin_right = 786.0
margin_bottom = 270.0
rect_pivot_offset = Vector2( -141, -49 )
[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/HFlowContainer10"]
margin_right = 97.0
margin_bottom = 14.0
text = "Lame Preview: "
[node name="lucy_servermsg_preview2" type="RichTextLabel" parent="PanelContainer/VBoxContainer/HFlowContainer10"]
unique_name_in_owner = true
margin_left = 101.0
margin_left = 149.0
margin_right = 786.0
margin_bottom = 14.0
size_flags_horizontal = 3
@ -199,111 +185,82 @@ bbcode_enabled = true
scroll_active = false
[node name="HSeparator5" type="HSeparator" parent="PanelContainer/VBoxContainer"]
margin_top = 274.0
margin_top = 196.0
margin_right = 786.0
margin_bottom = 278.0
margin_bottom = 200.0
[node name="HFlowContainer8" type="HFlowContainer" parent="PanelContainer/VBoxContainer"]
margin_top = 282.0
margin_top = 204.0
margin_right = 786.0
margin_bottom = 306.0
margin_bottom = 228.0
rect_pivot_offset = Vector2( -141, -49 )
[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/HFlowContainer8"]
margin_top = 5.0
margin_right = 157.0
margin_right = 107.0
margin_bottom = 19.0
text = "Chat Name Color (global)"
text = "Chat Name Color"
[node name="lucy_chatcolor_bool" type="CheckBox" parent="PanelContainer/VBoxContainer/HFlowContainer8"]
unique_name_in_owner = true
margin_left = 161.0
margin_right = 231.0
margin_left = 111.0
margin_right = 181.0
margin_bottom = 24.0
text = "Enable"
[node name="lucy_chatcolor" type="ColorPickerButton" parent="PanelContainer/VBoxContainer/HFlowContainer8"]
unique_name_in_owner = true
margin_left = 235.0
margin_right = 277.0
margin_bottom = 24.0
rect_min_size = Vector2( 42, 0 )
edit_alpha = false
[node name="Label2" type="Label" parent="PanelContainer/VBoxContainer/HFlowContainer8"]
margin_left = 281.0
margin_top = 5.0
margin_right = 475.0
margin_bottom = 19.0
text = " Chat Text Color (LucysTools)"
[node name="lucy_chatcolor_bool2" type="CheckBox" parent="PanelContainer/VBoxContainer/HFlowContainer8"]
unique_name_in_owner = true
margin_left = 479.0
margin_right = 549.0
margin_bottom = 24.0
text = "Enable"
[node name="lucy_chatcolor2" type="ColorPickerButton" parent="PanelContainer/VBoxContainer/HFlowContainer8"]
unique_name_in_owner = true
margin_left = 553.0
margin_right = 595.0
margin_left = 185.0
margin_right = 227.0
margin_bottom = 24.0
rect_min_size = Vector2( 42, 0 )
edit_alpha = false
[node name="HFlowContainer9" type="HFlowContainer" parent="PanelContainer/VBoxContainer"]
margin_top = 310.0
margin_top = 232.0
margin_right = 786.0
margin_bottom = 324.0
margin_bottom = 256.0
rect_pivot_offset = Vector2( -141, -49 )
hint_tooltip = "Must match Steam username"
[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/HFlowContainer9"]
margin_right = 348.0
margin_bottom = 14.0
text = "Custom Name - Must match Steam Name (LucysTools)"
margin_top = 5.0
margin_right = 91.0
margin_bottom = 19.0
text = "Custom Name"
[node name="lucy_namegood" type="RichTextLabel" parent="PanelContainer/VBoxContainer/HFlowContainer9"]
unique_name_in_owner = true
margin_left = 352.0
margin_right = 402.0
margin_bottom = 14.0
margin_left = 95.0
margin_right = 145.0
margin_bottom = 24.0
rect_min_size = Vector2( 50, 0 )
bbcode_enabled = true
bbcode_text = "[color=green]Good[/color]"
text = "Good"
scroll_active = false
[node name="lucy_name" type="LineEdit" parent="PanelContainer/VBoxContainer"]
[node name="lucy_name" type="LineEdit" parent="PanelContainer/VBoxContainer/HFlowContainer9"]
unique_name_in_owner = true
margin_top = 328.0
margin_right = 786.0
margin_bottom = 352.0
margin_left = 149.0
margin_right = 207.0
margin_bottom = 24.0
expand_to_text_length = true
placeholder_text = "Name"
[node name="lucy_name_preview" type="RichTextLabel" parent="PanelContainer/VBoxContainer"]
[node name="lucy_name_preview" type="RichTextLabel" parent="PanelContainer/VBoxContainer/HFlowContainer9"]
unique_name_in_owner = true
margin_top = 356.0
margin_left = 211.0
margin_right = 786.0
margin_bottom = 371.0
rect_min_size = Vector2( 0, 15 )
margin_bottom = 24.0
size_flags_horizontal = 3
bbcode_enabled = true
bbcode_text = "If you see this, modify your custom name"
text = "If you see this, modify your custom name"
scroll_active = false
[node name="HSeparator6" type="HSeparator" parent="PanelContainer/VBoxContainer"]
margin_top = 375.0
margin_right = 786.0
margin_bottom = 379.0
[node name="HFlowContainer2" type="HFlowContainer" parent="PanelContainer/VBoxContainer"]
margin_top = 383.0
margin_top = 260.0
margin_right = 786.0
margin_bottom = 403.0
margin_bottom = 280.0
[node name="lucy_clearchat" type="Button" parent="PanelContainer/VBoxContainer/HFlowContainer2"]
margin_right = 76.0
@ -311,69 +268,155 @@ margin_bottom = 20.0
hint_tooltip = "Clears game chat (for you only)"
text = "Clear Chat"
[node name="lucy_lobbyrefresh" type="Button" parent="PanelContainer/VBoxContainer/HFlowContainer2"]
unique_name_in_owner = true
margin_left = 80.0
margin_right = 180.0
margin_bottom = 20.0
text = "Update Lobby"
[node name="lucy_raincloud" type="Button" parent="PanelContainer/VBoxContainer/HFlowContainer2"]
unique_name_in_owner = true
margin_left = 184.0
margin_right = 267.0
margin_left = 80.0
margin_right = 198.0
margin_bottom = 20.0
text = "Spawn Rain"
text = "Spawn Raincloud"
[node name="lucy_meteor" type="Button" parent="PanelContainer/VBoxContainer/HFlowContainer2"]
unique_name_in_owner = true
margin_left = 271.0
margin_right = 373.0
margin_left = 202.0
margin_right = 304.0
margin_bottom = 20.0
text = "Spawn Meteor"
[node name="lucy_void" type="Button" parent="PanelContainer/VBoxContainer/HFlowContainer2"]
unique_name_in_owner = true
margin_left = 377.0
margin_right = 461.0
margin_bottom = 20.0
text = "Spawn Void"
[node name="lucy_freezerain" type="Button" parent="PanelContainer/VBoxContainer/HFlowContainer2"]
unique_name_in_owner = true
margin_left = 465.0
margin_right = 551.0
margin_left = 308.0
margin_right = 394.0
margin_bottom = 20.0
text = "Freeze Rain"
[node name="lucy_clearrain" type="Button" parent="PanelContainer/VBoxContainer/HFlowContainer2"]
unique_name_in_owner = true
margin_left = 555.0
margin_right = 630.0
margin_left = 398.0
margin_right = 473.0
margin_bottom = 20.0
text = "Clear Rain"
[node name="lucy_clearmeteor" type="Button" parent="PanelContainer/VBoxContainer/HFlowContainer2"]
unique_name_in_owner = true
margin_left = 634.0
margin_right = 728.0
margin_left = 477.0
margin_right = 571.0
margin_bottom = 20.0
text = "Clear Meteor"
[node name="HSeparator2" type="HSeparator" parent="PanelContainer/VBoxContainer"]
margin_top = 284.0
margin_right = 786.0
margin_bottom = 288.0
[node name="HSplitContainer" type="HSplitContainer" parent="PanelContainer/VBoxContainer"]
margin_top = 292.0
margin_right = 786.0
margin_bottom = 316.0
split_offset = 100
[node name="HFlowContainer3" type="HFlowContainer" parent="PanelContainer/VBoxContainer/HSplitContainer"]
margin_right = 218.0
margin_bottom = 24.0
[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/HSplitContainer/HFlowContainer3"]
margin_top = 5.0
margin_right = 118.0
margin_bottom = 19.0
text = "Per Frame Packets"
[node name="lucy_fpackets" type="SpinBox" parent="PanelContainer/VBoxContainer/HSplitContainer/HFlowContainer3"]
unique_name_in_owner = true
margin_left = 122.0
margin_right = 196.0
margin_bottom = 24.0
max_value = 256.0
value = 32.0
rounded = true
allow_greater = true
[node name="HFlowContainer" type="HFlowContainer" parent="PanelContainer/VBoxContainer/HSplitContainer"]
margin_left = 230.0
margin_right = 786.0
margin_bottom = 24.0
[node name="Label2" type="Label" parent="PanelContainer/VBoxContainer/HSplitContainer/HFlowContainer"]
margin_top = 5.0
margin_right = 116.0
margin_bottom = 19.0
text = "Bulk Read Packets"
[node name="lucy_bpackets" type="SpinBox" parent="PanelContainer/VBoxContainer/HSplitContainer/HFlowContainer"]
unique_name_in_owner = true
margin_left = 120.0
margin_right = 194.0
margin_bottom = 24.0
max_value = 4096.0
value = 128.0
rounded = true
allow_greater = true
[node name="HSplitContainer2" type="HSplitContainer" parent="PanelContainer/VBoxContainer"]
margin_top = 320.0
margin_right = 786.0
margin_bottom = 344.0
split_offset = 100
[node name="HFlowContainer3" type="HFlowContainer" parent="PanelContainer/VBoxContainer/HSplitContainer2"]
margin_right = 216.0
margin_bottom = 24.0
[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/HSplitContainer2/HFlowContainer3"]
margin_top = 5.0
margin_right = 116.0
margin_bottom = 19.0
text = "Bulk Read Interval"
[node name="lucy_binterval" type="SpinBox" parent="PanelContainer/VBoxContainer/HSplitContainer2/HFlowContainer3"]
unique_name_in_owner = true
margin_left = 120.0
margin_right = 194.0
margin_bottom = 24.0
max_value = 120.0
step = 0.05
value = 0.8
allow_greater = true
[node name="HFlowContainer" type="HFlowContainer" parent="PanelContainer/VBoxContainer/HSplitContainer2"]
margin_left = 228.0
margin_right = 786.0
margin_bottom = 24.0
[node name="Label2" type="Label" parent="PanelContainer/VBoxContainer/HSplitContainer2/HFlowContainer"]
margin_top = 5.0
margin_right = 111.0
margin_bottom = 19.0
text = "Full Read Interval"
[node name="lucy_finterval" type="SpinBox" parent="PanelContainer/VBoxContainer/HSplitContainer2/HFlowContainer"]
unique_name_in_owner = true
margin_left = 115.0
margin_right = 189.0
margin_bottom = 24.0
max_value = 120.0
step = 0.05
value = 6.4
allow_greater = true
[connection signal="toggled" from="PanelContainer/VBoxContainer/HFlowContainer/lucy_bbcode" to="." method="_on_lucy_bbcode_toggled"]
[connection signal="toggled" from="PanelContainer/VBoxContainer/HFlowContainer/lucy_intbbcode" to="." method="_on_lucy_intbbcode_toggled"]
[connection signal="toggled" from="PanelContainer/VBoxContainer/HFlowContainer/lucy_punchback" to="." method="_on_lucy_punchback_toggled"]
[connection signal="text_changed" from="PanelContainer/VBoxContainer/HFlowContainer3/lucy_lobbycode" to="." method="_on_lucy_lobbycode_text_changed"]
[connection signal="text_changed" from="PanelContainer/VBoxContainer/HFlowContainer4/lucy_servername" to="." method="_on_lucy_servername_text_changed"]
[connection signal="text_changed" from="PanelContainer/VBoxContainer/HFlowContainer5/lucy_servermsg" to="." method="_on_lucy_servermsg_text_changed"]
[connection signal="toggled" from="PanelContainer/VBoxContainer/HFlowContainer8/lucy_chatcolor_bool" to="." method="_on_lucy_chatcolor_bool_toggled"]
[connection signal="color_changed" from="PanelContainer/VBoxContainer/HFlowContainer8/lucy_chatcolor" to="." method="_on_lucy_chatcolor_color_changed"]
[connection signal="toggled" from="PanelContainer/VBoxContainer/HFlowContainer8/lucy_chatcolor_bool2" to="." method="_on_lucy_chatcolor_bool2_toggled"]
[connection signal="color_changed" from="PanelContainer/VBoxContainer/HFlowContainer8/lucy_chatcolor2" to="." method="_on_lucy_chatcolor2_color_changed"]
[connection signal="text_changed" from="PanelContainer/VBoxContainer/lucy_name" to="." method="_on_lucy_name_text_changed"]
[connection signal="text_changed" from="PanelContainer/VBoxContainer/HFlowContainer9/lucy_name" to="." method="_on_lucy_name_text_changed"]
[connection signal="pressed" from="PanelContainer/VBoxContainer/HFlowContainer2/lucy_clearchat" to="." method="_on_lucy_clearchat_pressed"]
[connection signal="pressed" from="PanelContainer/VBoxContainer/HFlowContainer2/lucy_lobbyrefresh" to="." method="_on_lucy_lobbyrefresh_pressed"]
[connection signal="pressed" from="PanelContainer/VBoxContainer/HFlowContainer2/lucy_raincloud" to="." method="_on_lucy_raincloud_pressed"]
[connection signal="pressed" from="PanelContainer/VBoxContainer/HFlowContainer2/lucy_meteor" to="." method="_on_lucy_meteor_pressed"]
[connection signal="pressed" from="PanelContainer/VBoxContainer/HFlowContainer2/lucy_void" to="." method="_on_lucy_void_pressed"]
[connection signal="pressed" from="PanelContainer/VBoxContainer/HFlowContainer2/lucy_freezerain" to="." method="_on_lucy_freezerain_pressed"]
[connection signal="pressed" from="PanelContainer/VBoxContainer/HFlowContainer2/lucy_clearrain" to="." method="_on_lucy_clearrain_pressed"]
[connection signal="pressed" from="PanelContainer/VBoxContainer/HFlowContainer2/lucy_clearmeteor" to="." method="_on_lucy_clearmeteor_pressed"]
[connection signal="value_changed" from="PanelContainer/VBoxContainer/HSplitContainer/HFlowContainer3/lucy_fpackets" to="." method="_on_lucy_fpackets_value_changed"]
[connection signal="value_changed" from="PanelContainer/VBoxContainer/HSplitContainer/HFlowContainer/lucy_bpackets" to="." method="_on_lucy_bpackets_value_changed"]
[connection signal="value_changed" from="PanelContainer/VBoxContainer/HSplitContainer2/HFlowContainer3/lucy_binterval" to="." method="_on_lucy_binterval_value_changed"]
[connection signal="value_changed" from="PanelContainer/VBoxContainer/HSplitContainer2/HFlowContainer/lucy_finterval" to="." method="_on_lucy_finterval_value_changed"]

View File

@ -1,200 +1,180 @@
extends Node
const LucysLib_t = preload("res://mods/LucysLib/main.gd")
var LucysLib: LucysLib_t
const BBCode_t = preload("res://mods/LucysLib/bbcode.gd")
const NetManager_t := preload("res://mods/LucysLib/net.gd")
const LUCYS_MENU_SCENE = preload("res://mods/Lucy.LucysTools/lucys_menu.tscn")
var lucys_menu = null
onready var root = get_tree().root
var custom_name_enabled: bool = false
var do_punchback = false
var allow_bbcode = false
var custom_server_name = "" setget set_server_name
var server_join_message = "[color=#5BCEFA]TRAN[/color][color=#F5A9B8]S RIG[/color][color=#ffffff]HTS![/color]" setget set_join_message
var frame_packets = 50 setget set_frame_packets
var bulk_packets = 200 setget set_bulk_packets
var bulk_interval = 1 setget set_bulk_interval
var full_interval = 5 setget set_full_interval
var custom_color_enabled = false
var custom_color = Color("009cd0") setget set_custom_color
var custom_name_enabled = false
var custom_name = ""
var allow_intrusive_bbcode = false setget set_allow_intrusive_bbcode
var srv_allow_bbcode = false setget set_srv_bbcode
var log_messages = false setget set_log_messages
var allowed_tags = ["b", "i", "u", "s", "color"]
var escape_invalid = true
var bbcode_matcher = null
# i know this sucks
# but i have things to do
func bbcode_recurse(text, data):
var m = bbcode_matcher.search(text)
if m == null:
var escaped = text.replace('[lb]','[').replace('[','[lb]') if escape_invalid else text
data.fin += escaped
data.stripped += escaped
else:
#print("Found ", m.strings, " in '", text, "'")
bbcode_recurse(m.get_string(1), data)
var tag = m.get_string(2)
var junk = m.get_string(3)
var allowed = tag in allowed_tags
if allowed:
data.fin += "[" + tag + junk + "]"
else:
data.fin += "[lb]" + tag + junk + "]"
data.stripped += "[lb]" + tag + junk + "]"
#print("TAG ", m.get_string(2), " JUNK ", m.get_string(3))
data.tags.append([tag, junk])
bbcode_recurse(m.get_string(4), data)
if allowed:
data.fin += "[/" + tag + "]"
else:
data.fin += "[lb]/" + tag + "]"
data.stripped += "[lb]/" + tag + "]"
bbcode_recurse(m.get_string(5), data)
func bbcode_process(text):
bbcode_matcher = RegEx.new()
bbcode_matcher.compile("^(.*?)\\[(\\w+?)([^\\]]*)\\](.+?)\\[/\\2\\](.*?)$")
#print("processing '", text, "'")
var data = {"fin": "", "tags": [], "stripped": ""}
bbcode_recurse(text, data)
return data
# Patched Network vars
# var LUCY_PACKETS_READ = 0
# var LUCY_BULK_FULL_TIMER = 0
# var LUCY_FRAME_PACKETS = 32
# var LUCY_BULK_PACKETS = 128
# var LUCY_BULK_INTERVAL = 0.8
# var LUCY_BULK_FULL_INTERVAL = 6.4
# var LUCY_SRV_NAME
# var LUCY_PUNCHED_ME
# var LUCY_INSTANCE_SENDER
# var LUCY_LOG_MESSAGES
var ingame = false
# config options
var do_punchback: bool = false
var custom_server_name: String = ""
var server_join_message: String = "[color=#5BCEFA]TRAN[/color][color=#F5A9B8]S RIG[/color][color=#ffffff]HTS![/color]"
var custom_color_enabled: bool = false
var custom_color: Color = Color("009cd0") setget set_custom_color
var log_messages: bool = false setget set_log_messages
var custom_name: String = ""
var DEBUG: bool = false setget set_DEBUG
var custom_text_color: Color = Color("00ff00")
var custom_text_color_enabled: bool = false
var lucys_menu_visible: bool = true
var allowed_bb: Array = BBCode_t.DEFAULT_ALLOWED_TYPES setget set_allowed_bb
var custom_lobbycode: String = ""
func process_message(lit_text, final_text, prefix, suffix, endcap, username, final_color, spoken_text):
var thing = {
"lit_text": lit_text, "final_text": final_text, "prefix": prefix, "suffix": suffix,
"endcap": endcap, "username": username, "final_color": final_color,
"srv_allow_bbcode": srv_allow_bbcode, "custom_color_enabled": custom_color_enabled,
"custom_name_enabled": custom_name_enabled, "allow_bbcode": allow_bbcode,
"allowed_tags": allowed_tags
}
#print("FUCK ", thing)
if srv_allow_bbcode and lit_text.begins_with("%"):
return [lit_text.trim_prefix('%'), spoken_text]
const SAVE_KEYS = [
"do_punchback", "allowed_bb",
"custom_server_name", "server_join_message",
"custom_color_enabled", "custom_color",
"log_messages", "custom_name",
"DEBUG", "custom_text_color",
"custom_text_color_enabled",
"lucys_menu_visible", "custom_lobbycode"
]
var name = custom_name if custom_name_enabled else username
var color = custom_color if custom_color_enabled else final_color
var msg = final_text
var speak = spoken_text
if allow_bbcode:
var p = bbcode_process(lit_text)
if not p.tags.empty():
msg = p.fin
speak = p.stripped
return [
prefix + "[color=#" + str(color.to_html()) + "]" + name + endcap + msg + suffix,
speak
]
func bbcode_changes():
if srv_allow_bbcode and allow_intrusive_bbcode:
allowed_tags = [
"b", "i", "u", "s", "color",
"wave", "rainbow", "shake", "tornado", "font"]
else:
allowed_tags = [
"b", "i", "u", "s", "color"]
if lucys_menu != null: lucys_menu.update()
func set_allowed_bb(val):
var f = []
for v in val:
if v == BBCode_t.TAG_TYPE.NULL or v == BBCode_t.TAG_TYPE.ROOT:
continue
if v in BBCode_t.TAG_TYPE.values():
f.append(v)
allowed_bb = f
LucysLib.ALLOWED_TAG_TYPES = f
func set_log_messages(val):
log_messages = val
Network.LUCY_LOG_MESSAGES = val
func set_allow_intrusive_bbcode(bbcode):
allow_intrusive_bbcode = bbcode
if Network.GAME_MASTER or not ingame:
self.srv_allow_bbcode = bbcode
else: bbcode_changes()
func set_srv_bbcode(bbcode):
if Network.GAME_MASTER and not Network.PLAYING_OFFLINE: send_server_sync_actor()
srv_allow_bbcode = bbcode
bbcode_changes()
func set_server_name(name):
custom_server_name = name
Network.LUCY_SRV_NAME = name
func set_join_message(msg):
server_join_message = msg
func set_frame_packets(val):
frame_packets = val
Network.LUCY_FRAME_PACKETS = val
func set_bulk_packets(val):
bulk_packets = val
Network.LUCY_BULK_PACKETS = val
func set_bulk_interval(val):
bulk_interval = val
Network.LUCY_BULK_INTERVAL = val
Network.BULK_PACKET_READ_TIMER = 0
func set_full_interval(val):
full_interval = val
Network.LUCY_BULK_FULL_INTERVAL = val
Network.LUCY_BULK_FULL_TIMER = 0
func set_custom_color(val):
custom_color = Color(val) if Color(val) != Color("d5aa73") else Color("739ed5")
custom_color.a = 1
func set_log_messages(val):
log_messages = val
LucysLib.LOG_MESSAGES = val
func set_DEBUG(val):
DEBUG = val
LucysLib.DEBUG = val
LucysLib.NetManager.DEBUG = val
LucysLib.BBCode.DEBUG = val
func get_user_color() -> Color:
var base_color = Color(Globals.cosmetic_data[PlayerData.cosmetics_equipped["primary_color"]]["file"].main_color) * Color(0.95, 0.9, 0.9)
var color = custom_color if custom_color_enabled else base_color
return color
# intercept player message send
# we just take over - replicate as
# much as i can be bothered to
func process_message(text: String, local: bool, player, playerhud):
if DEBUG:
var thing = {"text":text,"local":local,"player":player,"playerhud":playerhud,"custom_name":custom_name}
print("[LUCYSTOOLS process_message] ", thing)
# is this a host message? (no username)
if text.begins_with("%") and (Network.GAME_MASTER or Network.PLAYING_OFFLINE):
text = text.trim_prefix("%")
var msg := LucysLib.BBCode.parse_bbcode_text(text)
LucysLib.send_message(msg, Color.aqua, false, null, "peers")
return
# i don't know why the wag stuff toggles multiple times
# and applies anywhere in string
# i'm doing it once.
if "/wag" in text:
PlayerData.emit_signal("_wag_toggle")
text.replace("/wag","")
# /me has to be at beginning because i say so
var colon: bool = true
if text.begins_with("/me "):
colon = false
text = text.trim_prefix("/me ")
# process message into bbcode nodes
var msg := LucysLib.BBCode.parse_bbcode_text(text)
# clamp transparency
if not (Network.GAME_MASTER or Network.PLAYING_OFFLINE):
LucysLib.BBCode.clamp_alpha(msg, 0.7)
# get drunk params
var drunk_chance := 0.0
var drunk_max := 0
if is_instance_valid(player):
drunk_chance = 0.13 * player.drunk_tier
drunk_max = player.drunk_tier
# spoken text is gonna have different drunk text
# i don't want to think about this more
# get bbcode tag so it can get sent to the
# same function at least
# maybe i'll just add a toggle for hicc
var spoken_msg := LucysLib.BBCode.parse_bbcode_text(msg.get_stripped())
drunk_text_add(msg, drunk_chance, drunk_max, false)
drunk_text_add(spoken_msg, drunk_chance, drunk_max, true)
# add text color if it exists
if custom_text_color_enabled:
var col_tag: BBCode_t.BBCodeColorTag = BBCode_t.tag_creator(BBCode_t.TAG_TYPE.color, "")
col_tag.color = custom_text_color
col_tag.inner = [msg]
msg = col_tag
# prefix endcap suffix stuff
if colon:
msg.inner.push_front("%u: ")
else:
msg.inner.push_front("(%u ")
msg.inner.push_back(")")
var name := LucysLib.BBCode.parse_bbcode_text(custom_name) if custom_name_enabled else null
if DEBUG:
print("[LUCYSTOOLS process_message] ", {"name":name,"msg":msg})
LucysLib.send_message(msg, get_user_color(), local, name, "peers")
var spoken_text := spoken_msg.get_stripped()
if colon and spoken_text != "": playerhud.emit_signal("_message_sent", spoken_text)
# drunk processing. ouch this sucks
# not quite the same as vanilla
# if people want drunk text that
# works better. i will but. ugh
var line: String = ""
func drunk_text_add(msg: BBCode_t.BBCodeTag, drunk_chance: float, drunk_max: int, do_hicc: bool):
for index in msg.inner.size():
if msg.inner[index] is BBCode_t.BBCodeTag:
drunk_text_add(msg.inner[index], drunk_chance, drunk_max, do_hicc)
else:
var lines = msg.inner[index].split(" ")
var new: String = ""
var linei: int = 0
for line in lines:
for i in drunk_max:
if randf() >= drunk_chance or line == "": break
var d_effect = randi() % 5
var slot = randi() % line.length()
match d_effect:
0, 1: line = line.insert(slot, line[slot])
2: line = line.insert(slot, "'")
3: line = line.insert(slot, ",")
4:
if do_hicc: line = line.insert(slot, " -*HICC*- ")
break
if linei > 0: new += " "
linei += 1
new += line
msg.inner[index] = new
func process_packet_player_punch(DATA, PACKET_SENDER, from_host) -> bool:
# lucy punchback :3
if not DATA.has("nya"): punched(PACKET_SENDER, DATA["punch_type"])
# still get punched!
return false
func _ready():
print("[LUCY] Loaded LucysTools 0.7.0")
LucysLib = $"/root/LucysLib"
print("[LUCY] Loaded LucysTools")
load_settings()
root.connect("child_entered_tree", self, "_on_enter")
Network.connect("_new_player_join", self, "new_player")
Steam.connect("lobby_created", self, "inject_lobby_data")
PlayerData.connect("_punched", self, "punched")
Network.connect("_instance_actor", self, "_instance_actor")
LucysLib.register_bb_msg_support()
LucysLib.register_log_msg_support()
LucysLib.NetManager.add_network_processor("player_punch", funcref(self, "process_packet_player_punch"), 10)
func send_server_sync_actor(to = "peers"):
if not Network.GAME_MASTER: return
var dict = {"actor_type": "lucy_fake_actor", "at": Vector3.ZERO, "zone": "", "actor_id": 0, "creator_id": Network.STEAM_ID, "data": {
"allow_bbcode": allow_bbcode
}}
Network._send_P2P_Packet({"type": "instance_actor", "params": dict}, to, 2)
func inject_lobby_data(connect, lobby_id):
if connect != 1: return
if custom_server_name != "":
var bb_name := LucysLib.BBCode.parse_bbcode_text(custom_server_name)
Steam.setLobbyData(lobby_id, "bbcode_lobby_name", bb_name.get_full(LucysLib.ALLOWED_TAG_TYPES))
Steam.setLobbyData(lobby_id, "lobby_name", bb_name.get_stripped())
if custom_lobbycode != "":
Steam.setLobbyData(lobby_id, "code", custom_lobbycode)
Network.LOBBY_CODE = custom_lobbycode
func _instance_actor(dict):
if dict["actor_type"] != "lucy_fake_actor": return
var sender = Network.LUCY_INSTANCE_SENDER
Network.LUCY_INSTANCE_SENDER = 0
if sender != Network.KNOWN_GAME_MASTER or Network.GAME_MASTER: return
var data = dict["data"]
self.srv_allow_bbcode = data["allow_bbcode"]
func get_player() -> Actor:
for p in get_tree().get_nodes_in_group("player"):
@ -202,24 +182,28 @@ func get_player() -> Actor:
return p
return null
func punched(puncher_id, type):
print("[LUCY] punch from ", Network._get_username_from_id(puncher_id))
func punched(from, type):
print("[LUCY] punched!")
if not do_punchback: return
if puncher_id == 0 or puncher_id == Network.STEAM_ID: return
if Network.LUCY_PUNCHED_ME == 0 or Network.LUCY_PUNCHED_ME == Network.STEAM_ID: return
var punched_me = null
for p in get_tree().get_nodes_in_group("player"):
if p.owner_id == Network.LUCY_PUNCHED_ME: punched_me = p
if punched_me == null: return
if punched_me.controlled: return
print("[LUCY] punching back...")
Network._send_P2P_Packet(
{"type": "player_punch", "from_pos": get_player().global_transform.origin, "punch_type": type, "nya": "nya"},
str(puncher_id), 2, Network.CHANNELS.ACTOR_ACTION)
Network.LUCY_PUNCHED_ME = 0
Network._send_P2P_Packet({"type": "player_punch", "from": get_player().global_transform.origin, "player": Network.STEAM_ID, "punch_type": type, "nya": "nya"}, str(punched_me.owner_id), 2)
func new_player(id):
print("[LUCY] new player!")
if server_join_message.empty() or not Network.GAME_MASTER: return
print("[LUCY] sending join message")
var bb_msg := LucysLib.BBCode.parse_bbcode_text(server_join_message)
LucysLib.send_message(bb_msg, Color.aqua, false, null, "peers")
Network._send_message(server_join_message)
send_server_sync_actor(str(id))
func _on_enter(node: Node):
if DEBUG: print("[LUCY] INSTANCING MENU")
if node.name == "main_menu":
lucys_menu = LUCYS_MENU_SCENE.instance()
lucys_menu.MANAGER = self
@ -231,8 +215,21 @@ func _on_enter(node: Node):
lucys_menu.MANAGER = self
node.add_child(lucys_menu)
ingame = true
# retrigger setter
self.srv_allow_bbcode = false
self.allow_intrusive_bbcode = allow_intrusive_bbcode
lucys_menu.setup()
const save_keys = [
"do_punchback", "allow_bbcode",
"custom_server_name", "server_join_message",
"frame_packets", "bulk_packets",
"bulk_interval", "full_interval",
"custom_color_enabled", "custom_color",
"log_messages", "custom_name",
"allow_intrusive_bbcode"
]
func load_settings():
print("[LUCY] Loading settings")
var file = File.new()
@ -242,17 +239,16 @@ func load_settings():
var result = parse.result
# trigger setters
for key in result.keys():
if key in SAVE_KEYS: self[key] = result[key]
if key in save_keys: self[key] = result[key]
func save_settings():
print("[LUCY] Saving settings")
custom_color = Color(custom_color).to_html()
var settings = {}
for key in SAVE_KEYS:
if key in ["custom_color", "custom_text_color"]:
settings[key] = self[key].to_html()
else:
settings[key] = self[key]
for key in save_keys:
settings[key] = self[key]
var file = File.new()
if file.open(OS.get_executable_path().get_base_dir().plus_file("GDWeave/configs/LucysTools.json"),File.WRITE) == OK:

View File

@ -2,6 +2,6 @@
.vs/
*.user
/local
Makefile
bin/
obj/

View File

@ -14,4 +14,21 @@
<ItemGroup>
<None Include="manifest.json" CopyToOutputDirectory="PreserveNewest"/>
</ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="'$(GDWeavePath)' != ''">
<PropertyGroup>
<IsWindows Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))'">true</IsWindows>
<IsLinux Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))'">true</IsLinux>
</PropertyGroup>
<Exec
Command="xcopy /Y /I &quot;$(TargetDir)&quot; &quot;$(GDWeavePath)/mods/$(AssemblyName)&quot;"
Condition="'$(IsWindows)' == 'true'"
/>
<Exec
Command="cp -r $(TargetDir) '$(GDWeavePath)/mods/$(AssemblyName)/'"
Condition="'$(IsLinux)' == 'true'"
/>
</Target>
</Project>

View File

@ -13,8 +13,7 @@ public class Mod : IMod {
modInterface.Logger.Information("Lucy was here :3");
ModInterface = modInterface;
modInterface.RegisterScriptMod(new LucysChatChanges());
modInterface.RegisterScriptMod(new LucyServerBrowserChanges());
modInterface.RegisterScriptMod(new LucyMainMenuChanges());
modInterface.RegisterScriptMod(new LucysNetFixes());
}
public void Dispose(){}
@ -26,195 +25,13 @@ public record CodeChange {
public required Token[] code_to_add;
}
public class LucyServerBrowserChanges: IScriptMod
{
bool IScriptMod.ShouldRun(string path) => path == "res://Scenes/Menus/Main Menu/ServerButton/server_button.gdc";
CodeChange[] changes = {
new CodeChange {
name = "server button arg",
// , age_limit, dated, banned END
multitoken_prefix = new Func<Token, bool>[] {
t => t.Type == TokenType.Comma,
t => t is IdentifierToken {Name: "age_limit"},
t => t.Type == TokenType.Comma,
t => t is IdentifierToken {Name: "dated"},
t => t.Type == TokenType.Comma,
t => t is IdentifierToken {Name: "banned"},
},
// , lucy_display
code_to_add = new Token[] {
new Token(TokenType.Comma),
new IdentifierToken("lucy_display"),
new Token(TokenType.OpAssign),
new ConstantToken(new StringVariant("")),
}
},
new CodeChange {
name = "server button load",
// display_name.replace(']', '')
// END
multitoken_prefix = new Func<Token, bool>[] {
t => t is IdentifierToken {Name: "display_name"},
t => t.Type == TokenType.Period,
t => t is IdentifierToken {Name: "replace"},
t => t.Type == TokenType.ParenthesisOpen,
t => t is ConstantToken {Value:StringVariant{Value:"]"}},
t => t.Type == TokenType.Comma,
t => t is ConstantToken,
t => t.Type == TokenType.ParenthesisClose,
t => t.Type == TokenType.Newline,
},
// if lucy_display != "": display_name = lucy_display
code_to_add = new Token[] {
new Token(TokenType.CfIf),
new IdentifierToken("lucy_display"),
new Token(TokenType.OpNotEqual),
new ConstantToken(new StringVariant("")),
new Token(TokenType.Colon),
new IdentifierToken("display_name"),
new Token(TokenType.OpAssign),
new IdentifierToken("lucy_display"),
new Token(TokenType.Newline, 1),
}
},
};
IEnumerable<Token> IScriptMod.Modify(string path, IEnumerable<Token> tokens)
{
var pending_changes = changes
.Select(c => (c, new MultiTokenWaiter(c.multitoken_prefix)))
.ToList();
// I'm sure there's a better way to do this
// with list comprehension stuff, but my
// C# is too rusty
foreach (var token in tokens) {
var had_change = false;
foreach (var (change, waiter) in pending_changes) {
if (waiter.Check(token)) {
Mod.ModInterface.Logger.Information($"Adding Lucy server button mod {change.name}");
yield return token;
foreach (var t in change.code_to_add) yield return t;
had_change = true;
break;
}
}
if (!had_change) yield return token;
}
}
}
public class LucyMainMenuChanges: IScriptMod
{
bool IScriptMod.ShouldRun(string path) => path == "res://Scenes/Menus/Main Menu/main_menu.gdc";
CodeChange[] changes = {
new CodeChange {
name = "server button lucy_display get",
// if $"%hidenames".pressed: lobby_custom_name = ""
// END
multitoken_prefix = new Func<Token, bool>[] {
t => t.Type == TokenType.CfIf,
t => t.Type == TokenType.Dollar,
t => t is ConstantToken {Value:StringVariant{Value:"%hidenames"}},
t => t.Type == TokenType.Period,
t => t is IdentifierToken {Name: "pressed"},
t => t.Type == TokenType.Colon,
t => t is IdentifierToken {Name: "lobby_custom_name"},
t => t.Type == TokenType.OpAssign,
t => t.Type == TokenType.Constant,
t => t.Type == TokenType.Newline,
},
// var lucy_display = ""
// if not $"%hidenames".pressed:
// lucy_display = Steam.getLobbyData(lobby, "bbcode_lobby_name")
code_to_add = new Token[] {
new Token(TokenType.PrVar),
new IdentifierToken("lucy_display"),
new Token(TokenType.OpAssign),
new ConstantToken(new StringVariant("")),
new Token(TokenType.Newline, 2),
new Token(TokenType.CfIf),
new Token(TokenType.OpNot),
new Token(TokenType.Dollar),
new ConstantToken(new StringVariant("%hidenames")),
new Token(TokenType.Period),
new IdentifierToken("pressed"),
new Token(TokenType.Colon),
new Token(TokenType.Newline, 3),
new IdentifierToken("lucy_display"),
new Token(TokenType.OpAssign),
new IdentifierToken("Steam"),
new Token(TokenType.Period),
new IdentifierToken("getLobbyData"),
new Token(TokenType.ParenthesisOpen),
new IdentifierToken("lobby"),
new Token(TokenType.Comma),
new ConstantToken(new StringVariant("bbcode_lobby_name")),
new Token(TokenType.ParenthesisClose),
new Token(TokenType.Newline, 2)
}
},
new CodeChange {
name = "server button lucy_display arg",
// lobby_cap, lobby_age, dated, banned END
multitoken_prefix = new Func<Token, bool>[] {
t => t is IdentifierToken {Name: "lobby_cap"},
t => t.Type == TokenType.Comma,
t => t is IdentifierToken {Name: "lobby_age"},
t => t.Type == TokenType.Comma,
t => t is IdentifierToken {Name: "dated"},
t => t.Type == TokenType.Comma,
t => t is IdentifierToken {Name: "banned"},
},
// , lucy_display END
code_to_add = new Token[] {
new Token(TokenType.Comma),
new IdentifierToken("lucy_display"),
}
},
};
IEnumerable<Token> IScriptMod.Modify(string path, IEnumerable<Token> tokens)
{
var pending_changes = changes
.Select(c => (c, new MultiTokenWaiter(c.multitoken_prefix)))
.ToList();
// I'm sure there's a better way to do this
// with list comprehension stuff, but my
// C# is too rusty
foreach (var token in tokens) {
var had_change = false;
foreach (var (change, waiter) in pending_changes) {
if (waiter.Check(token)) {
Mod.ModInterface.Logger.Information($"Adding Lucy server button mod {change.name}");
yield return token;
foreach (var t in change.code_to_add) yield return t;
had_change = true;
break;
}
}
if (!had_change) yield return token;
}
}
}
public class LucysChatChanges : IScriptMod
{
bool IScriptMod.ShouldRun(string path) => path == "res://Scenes/HUD/playerhud.gdc";
CodeChange[] changes = {
new CodeChange {
name = "chat process intercept",
name = "save lit text",
// color.to_html()
//
// END
@ -227,25 +44,80 @@ public class LucysChatChanges : IScriptMod
t => t.Type == TokenType.Newline,
t => t.Type == TokenType.Newline,
},
// $"/root/LucyLucysTools".process_message(text, chat_local, player, self)
// return
// var lit_text = text
code_to_add = new Token[] {
new Token(TokenType.PrVar),
new IdentifierToken("lit_text"),
new Token(TokenType.OpAssign),
new IdentifierToken("text"),
new Token(TokenType.Newline, 1),
}
},
new CodeChange {
name = "chat bbcode",
// endcap + final_text + suffix
// END
multitoken_prefix = new Func<Token, bool>[] {
t => t is IdentifierToken {Name: "endcap"},
t => t.Type == TokenType.OpAdd,
t => t is IdentifierToken {Name: "final_text"},
t => t.Type == TokenType.OpAdd,
t => t is IdentifierToken {Name: "suffix"},
t => t.Type == TokenType.Newline,
},
// if $"/root/LucyLucysTools":
// var tmp = $"/root/LucyLucysTools".process_message(lit_text, final_text, prefix, suffix, endcap, username, spoken_text)
// final = tmp[0]
// spoken_text = tmp[1]
// END
code_to_add = new Token[] {
new Token(TokenType.CfIf),
new Token(TokenType.Dollar),
new ConstantToken(new StringVariant("/root/LucyLucysTools")),
new Token(TokenType.Colon),
new Token(TokenType.Newline, 2),
new Token(TokenType.PrVar),
new IdentifierToken("tmp"),
new Token(TokenType.OpAssign),
new Token(TokenType.Dollar),
new ConstantToken(new StringVariant("/root/LucyLucysTools")),
new Token(TokenType.Period),
new IdentifierToken("process_message"),
new Token(TokenType.ParenthesisOpen),
new IdentifierToken("text"),
new IdentifierToken("lit_text"),
new Token(TokenType.Comma),
new IdentifierToken("chat_local"),
new IdentifierToken("final_text"),
new Token(TokenType.Comma),
new IdentifierToken("player"),
new IdentifierToken("prefix"),
new Token(TokenType.Comma),
new Token(TokenType.Self),
new IdentifierToken("suffix"),
new Token(TokenType.Comma),
new IdentifierToken("endcap"),
new Token(TokenType.Comma),
new IdentifierToken("username"),
new Token(TokenType.Comma),
new IdentifierToken("final_color"),
new Token(TokenType.Comma),
new IdentifierToken("spoken_text"),
new Token(TokenType.ParenthesisClose),
new Token(TokenType.Newline, 1),
new Token(TokenType.Newline, 2),
new Token(TokenType.CfReturn),
new IdentifierToken("final"),
new Token(TokenType.OpAssign),
new IdentifierToken("tmp"),
new Token(TokenType.BracketOpen),
new ConstantToken(new IntVariant(0)),
new Token(TokenType.BracketClose),
new Token(TokenType.Newline, 2),
new IdentifierToken("spoken_text"),
new Token(TokenType.OpAssign),
new IdentifierToken("tmp"),
new Token(TokenType.BracketOpen),
new ConstantToken(new IntVariant(1)),
new Token(TokenType.BracketClose),
new Token(TokenType.Newline, 1),
}
},
@ -278,3 +150,688 @@ public class LucysChatChanges : IScriptMod
}
}
public class LucysNetFixes : IScriptMod {
bool IScriptMod.ShouldRun(string path) => path == "res://Scenes/Singletons/SteamNetwork.gdc";
CodeChange[] changes = {
new CodeChange {
name = "send_message channel 2",
// MESSAGE_ZONE, "zone_owner": PlayerData.player_saved_zone_owner}, "peers", 2)
multitoken_prefix = new Func<Token, bool>[] {
t => t is IdentifierToken {Name: "MESSAGE_ZONE"},
t => t.Type == TokenType.Comma,
t => t is ConstantToken {Value:StringVariant{Value: "zone_owner"}},
t => t.Type == TokenType.Colon,
t => t is IdentifierToken {Name: "PlayerData"},
t => t.Type == TokenType.Period,
t => t is IdentifierToken {Name: "player_saved_zone_owner"},
t => t.Type == TokenType.CurlyBracketClose,
t => t.Type == TokenType.Comma,
t => t is ConstantToken {Value:StringVariant{Value: "peers"}},
t => t.Type == TokenType.Comma,
t => t is ConstantToken {Value:IntVariant{Value: 2}},
},
// , 2 END
code_to_add = new Token[] {
new Token(TokenType.Comma),
new ConstantToken(new IntVariant(2)),
}
},
new CodeChange {
name = "instance_actor",
// "instance_actor":
// END
multitoken_prefix = new Func<Token, bool>[] {
t => t is ConstantToken {Value:StringVariant{Value: "instance_actor"}},
t => t.Type == TokenType.Colon,
t => t.Type == TokenType.Newline,
},
// LUCY_INSTANCE_SENDER = packet_sender
// END
code_to_add = new Token[] {
new IdentifierToken("LUCY_INSTANCE_SENDER"),
new Token(TokenType.OpAssign),
new IdentifierToken("packet_sender"),
new Token(TokenType.Newline, 4),
}
},
new CodeChange {
name = "kick",
// "kick":
// END
multitoken_prefix = new Func<Token, bool>[] {
t => t is ConstantToken {Value:StringVariant{Value: "kick"}},
t => t.Type == TokenType.Colon,
t => t.Type == TokenType.Newline
},
// if LUCY_LOG_MESSAGES: print("[KICK from", _get_username_from_id(packet_sender), " (", packet_sender, ")]")
// if GAME_MASTER: return
// if packet_sender != KNOWN_GAME_MASTER: return
// END
code_to_add = new Token[] {
new Token(TokenType.CfIf),
new IdentifierToken("LUCY_LOG_MESSAGES"),
new Token(TokenType.Colon),
new Token(TokenType.BuiltInFunc, (uint)BuiltinFunction.TextPrint),
new Token(TokenType.ParenthesisOpen),
new ConstantToken(new StringVariant("[KICK from ")),
new Token(TokenType.Comma),
new IdentifierToken("_get_username_from_id"),
new Token(TokenType.ParenthesisOpen),
new IdentifierToken("packet_sender"),
new Token(TokenType.ParenthesisClose),
new Token(TokenType.Comma),
new ConstantToken(new StringVariant(" (")),
new Token(TokenType.Comma),
new IdentifierToken("packet_sender"),
new Token(TokenType.Comma),
new ConstantToken(new StringVariant(")]")),
new Token(TokenType.ParenthesisClose),
new Token(TokenType.Newline, 4),
new Token(TokenType.CfIf),
new IdentifierToken("GAME_MASTER"),
new Token(TokenType.Colon),
new Token(TokenType.CfReturn),
new Token(TokenType.Newline, 4),
new Token(TokenType.CfIf),
new IdentifierToken("packet_sender"),
new Token(TokenType.OpNotEqual),
new IdentifierToken("KNOWN_GAME_MASTER"),
new Token(TokenType.Colon),
new Token(TokenType.CfReturn),
new Token(TokenType.Newline, 4),
}
},
new CodeChange {
name = "ban",
// "ban":
// END
multitoken_prefix = new Func<Token, bool>[] {
t => t is ConstantToken {Value:StringVariant{Value: "ban"}},
t => t.Type == TokenType.Colon,
t => t.Type == TokenType.Newline
},
// if LUCY_LOG_MESSAGES: print("[BAN from", _get_username_from_id(packet_sender), " (", packet_sender, ")]")
// if GAME_MASTER: return
// if packet_sender != KNOWN_GAME_MASTER: return
// END
code_to_add = new Token[] {
new Token(TokenType.CfIf),
new IdentifierToken("LUCY_LOG_MESSAGES"),
new Token(TokenType.Colon),
new Token(TokenType.BuiltInFunc, (uint)BuiltinFunction.TextPrint),
new Token(TokenType.ParenthesisOpen),
new ConstantToken(new StringVariant("[BAN from ")),
new Token(TokenType.Comma),
new IdentifierToken("_get_username_from_id"),
new Token(TokenType.ParenthesisOpen),
new IdentifierToken("packet_sender"),
new Token(TokenType.ParenthesisClose),
new Token(TokenType.Comma),
new ConstantToken(new StringVariant(" (")),
new Token(TokenType.Comma),
new IdentifierToken("packet_sender"),
new Token(TokenType.Comma),
new ConstantToken(new StringVariant(")]")),
new Token(TokenType.ParenthesisClose),
new Token(TokenType.Newline, 4),
new Token(TokenType.CfIf),
new IdentifierToken("GAME_MASTER"),
new Token(TokenType.Colon),
new Token(TokenType.CfReturn),
new Token(TokenType.Newline, 4),
new Token(TokenType.CfIf),
new IdentifierToken("packet_sender"),
new Token(TokenType.OpNotEqual),
new IdentifierToken("KNOWN_GAME_MASTER"),
new Token(TokenType.Colon),
new Token(TokenType.CfReturn),
new Token(TokenType.Newline, 4),
}
},
new CodeChange {
name = "punch",
// "player_punch":
// END
multitoken_prefix = new Func<Token, bool>[] {
t => t is ConstantToken {Value:StringVariant{Value: "player_punch"}},
t => t.Type == TokenType.Colon,
t => t.Type == TokenType.Newline
},
// if not DATA.has("nya"): LUCY_PUNCHED_ME = packet_sender
// END
code_to_add = new Token[] {
new Token(TokenType.CfIf),
new Token(TokenType.OpNot),
new IdentifierToken("DATA"),
new Token(TokenType.Period),
new IdentifierToken("has"),
new Token(TokenType.ParenthesisOpen),
new ConstantToken(new StringVariant("nya")),
new Token(TokenType.ParenthesisClose),
new Token(TokenType.Colon),
new IdentifierToken("LUCY_PUNCHED_ME"),
new Token(TokenType.OpAssign),
new IdentifierToken("packet_sender"),
new Token(TokenType.Newline,4),
}
},
new CodeChange {
name = "message",
// "message":
multitoken_prefix = new Func<Token, bool>[] {
t => t is ConstantToken {Value:StringVariant{Value: "message"}},
t => t.Type == TokenType.Colon,
t => t.Type == TokenType.Newline
},
// if LUCY_LOG_MESSAGES: print("[msg ", _get_username_from_id(packet_sender), "] ", DATA.message)
code_to_add = new Token[] {
new Token(TokenType.CfIf),
new IdentifierToken("LUCY_LOG_MESSAGES"),
new Token(TokenType.Colon),
new Token(TokenType.BuiltInFunc, (uint)BuiltinFunction.TextPrint),
new Token(TokenType.ParenthesisOpen),
new ConstantToken(new StringVariant("[msg ")),
new Token(TokenType.Comma),
new IdentifierToken("_get_username_from_id"),
new Token(TokenType.ParenthesisOpen),
new IdentifierToken("packet_sender"),
new Token(TokenType.ParenthesisClose),
new Token(TokenType.Comma),
new ConstantToken(new StringVariant(" (")),
new Token(TokenType.Comma),
new IdentifierToken("packet_sender"),
new Token(TokenType.Comma),
new ConstantToken(new StringVariant(")] ")),
new Token(TokenType.Comma),
new IdentifierToken("DATA"),
new Token(TokenType.Period),
new IdentifierToken("message"),
new Token(TokenType.ParenthesisClose),
new Token(TokenType.Newline, 4),
}
},
new CodeChange {
name = "_read_all_P2P_packets",
// func _read_all_P2P_packets(channel = 0 END
multitoken_prefix = new Func<Token, bool>[] {
t => t.Type == TokenType.PrFunction,
t => t is IdentifierToken {Name: "_read_all_P2P_packets"},
t => t.Type == TokenType.ParenthesisOpen,
t => t.Type == TokenType.Identifier,
t => t.Type == TokenType.OpAssign,
t => t.Type == TokenType.Constant,
},
// , limit = 64):
// var read_count = 0
// while Steam.getAvailableP2PPacketSize(channel) > 0 and read_count < limit:
// _read_P2P_Packet(channel)
// read_count += 1
// LUCY_PACKETS_READ += read_count
// func _old_read_all_P2P_packets(channel = 0 END
code_to_add = new Token[] {
new Token(TokenType.Comma),
new IdentifierToken("limit"),
new Token(TokenType.OpAssign),
new ConstantToken(new IntVariant(64)),
new Token(TokenType.ParenthesisClose),
new Token(TokenType.Colon),
new Token(TokenType.Newline, 1),
new Token(TokenType.PrVar),
new IdentifierToken("read_count"),
new Token(TokenType.OpAssign),
new ConstantToken(new IntVariant(0)),
new Token(TokenType.Newline, 1),
new Token(TokenType.CfWhile),
new IdentifierToken("Steam"),
new Token(TokenType.Period),
new IdentifierToken("getAvailableP2PPacketSize"),
new Token(TokenType.ParenthesisOpen),
new IdentifierToken("channel"),
new Token(TokenType.ParenthesisClose),
new Token(TokenType.OpGreater),
new ConstantToken(new IntVariant(0)),
new Token(TokenType.OpAnd),
new IdentifierToken("read_count"),
new Token(TokenType.OpLess),
new IdentifierToken("limit"),
new Token(TokenType.Colon),
new Token(TokenType.Newline, 2),
new IdentifierToken("_read_P2P_Packet"),
new Token(TokenType.ParenthesisOpen),
new IdentifierToken("channel"),
new Token(TokenType.ParenthesisClose),
new Token(TokenType.Newline, 2),
new IdentifierToken("read_count"),
new Token(TokenType.OpAssignAdd),
new ConstantToken(new IntVariant(1)),
new Token(TokenType.Newline, 1),
new IdentifierToken("LUCY_PACKETS_READ"),
new Token(TokenType.OpAssignAdd),
new IdentifierToken("read_count"),
new Token(TokenType.Newline, 0),
// Give old function new signature, it'll come after in token stream
new Token(TokenType.PrFunction),
new IdentifierToken("_old_read_all_P2P_packets"),
new Token(TokenType.ParenthesisOpen),
new IdentifierToken("channel"),
new Token(TokenType.OpAssign),
new ConstantToken(new IntVariant(0)),
}
},
new CodeChange {
name = "_process",
// func _process(delta):
// if not STEAM_ENABLED: return
// Steam.run_callbacks()
// if STEAM_LOBBY_ID > 0:
// END
multitoken_prefix = new Func<Token, bool>[] {
t => t.Type == TokenType.PrFunction,
t => t is IdentifierToken {Name: "_process"},
t => t.Type == TokenType.ParenthesisOpen,
t => t.Type == TokenType.Identifier,
t => t.Type == TokenType.ParenthesisClose,
t => t.Type == TokenType.Colon,
t => t.Type == TokenType.Newline,
t => t.Type == TokenType.CfIf,
t => t.Type == TokenType.OpNot,
t => t.Type == TokenType.Identifier,
t => t.Type == TokenType.Colon,
t => t.Type == TokenType.CfReturn,
t => t.Type == TokenType.Newline,
t => t.Type == TokenType.Identifier,
t => t.Type == TokenType.Period,
t => t.Type == TokenType.Identifier,
t => t.Type == TokenType.ParenthesisOpen,
t => t.Type == TokenType.ParenthesisClose,
t => t.Type == TokenType.Newline,
t => t.Type == TokenType.CfIf,
t => t.Type == TokenType.Identifier,
t => t.Type == TokenType.OpGreater,
t => t.Type == TokenType.Constant,
t => t.Type == TokenType.Colon,
t => t.Type == TokenType.Newline,
},
// for i in 3: _read_all_P2P_packets(i,LUCY_FRAME_PACKETS)
// return
// if false:
code_to_add = new Token[] {
new Token(TokenType.CfFor),
new IdentifierToken("i"),
new Token(TokenType.OpIn),
new ConstantToken(new IntVariant(3)),
new Token(TokenType.Colon),
new IdentifierToken("_read_all_P2P_packets"),
new Token(TokenType.ParenthesisOpen),
new IdentifierToken("i"),
new Token(TokenType.Comma),
new IdentifierToken("LUCY_FRAME_PACKETS"),
new Token(TokenType.ParenthesisClose),
new Token(TokenType.Newline, 1),
new Token(TokenType.CfReturn),
new Token(TokenType.Newline, 1),
new Token(TokenType.CfIf),
new ConstantToken(new BoolVariant(false)),
new Token(TokenType.Colon),
new Token(TokenType.Newline, 2),
}
},
new CodeChange {
name = "_physics_process",
// func _physics_process(delta):
// if not STEAM_ENABLED: return
// END
multitoken_prefix = new Func<Token, bool>[] {
t => t.Type == TokenType.PrFunction,
t => t is IdentifierToken {Name: "_physics_process"},
t => t.Type == TokenType.ParenthesisOpen,
t => t.Type == TokenType.Identifier,
t => t.Type == TokenType.ParenthesisClose,
t => t.Type == TokenType.Colon,
t => t.Type == TokenType.Newline,
t => t.Type == TokenType.CfIf,
t => t.Type == TokenType.OpNot,
t => t.Type == TokenType.Identifier,
t => t.Type == TokenType.Colon,
t => t.Type == TokenType.CfReturn,
t => t.Type == TokenType.Newline,
},
// var do_print = false
// BULK_PACKET_READ_TIMER -= delta
// if BULK_PACKET_READ_TIMER <= 0:
// print("Bulk Reading Packets.")
// for i in 3: _read_all_P2P_packets(i,LUCY_BULK_PACKETS)
// BULK_PACKET_READ_TIMER = LUCY_BULK_INTERVAL
// do_print = true
// LUCY_BULK_FULL_TIMER -= delta
// if LUCY_BULK_FULL_TIMER <= 0:
// print("Reading all packets.")
// for i in 3: _read_all_P2P_packets(i,1000000)
// LUCY_BULK_FULL_TIMER = LUCY_BULK_FULL_INTERVAL
// do_print = true
// if do_print:
// print("PACKETS ", LUCY_PACKETS_READ)
// LUCY_PACKETS_READ = 0
// return
code_to_add = new Token[] {
// var do_print = false
// BULK_PACKET_READ_TIMER -= delta
// if BULK_PACKET_READ_TIMER <= 0:
// print("Bulk Reading Packets.")
// for i in 3: _read_all_P2P_packets(i,LUCY_BULK_PACKETS)
// BULK_PACKET_READ_TIMER = LUCY_BULK_INTERVAL
// do_print = true
new Token(TokenType.PrVar),
new IdentifierToken("do_print"),
new Token(TokenType.OpAssign),
new ConstantToken(new BoolVariant(false)),
new Token(TokenType.Newline, 1),
new IdentifierToken("BULK_PACKET_READ_TIMER"),
new Token(TokenType.OpAssignSub),
new IdentifierToken("delta"),
new Token(TokenType.Newline, 1),
new Token(TokenType.CfIf),
new IdentifierToken("BULK_PACKET_READ_TIMER"),
new Token(TokenType.OpLessEqual),
new ConstantToken(new IntVariant(0)),
new Token(TokenType.Colon),
new Token(TokenType.Newline, 2),
new Token(TokenType.BuiltInFunc, (uint)BuiltinFunction.TextPrint),
new Token(TokenType.ParenthesisOpen),
new ConstantToken(new StringVariant("Bulk Reading Packets.")),
new Token(TokenType.ParenthesisClose),
new Token(TokenType.Newline, 2),
new Token(TokenType.CfFor),
new IdentifierToken("i"),
new Token(TokenType.OpIn),
new ConstantToken(new IntVariant(3)),
new Token(TokenType.Colon),
new IdentifierToken("_read_all_P2P_packets"),
new Token(TokenType.ParenthesisOpen),
new IdentifierToken("i"),
new Token(TokenType.Comma),
new IdentifierToken("LUCY_BULK_PACKETS"),
new Token(TokenType.ParenthesisClose),
new Token(TokenType.Newline, 2),
new IdentifierToken("BULK_PACKET_READ_TIMER"),
new Token(TokenType.OpAssign),
new IdentifierToken("LUCY_BULK_INTERVAL"),
new Token(TokenType.Newline, 2),
new IdentifierToken("do_print"),
new Token(TokenType.OpAssign),
new ConstantToken(new BoolVariant(true)),
new Token(TokenType.Newline, 1),
// LUCY_BULK_FULL_TIMER -= delta
// if LUCY_BULK_FULL_TIMER <= 0:
// print("Reading all packets.")
// for i in 3: _read_all_P2P_packets(i,1000000)
// LUCY_BULK_FULL_TIMER = LUCY_BULK_FULL_INTERVAL
// do_print = true
new IdentifierToken("LUCY_BULK_FULL_TIMER"),
new Token(TokenType.OpAssignSub),
new IdentifierToken("delta"),
new Token(TokenType.Newline, 1),
new Token(TokenType.CfIf),
new IdentifierToken("LUCY_BULK_FULL_TIMER"),
new Token(TokenType.OpLessEqual),
new ConstantToken(new IntVariant(0)),
new Token(TokenType.Colon),
new Token(TokenType.Newline, 2),
new Token(TokenType.BuiltInFunc, (uint)BuiltinFunction.TextPrint),
new Token(TokenType.ParenthesisOpen),
new ConstantToken(new StringVariant("Reading all packets.")),
new Token(TokenType.ParenthesisClose),
new Token(TokenType.Newline, 2),
new Token(TokenType.CfFor),
new IdentifierToken("i"),
new Token(TokenType.OpIn),
new ConstantToken(new IntVariant(3)),
new Token(TokenType.Colon),
new IdentifierToken("_read_all_P2P_packets"),
new Token(TokenType.ParenthesisOpen),
new IdentifierToken("i"),
new Token(TokenType.Comma),
new ConstantToken(new IntVariant(1000000)),
new Token(TokenType.ParenthesisClose),
new Token(TokenType.Newline, 2),
new IdentifierToken("LUCY_BULK_FULL_TIMER"),
new Token(TokenType.OpAssign),
new IdentifierToken("LUCY_BULK_FULL_INTERVAL"),
new Token(TokenType.Newline, 2),
new IdentifierToken("do_print"),
new Token(TokenType.OpAssign),
new ConstantToken(new BoolVariant(true)),
new Token(TokenType.Newline, 1),
// if do_print:
// print("PACKETS ", LUCY_PACKETS_READ)
// LUCY_PACKETS_READ = 0
new Token(TokenType.CfIf),
new IdentifierToken("do_print"),
new Token(TokenType.Colon),
new Token(TokenType.Newline, 2),
new Token(TokenType.BuiltInFunc, (uint)BuiltinFunction.TextPrint),
new Token(TokenType.ParenthesisOpen),
new ConstantToken(new StringVariant("PACKETS ")),
new Token(TokenType.Comma),
new IdentifierToken("LUCY_PACKETS_READ"),
new Token(TokenType.ParenthesisClose),
new Token(TokenType.Newline, 2),
new IdentifierToken("LUCY_PACKETS_READ"),
new Token(TokenType.OpAssign),
new ConstantToken(new IntVariant(0)),
new Token(TokenType.Newline, 1),
// return
new Token(TokenType.CfReturn),
new Token(TokenType.Newline, 1),
}
},
new CodeChange {
name = "new globals",
// var REPLICATIONS_RECIEVED = []
// END
multitoken_prefix = new Func<Token, bool>[] {
t => t.Type == TokenType.PrVar,
t => t is IdentifierToken {Name: "REPLICATIONS_RECIEVED"},
t => t.Type == TokenType.OpAssign,
t => t.Type == TokenType.BracketOpen,
t => t.Type == TokenType.BracketClose,
t => t.Type == TokenType.Newline,
},
// var LUCY_PACKETS_READ = 0
// var LUCY_BULK_FULL_TIMER = 0
// var LUCY_FRAME_PACKETS = 32
// var LUCY_BULK_PACKETS = 128
// var LUCY_BULK_INTERVAL = 0.8
// var LUCY_BULK_FULL_INTERVAL = 6.4
// var LUCY_SRV_NAME = ""
// var LUCY_PUNCHED_ME = 0
// var LUCY_INSTANCE_SENDER = 0
// var LUCY_LOG_MESSAGES = false
// END
code_to_add = new Token[] {
new Token(TokenType.PrVar),
new IdentifierToken("LUCY_PACKETS_READ"),
new Token(TokenType.OpAssign),
new ConstantToken(new IntVariant(0)),
new Token(TokenType.Newline, 0),
new Token(TokenType.PrVar),
new IdentifierToken("LUCY_BULK_FULL_TIMER"),
new Token(TokenType.OpAssign),
new ConstantToken(new IntVariant(0)),
new Token(TokenType.Newline, 0),
new Token(TokenType.PrVar),
new IdentifierToken("LUCY_FRAME_PACKETS"),
new Token(TokenType.OpAssign),
new ConstantToken(new IntVariant(32)),
new Token(TokenType.Newline, 0),
new Token(TokenType.PrVar),
new IdentifierToken("LUCY_BULK_PACKETS"),
new Token(TokenType.OpAssign),
new ConstantToken(new IntVariant(128)),
new Token(TokenType.Newline, 0),
new Token(TokenType.PrVar),
new IdentifierToken("LUCY_BULK_INTERVAL"),
new Token(TokenType.OpAssign),
new ConstantToken(new RealVariant(0.8)),
new Token(TokenType.Newline, 0),
new Token(TokenType.PrVar),
new IdentifierToken("LUCY_BULK_FULL_INTERVAL"),
new Token(TokenType.OpAssign),
new ConstantToken(new RealVariant(6.4)),
new Token(TokenType.Newline, 0),
new Token(TokenType.PrVar),
new IdentifierToken("LUCY_SRV_NAME"),
new Token(TokenType.OpAssign),
new ConstantToken(new StringVariant("")),
new Token(TokenType.Newline, 0),
new Token(TokenType.PrVar),
new IdentifierToken("LUCY_PUNCHED_ME"),
new Token(TokenType.OpAssign),
new ConstantToken(new IntVariant(0)),
new Token(TokenType.Newline, 0),
new Token(TokenType.PrVar),
new IdentifierToken("LUCY_INSTANCE_SENDER"),
new Token(TokenType.OpAssign),
new ConstantToken(new IntVariant(0)),
new Token(TokenType.Newline, 0),
new Token(TokenType.PrVar),
new IdentifierToken("LUCY_LOG_MESSAGES"),
new Token(TokenType.OpAssign),
new ConstantToken(new BoolVariant(false)),
new Token(TokenType.Newline, 0),
}
},
new CodeChange {
name = "packet sender",
// if PACKET.empty():
// print("Error! Empty Packet!")
// END
multitoken_prefix = new Func<Token, bool>[] {
t => t is IdentifierToken {Name: "PACKET"},
t => t.Type == TokenType.Period,
t => t is IdentifierToken {Name: "empty"},
t => t.Type == TokenType.ParenthesisOpen,
t => t.Type == TokenType.ParenthesisClose,
t => t.Type == TokenType.Colon,
t => t.Type == TokenType.Newline,
t => t.Type == TokenType.BuiltInFunc,
t => t.Type == TokenType.ParenthesisOpen,
t => t.Type == TokenType.Constant,
t => t.Type == TokenType.ParenthesisClose,
t => t.Type == TokenType.Newline,
},
// var packet_sender = PACKET['steam_id_remote']
// END
code_to_add = new Token[] {
new Token(TokenType.PrVar),
new IdentifierToken("packet_sender"),
new Token(TokenType.OpAssign),
new IdentifierToken("PACKET"),
new Token(TokenType.BracketOpen),
new ConstantToken(new StringVariant("steam_id_remote")),
new Token(TokenType.BracketClose),
new Token(TokenType.Newline, 2),
}
},
new CodeChange {
name = "set lobby name",
// Steam.setLobbyData(lobby_id, "name", str(STEAM_USERNAME) END
multitoken_prefix = new Func<Token, bool>[] {
t => t is IdentifierToken {Name: "setLobbyData"},
t => t.Type == TokenType.ParenthesisOpen,
t => t is IdentifierToken {Name: "lobby_id"},
t => t.Type == TokenType.Comma,
t => t.Type == TokenType.Constant,
t => t.Type == TokenType.Comma,
t => t.Type == TokenType.BuiltInFunc,
t => t.Type == TokenType.ParenthesisOpen,
t => t is IdentifierToken {Name: "STEAM_USERNAME"},
t => t.Type == TokenType.ParenthesisClose,
},
// if LUCY_SRV_NAME == "" else LUCY_SRV_NAME END
code_to_add = new Token[] {
new Token(TokenType.CfIf),
new IdentifierToken("LUCY_SRV_NAME"),
new Token(TokenType.OpEqual),
new ConstantToken(new StringVariant("")),
new Token(TokenType.CfElse),
new IdentifierToken("LUCY_SRV_NAME"),
}
},
};
IEnumerable<Token> IScriptMod.Modify(string path, IEnumerable<Token> tokens)
{
var pending_changes = changes
.Select(c => (c, new MultiTokenWaiter(c.multitoken_prefix)))
.ToList();
// I'm sure there's a better way to do this
// with list comprehension stuff, but my
// C# is too rusty
foreach (var token in tokens) {
var had_change = false;
foreach (var (change, waiter) in pending_changes) {
if (waiter.Check(token)) {
Mod.ModInterface.Logger.Information($"Adding Lucy Network mod {change.name}");
yield return token;
foreach (var t in change.code_to_add) yield return t;
had_change = true;
break;
}
}
if (!had_change) yield return token;
}
}
}

View File

@ -1,6 +1,5 @@
{
"Id": "Lucy.LucysTools",
"AssemblyPath": "LucysTools.dll",
"PackPath": "LucysTools.pck",
"Dependencies": [ "LucysLib" ]
"PackPath": "LucysTools.pck"
}

View File

@ -3,31 +3,34 @@ LucysTools
Uses GDWeave.
Client Features:
- Makes the client (tunably) read all packets. This fixes chat messages dropping.
- Optionally knocks people back when they punch you.
- Lets you clear gamechat
- Allows custom name color (for all users)
- Allows custom name BBCode (for compatible peers)
- Allows custom text color (for compatible peers)
- Allows BBCode in chat (for compatible peers)
- Sends messages on P2P channel 2 (This should make your messages more reliable for users who don't have LucysTools)
- Only the game host can kick/ban you
- Allows custom name bbcode (and/or custom color)
- Allows some BBCode in chat: [b], [i], [u], [s], [color] Make sure to close your tags!
Host Features:
- Lets you set a message that will be sent when someone joins.
- Lets you spawn rainclouds, voids, & meteors.
- As host 'raw' messages can be sent with a % prefix
- Lets you set a custom server name with BBCode (for compatible peers)
- Lets you set a custom lobby code
- Lets you update lobby name & code while running
- Lets you set a custom server name and message that will be sent when someone joins.
- Lets you spawn rainclouds & meteors.
- Lets you enable intrusive BBCode ([rainbow], [tornado], [shake], [wave], [font]) in messages. If enabled, other players on the server can use these too. (Not secure or anything, implemented client side)
- If intrusive BBCode is enabled, 'raw' messages can be sent with a % prefix
Info for Modders:
- Check out LucysLib (in progress)
- If you'd like to make things compatible, servers get a "bbcode_lobby_name" property, and messages have additional "bb_msg" and "bb_user" fields. DM me!
Log Features:
- If you enable "log_messages" in the config file, messages, kicks, and bans will be logged to godot.log along with the user who sent the packet.
More coming soon!
Probably certainly full of bugs.
Packet options:
- 'Per Frame Packets' is the number of net packets your client will attempt to read per frame.
- 'Bulk Read Packets' is the number of net packets your client will attempt to read per 'Bulk Read Interval' (in seconds)
- 'Full Read Interval' is how often your client will attempt to read *all* net packets (in seconds).
Compatibility:
- Works *only* with WEBFISHING 1.10
- Works *only* with WEBFISHING 1.08
- I haven't tested any other mods with this, but I'm happy to try to make things compatible, submit a bug report with the incompatible mod! (Only mods that have source available)
Bugs:
- Make sure your versions of LucysTools & LucysLib are the latest release before submitting bug reports, please.
- Make sure your version of LucysTools is the latest release before submitting bug reports, please.