update: 更新到godot4.4.1,并大量重构代码
This commit is contained in:
7
.gitignore
vendored
7
.gitignore
vendored
@ -16,13 +16,14 @@ data_*/
|
||||
mono_crash.*.json
|
||||
|
||||
# MyProject specific ignores
|
||||
.*/
|
||||
.vscode/
|
||||
.vs/
|
||||
android/
|
||||
Bin/
|
||||
bin/
|
||||
*.aseprite
|
||||
*.csproj
|
||||
*.csproj.old
|
||||
*.sln
|
||||
*.error
|
||||
*.key*
|
||||
@ -34,3 +35,7 @@ bin/
|
||||
# Test files
|
||||
Test/bin
|
||||
Test/obj
|
||||
|
||||
# temp ignores
|
||||
Lang/*
|
||||
*.zip
|
||||
|
File diff suppressed because one or more lines are too long
@ -1,4 +1,4 @@
|
||||
<Project Sdk="Godot.NET.Sdk/4.4.0">
|
||||
<Project Sdk="Godot.NET.Sdk/4.4.1">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<EnableDynamicLoading>true</EnableDynamicLoading>
|
||||
@ -7,5 +7,16 @@
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Remove="Test\**\*" />
|
||||
<Protobuf Include="Protos\chess.proto" GrpcServices="Client" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Google.Protobuf" Version="3.30.2" />
|
||||
<PackageReference Include="Grpc.Net.Client" Version="2.70.0" />
|
||||
<PackageReference Include="Grpc.Tools" Version="2.71.0">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="KeraLua" Version="1.4.5" />
|
||||
<PackageReference Include="NLua" Version="1.7.5" />
|
||||
</ItemGroup>
|
||||
</Project>
|
16
Main.cs
16
Main.cs
@ -29,7 +29,7 @@ public partial class Main : Node2D
|
||||
// }
|
||||
|
||||
// Called when the node enters the scene tree for the first time.
|
||||
Global global = null;
|
||||
GlobalManager global = null!;
|
||||
public override void _Ready() {
|
||||
// GetTree().Connect("screen_resized", ResizeChessboardToFitScreen);
|
||||
// Button undo = GetNode<Button>("Undo");
|
||||
@ -40,9 +40,9 @@ public partial class Main : Node2D
|
||||
// ChessBoard board1 = GetChild<ChessBoard>(0);
|
||||
// board.Visible = false;
|
||||
// board.Can
|
||||
global = GetNode<Global>("/root/Global");
|
||||
global = GlobalManager.Instance;
|
||||
global.GlobalTheme = GetChild<Control>(GetChildCount() - 1).Theme;
|
||||
global.ConfigFlush();
|
||||
global.GlobalThemeConfigFlush();
|
||||
}
|
||||
|
||||
// Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
@ -51,16 +51,20 @@ public partial class Main : Node2D
|
||||
|
||||
private void GoToSignlePlayer() {
|
||||
// global.GotoScene("res://Scenes/SinglePlayer.tscn");
|
||||
global.GotoScene("res://Scenes/ChessGame.tscn");
|
||||
global?.GotoScene("res://Scenes/ChessGame.tscn");
|
||||
}
|
||||
|
||||
private void GoToMultiPlayer() {
|
||||
// global.GotoScene("res://Scenes/MultiPlayer.tscn");
|
||||
global.GotoScene("res://Scenes/GameLobby.tscn");
|
||||
global?.GotoScene("res://Scenes/GameLobby.tscn");
|
||||
}
|
||||
|
||||
private void GoToSetting() {
|
||||
global.GotoScene("res://Scenes/Setting.tscn");
|
||||
global?.GotoScene("res://Scenes/Setting.tscn");
|
||||
}
|
||||
|
||||
private void GotoMods() {
|
||||
global?.GotoScene("res://Scenes/Mods.tscn");
|
||||
}
|
||||
|
||||
// private void goToMenu() {
|
||||
|
78
Main.tscn
78
Main.tscn
@ -6,46 +6,54 @@
|
||||
[node name="Main" type="Node2D"]
|
||||
script = ExtResource("1_h4cv2")
|
||||
|
||||
[node name="Control" type="Control" parent="."]
|
||||
layout_mode = 3
|
||||
anchors_preset = 0
|
||||
[node name="CenterContainer" type="CenterContainer" parent="."]
|
||||
offset_right = 720.0
|
||||
offset_bottom = 1280.0
|
||||
theme = ExtResource("2_afihr")
|
||||
|
||||
[node name="SignlePlayer" type="Button" parent="Control"]
|
||||
layout_mode = 0
|
||||
offset_left = 83.0
|
||||
offset_top = 671.0
|
||||
offset_right = 298.0
|
||||
offset_bottom = 850.0
|
||||
text = "单人"
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="CenterContainer"]
|
||||
custom_minimum_size = Vector2(720, 720)
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 30
|
||||
|
||||
[node name="MultiPlayer" type="Button" parent="Control"]
|
||||
layout_mode = 0
|
||||
offset_left = 406.0
|
||||
offset_top = 670.0
|
||||
offset_right = 612.0
|
||||
offset_bottom = 852.0
|
||||
text = "多人"
|
||||
|
||||
[node name="Label" type="Label" parent="Control"]
|
||||
layout_mode = 0
|
||||
offset_left = 191.0
|
||||
offset_top = 265.0
|
||||
offset_right = 501.0
|
||||
offset_bottom = 451.0
|
||||
[node name="Label" type="Label" parent="CenterContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 6
|
||||
theme_override_font_sizes/font_size = 48
|
||||
text = "中国象棋"
|
||||
text = "KEY_ChessGame"
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
|
||||
[node name="Setting" type="Button" parent="Control"]
|
||||
layout_mode = 0
|
||||
offset_left = 239.0
|
||||
offset_top = 967.0
|
||||
offset_right = 450.0
|
||||
offset_bottom = 1150.0
|
||||
text = "设置"
|
||||
[node name="MarginContainer" type="MarginContainer" parent="CenterContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/margin_left = 30
|
||||
theme_override_constants/margin_right = 30
|
||||
|
||||
[connection signal="pressed" from="Control/SignlePlayer" to="." method="GoToSignlePlayer"]
|
||||
[connection signal="pressed" from="Control/MultiPlayer" to="." method="GoToMultiPlayer"]
|
||||
[connection signal="pressed" from="Control/Setting" to="." method="GoToSetting"]
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="CenterContainer/VBoxContainer/MarginContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="CenterContainer/VBoxContainer/MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="SignlePlayer" type="Button" parent="CenterContainer/VBoxContainer/MarginContainer/VBoxContainer/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "KEY_SinglePlayer"
|
||||
|
||||
[node name="MultiPlayer" type="Button" parent="CenterContainer/VBoxContainer/MarginContainer/VBoxContainer/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "KEY_MultiPlayer"
|
||||
|
||||
[node name="Setting" type="Button" parent="CenterContainer/VBoxContainer/MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "KEY_Setting"
|
||||
|
||||
[node name="Mod" type="Button" parent="CenterContainer/VBoxContainer/MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "KEY_Mode"
|
||||
|
||||
[connection signal="pressed" from="CenterContainer/VBoxContainer/MarginContainer/VBoxContainer/HBoxContainer/SignlePlayer" to="." method="GoToSignlePlayer"]
|
||||
[connection signal="pressed" from="CenterContainer/VBoxContainer/MarginContainer/VBoxContainer/HBoxContainer/MultiPlayer" to="." method="GoToMultiPlayer"]
|
||||
[connection signal="pressed" from="CenterContainer/VBoxContainer/MarginContainer/VBoxContainer/Setting" to="." method="GoToSetting"]
|
||||
[connection signal="pressed" from="CenterContainer/VBoxContainer/MarginContainer/VBoxContainer/Mod" to="." method="GotoMods"]
|
||||
|
@ -38,7 +38,7 @@ size_flags_horizontal = 3
|
||||
|
||||
[node name="Home" type="Button" parent="Control/VBoxContainer/MarginContainer/HBoxContainer/MarginContainer"]
|
||||
layout_mode = 2
|
||||
text = "返回主页"
|
||||
text = "KEY_BackHome"
|
||||
|
||||
[node name="MarginContainer2" type="MarginContainer" parent="Control/VBoxContainer/MarginContainer/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
@ -47,7 +47,7 @@ size_flags_horizontal = 3
|
||||
[node name="Undo" type="Button" parent="Control/VBoxContainer/MarginContainer/HBoxContainer/MarginContainer2"]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 4
|
||||
text = "撤回"
|
||||
text = "KEY_GameUndo"
|
||||
|
||||
[node name="MarginContainer3" type="MarginContainer" parent="Control/VBoxContainer/MarginContainer/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
@ -55,7 +55,7 @@ size_flags_horizontal = 3
|
||||
|
||||
[node name="ReInit" type="Button" parent="Control/VBoxContainer/MarginContainer/HBoxContainer/MarginContainer3"]
|
||||
layout_mode = 2
|
||||
text = "重开"
|
||||
text = "KEY_GameReInit"
|
||||
|
||||
[node name="MarginContainer3" type="MarginContainer" parent="Control/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
@ -65,8 +65,7 @@ layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="Control/VBoxContainer/MarginContainer3/HFlowContainer"]
|
||||
layout_mode = 2
|
||||
text = "You Are
|
||||
"
|
||||
text = "KEY_Content_YouAre"
|
||||
|
||||
[node name="LineEdit" type="LineEdit" parent="Control/VBoxContainer/MarginContainer3/HFlowContainer"]
|
||||
layout_mode = 2
|
||||
@ -75,7 +74,7 @@ editable = false
|
||||
|
||||
[node name="Label2" type="Label" parent="Control/VBoxContainer/MarginContainer3/HFlowContainer"]
|
||||
layout_mode = 2
|
||||
text = "Turns On"
|
||||
text = "KEY_Content_TurnOn"
|
||||
|
||||
[node name="LineEdit2" type="LineEdit" parent="Control/VBoxContainer/MarginContainer3/HFlowContainer"]
|
||||
layout_mode = 2
|
||||
@ -94,8 +93,7 @@ grow_vertical = 0
|
||||
|
||||
[node name="Over" type="Button" parent="Control/MarginContainer2"]
|
||||
layout_mode = 2
|
||||
text = "结束回合
|
||||
(提示对方结束)"
|
||||
text = "KEY_OverThisTurn"
|
||||
|
||||
[connection signal="pressed" from="Control/VBoxContainer/MarginContainer/HBoxContainer/MarginContainer/Home" to="." method="GoHome"]
|
||||
[connection signal="pressed" from="Control/VBoxContainer/MarginContainer/HBoxContainer/MarginContainer2/Undo" to="." method="Undo"]
|
||||
|
@ -10,7 +10,7 @@ metadata/_edit_use_anchors_ = true
|
||||
[node name="Label" type="Label" parent="."]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 0
|
||||
text = "Server Status"
|
||||
text = "KEY_ServerConnectStatus"
|
||||
|
||||
[node name="ColorRect" type="ColorRect" parent="."]
|
||||
custom_minimum_size = Vector2(15, 15)
|
||||
|
@ -29,8 +29,7 @@ layout_mode = 2
|
||||
|
||||
[node name="Button" type="Button" parent="MarginContainer/VBoxContainer/MarginContainer"]
|
||||
layout_mode = 2
|
||||
text = "Back
|
||||
"
|
||||
text = "KEY_BackHome"
|
||||
|
||||
[node name="MarginContainer2" type="HFlowContainer" parent="MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
@ -40,7 +39,7 @@ layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/MarginContainer2/MarginContainer"]
|
||||
layout_mode = 2
|
||||
text = "Connect States"
|
||||
text = "KEY_ServerConnectStatus"
|
||||
|
||||
[node name="MarginContainer2" type="MarginContainer" parent="MarginContainer/VBoxContainer/MarginContainer2"]
|
||||
layout_mode = 2
|
||||
|
23
Scenes/Mods.tscn
Normal file
23
Scenes/Mods.tscn
Normal file
@ -0,0 +1,23 @@
|
||||
[gd_scene load_steps=3 format=3 uid="uid://c2ov83uk7r6rq"]
|
||||
|
||||
[ext_resource type="Theme" uid="uid://intlbeu8h82r" path="res://Asserts/defaultTheme.tres" id="1_mhtia"]
|
||||
[ext_resource type="Script" uid="uid://c8t8d8e7inajy" path="res://Scripts/Controllers/Mods.cs" id="1_mnyng"]
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer"]
|
||||
offset_right = 720.0
|
||||
offset_bottom = 1280.0
|
||||
theme = ExtResource("1_mhtia")
|
||||
theme_override_constants/margin_left = 30
|
||||
theme_override_constants/margin_top = 30
|
||||
theme_override_constants/margin_right = 30
|
||||
theme_override_constants/margin_bottom = 30
|
||||
script = ExtResource("1_mnyng")
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="."]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Button" type="Button" parent="VBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "back"
|
||||
|
||||
[connection signal="pressed" from="VBoxContainer/Button" to="." method="OnBack"]
|
@ -1,9 +1,11 @@
|
||||
[gd_scene load_steps=4 format=3 uid="uid://c6gxufppw1fu3"]
|
||||
[gd_scene load_steps=5 format=3 uid="uid://c6gxufppw1fu3"]
|
||||
|
||||
[ext_resource type="Theme" uid="uid://intlbeu8h82r" path="res://Asserts/defaultTheme.tres" id="1_6yfoi"]
|
||||
[ext_resource type="Script" uid="uid://71ril3nh84rw" path="res://Scripts/Controllers/Setting.cs" id="1_xbvb3"]
|
||||
[ext_resource type="PackedScene" uid="uid://pc83bstfltn" path="res://Scenes/Entities/ServerStatus.tscn" id="3_e50hu"]
|
||||
|
||||
[sub_resource type="ButtonGroup" id="ButtonGroup_efio3"]
|
||||
|
||||
[node name="Setting" type="MarginContainer"]
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
@ -21,14 +23,21 @@ layout_mode = 2
|
||||
|
||||
[node name="Back" type="Button" parent="BoxContainer/MarginContainer"]
|
||||
layout_mode = 2
|
||||
text = "Back"
|
||||
text = "KEY_BackHome"
|
||||
|
||||
[node name="MarginContainer7" type="MarginContainer" parent="BoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Button" type="Button" parent="BoxContainer/MarginContainer7"]
|
||||
layout_mode = 2
|
||||
text = "Save"
|
||||
text = "KEY_SaveConfigFile"
|
||||
|
||||
[node name="MarginContainer9" type="MarginContainer" parent="BoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Button" type="Button" parent="BoxContainer/MarginContainer9"]
|
||||
layout_mode = 2
|
||||
text = "KEY_GetConfigDir"
|
||||
|
||||
[node name="MarginContainer2" type="MarginContainer" parent="BoxContainer"]
|
||||
layout_mode = 2
|
||||
@ -38,7 +47,7 @@ layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="BoxContainer/MarginContainer2/Server"]
|
||||
layout_mode = 2
|
||||
text = "Server IP"
|
||||
text = "KEY_ServerIP"
|
||||
|
||||
[node name="LineEdit" type="LineEdit" parent="BoxContainer/MarginContainer2/Server"]
|
||||
layout_mode = 2
|
||||
@ -52,7 +61,7 @@ layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="BoxContainer/MarginContainer3/Name"]
|
||||
layout_mode = 2
|
||||
text = "Name"
|
||||
text = "KEY_UserName"
|
||||
|
||||
[node name="LineEdit" type="LineEdit" parent="BoxContainer/MarginContainer3/Name"]
|
||||
layout_mode = 2
|
||||
@ -86,7 +95,7 @@ layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="BoxContainer/MarginContainer5/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "Font Size"
|
||||
text = "KEY_GlobalFontSize"
|
||||
|
||||
[node name="FontSize" type="LineEdit" parent="BoxContainer/MarginContainer5/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
@ -103,6 +112,30 @@ min_value = 10.0
|
||||
max_value = 50.0
|
||||
value = 10.0
|
||||
|
||||
[node name="HBoxContainer2" type="HFlowContainer" parent="BoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="BoxContainer/HBoxContainer2"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="Button" type="Button" parent="BoxContainer/HBoxContainer2/MarginContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
toggle_mode = true
|
||||
button_group = SubResource("ButtonGroup_efio3")
|
||||
text = "简体中文"
|
||||
|
||||
[node name="MarginContainer2" type="MarginContainer" parent="BoxContainer/HBoxContainer2"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="Button2" type="Button" parent="BoxContainer/HBoxContainer2/MarginContainer2"]
|
||||
layout_mode = 2
|
||||
toggle_mode = true
|
||||
button_group = SubResource("ButtonGroup_efio3")
|
||||
text = "English"
|
||||
|
||||
[node name="HBoxContainer" type="HFlowContainer" parent="BoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
@ -161,9 +194,12 @@ text = "Trace Color"
|
||||
|
||||
[connection signal="pressed" from="BoxContainer/MarginContainer/Back" to="." method="OnBack"]
|
||||
[connection signal="pressed" from="BoxContainer/MarginContainer7/Button" to="." method="OnSave"]
|
||||
[connection signal="pressed" from="BoxContainer/MarginContainer9/Button" to="." method="OnGetSettingsFile"]
|
||||
[connection signal="text_changed" from="BoxContainer/MarginContainer2/Server/LineEdit" to="." method="OnServerUrlChanged"]
|
||||
[connection signal="text_changed" from="BoxContainer/MarginContainer3/Name/LineEdit" to="." method="OnNameChanged"]
|
||||
[connection signal="value_changed" from="BoxContainer/MarginContainer6/FontSizeBar" to="." method="OnFontSizeChanged"]
|
||||
[connection signal="toggled" from="BoxContainer/HBoxContainer2/MarginContainer/Button" to="." method="ChangeLangZHCN"]
|
||||
[connection signal="toggled" from="BoxContainer/HBoxContainer2/MarginContainer2/Button2" to="." method="ChangeLangEN"]
|
||||
[connection signal="pressed" from="BoxContainer/HBoxContainer/MarginContainer2/Button2" to="." method="OnClearUserData"]
|
||||
[connection signal="pressed" from="BoxContainer/HFlowContainer/Button" to="." method="OnGetCacheDir"]
|
||||
[connection signal="pressed" from="BoxContainer/HFlowContainer/Button2" to="." method="OnGetConfigDir"]
|
||||
|
@ -5,7 +5,7 @@ using ChineseChess;
|
||||
|
||||
public partial class ChessGame : Node2D {
|
||||
ChessBoard board;
|
||||
Global global;
|
||||
GlobalManager global = GlobalManager.Instance;
|
||||
ConfirmationDialog dialog;
|
||||
private bool isSession = false;
|
||||
ChessCore Game;
|
||||
@ -15,15 +15,17 @@ public partial class ChessGame : Node2D {
|
||||
// Called when the node enters the scene tree for the first time.
|
||||
public override void _Ready() {
|
||||
// Init.Call();
|
||||
global = GetNode<Global>("/root/Global");
|
||||
board = GetNode<ChessBoard>("Chessboard");
|
||||
isSession = global.RPClient.IsOnline();
|
||||
// ChessGameAPI api = new();
|
||||
// api.BindToLua(global.ModManager.lua);
|
||||
|
||||
// isSession = global.RPClient.IsOnline();
|
||||
|
||||
GetNode<LineEdit>("Control/VBoxContainer/MarginContainer3/HFlowContainer/LineEdit")
|
||||
.Text = global.GlobalData["player_color"].AsString();
|
||||
LineEdit turnSideEdit = GetNode<LineEdit>("Control/VBoxContainer/MarginContainer3/HFlowContainer/LineEdit2");
|
||||
turnSideEdit.Text = "red";
|
||||
GD.Print("ChessGame uid:", global.RPClient.GetUserId(), " color:",global.GlobalData["player_color"]);
|
||||
// GD.Print("ChessGame uid:", global.RPClient.GetUserId(), " color:",global.GlobalData["player_color"]);
|
||||
|
||||
dialog = new ConfirmationDialog {
|
||||
DialogAutowrap = true,
|
||||
@ -52,12 +54,12 @@ public partial class ChessGame : Node2D {
|
||||
Vector.Vector2I vector = new(posX, posY);
|
||||
if (isSession) {
|
||||
Game.OnPosClicked(vector, ChessCore.PlayerSideType.Self);
|
||||
var res = global.RPClient.SendSessionToAll(global.sessionId, new Dictionary {
|
||||
{"type", "mouseClicked"},
|
||||
{"X", pos.X},
|
||||
{"Y", pos.Y},
|
||||
{"id", global.RPClient.GetUserId()}
|
||||
});
|
||||
// var res = global.RPClient.SendSessionToAll(global.sessionId, new Dictionary {
|
||||
// {"type", "mouseClicked"},
|
||||
// {"X", pos.X},
|
||||
// {"Y", pos.Y},
|
||||
// {"id", global.RPClient.GetUserId()}
|
||||
// });
|
||||
} else {
|
||||
Game.OnPosClicked(vector);
|
||||
}
|
||||
@ -66,13 +68,13 @@ public partial class ChessGame : Node2D {
|
||||
if (isSession) {
|
||||
GD.Print("ws is connected");
|
||||
|
||||
global.RPClient.OnPRCSessionExit += (cmd, code) => {
|
||||
GoHome();
|
||||
};
|
||||
// global.RPClient.OnPRCSessionExit += (cmd, code) => {
|
||||
// GoHome();
|
||||
// };
|
||||
|
||||
global.RPClient.OnPRCSessionRecv += (msg) => {
|
||||
SessionMsgHandle(msg["msg"].AsGodotDictionary());
|
||||
};
|
||||
// global.RPClient.OnPRCSessionRecv += (msg) => {
|
||||
// SessionMsgHandle(msg["msg"].AsGodotDictionary());
|
||||
// };
|
||||
}
|
||||
}
|
||||
|
||||
@ -80,50 +82,50 @@ public partial class ChessGame : Node2D {
|
||||
public override void _Process(double delta) {
|
||||
}
|
||||
|
||||
private void SessionMsgHandle(Dictionary msg) {
|
||||
GD.PrintErr($"session msg: {msg}");
|
||||
switch (msg["type"].AsString()) {
|
||||
case "over":
|
||||
if (global.RPClient.GetUserId() == msg["id"].AsString()) {
|
||||
break;
|
||||
}
|
||||
dialog.Title = "Opponent Finished";
|
||||
dialog.DialogText = "Turn On You\n";
|
||||
dialog.Visible = true;
|
||||
break;
|
||||
case "mouseClicked":
|
||||
if (msg["id"].ToString() == global.RPClient.GetUserId()) {
|
||||
break;
|
||||
}
|
||||
Vector2 mouseClicked = new(GD.StrToVar(msg["X"].ToString()).AsInt32(),
|
||||
GD.StrToVar(msg["Y"].ToString()).AsInt32());
|
||||
Vector.Vector2I vector = new((int)mouseClicked.X, (int)mouseClicked.Y);
|
||||
Game.OnPosClicked(vector, ChessCore.PlayerSideType.Opponent);
|
||||
break;
|
||||
case "undo":
|
||||
Game.Undo();
|
||||
break;
|
||||
case "reInit":
|
||||
Game.ReInit();
|
||||
break;
|
||||
}
|
||||
}
|
||||
// private void SessionMsgHandle(Dictionary msg) {
|
||||
// GD.PrintErr($"session msg: {msg}");
|
||||
// switch (msg["type"].AsString()) {
|
||||
// case "over":
|
||||
// if (global.RPClient.GetUserId() == msg["id"].AsString()) {
|
||||
// break;
|
||||
// }
|
||||
// dialog.Title = "Opponent Finished";
|
||||
// dialog.DialogText = "Turn On You\n";
|
||||
// dialog.Visible = true;
|
||||
// break;
|
||||
// case "mouseClicked":
|
||||
// if (msg["id"].ToString() == global.RPClient.GetUserId()) {
|
||||
// break;
|
||||
// }
|
||||
// Vector2 mouseClicked = new(GD.StrToVar(msg["X"].ToString()).AsInt32(),
|
||||
// GD.StrToVar(msg["Y"].ToString()).AsInt32());
|
||||
// Vector.Vector2I vector = new((int)mouseClicked.X, (int)mouseClicked.Y);
|
||||
// Game.OnPosClicked(vector, ChessCore.PlayerSideType.Opponent);
|
||||
// break;
|
||||
// case "undo":
|
||||
// Game.Undo();
|
||||
// break;
|
||||
// case "reInit":
|
||||
// Game.ReInit();
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
private void BtnOver() {
|
||||
GD.Print($"BtnOver {isSession}");
|
||||
if (isSession == false) {
|
||||
return;
|
||||
}
|
||||
global.RPClient.SendSessionToAll(global.sessionId, new Dictionary{
|
||||
{"type", "over"},
|
||||
{"id", global.RPClient.GetUserId()},
|
||||
});
|
||||
// global.RPClient.SendSessionToAll(global.sessionId, new Dictionary{
|
||||
// {"type", "over"},
|
||||
// {"id", global.RPClient.GetUserId()},
|
||||
// });
|
||||
}
|
||||
|
||||
public void GoHome() {
|
||||
if (global.RPClient.IsOnline()) {
|
||||
global.RPClient.ExitServer();
|
||||
}
|
||||
// if (global.RPClient.IsOnline()) {
|
||||
// global.RPClient.ExitServer();
|
||||
// }
|
||||
global.GotoScene("res://Main.tscn");
|
||||
}
|
||||
|
||||
@ -131,10 +133,10 @@ public partial class ChessGame : Node2D {
|
||||
GD.Print($"Undo {isSession}");
|
||||
|
||||
if (isSession) {
|
||||
global.RPClient.SendSessionToAll(global.sessionId, new Dictionary{
|
||||
{"type", "undo"},
|
||||
{"id", global.RPClient.GetUserId()},
|
||||
});
|
||||
// global.RPClient.SendSessionToAll(global.sessionId, new Dictionary{
|
||||
// {"type", "undo"},
|
||||
// {"id", global.RPClient.GetUserId()},
|
||||
// });
|
||||
} else {
|
||||
if (Game.board.Steps == 0) board.Clear();
|
||||
Game.Undo();
|
||||
@ -145,9 +147,9 @@ public partial class ChessGame : Node2D {
|
||||
GD.PrintErr($"ReInit {isSession}");
|
||||
|
||||
if (isSession) {
|
||||
global.RPClient.SendSessionToAll(global.sessionId, new Dictionary{
|
||||
{"type", "reInit"},
|
||||
});
|
||||
// global.RPClient.SendSessionToAll(global.sessionId, new Dictionary{
|
||||
// {"type", "reInit"},
|
||||
// });
|
||||
} else {
|
||||
Game.ReInit();
|
||||
board.Clear();
|
||||
|
@ -3,7 +3,7 @@ using Godot;
|
||||
using Godot.Collections;
|
||||
|
||||
public partial class GameLobby : Control {
|
||||
Global global = null;
|
||||
GlobalManager global = GlobalManager.Instance;
|
||||
Timer timer = null;
|
||||
|
||||
ItemList lists = null;
|
||||
@ -15,32 +15,31 @@ public partial class GameLobby : Control {
|
||||
|
||||
// Called when the node enters the scene tree for the first time.
|
||||
public override void _Ready() {
|
||||
global = GetNode<Global>("/root/Global");
|
||||
lists = GetNode<ItemList>("MarginContainer/VBoxContainer/MarginContainer3/ItemList");
|
||||
dialog = GetNode<ConfirmationDialog>("Dialogs/ConfirmationDialog");
|
||||
URL = global.GlobalConfigDict["server_url"].AsString();
|
||||
userName = global.GlobalConfigDict["user_name"].AsString();
|
||||
URL = global.ConfigManager.GetValue<string>("server_url");
|
||||
userName = global.ConfigManager.GetValue<string>("user_name");
|
||||
|
||||
dialog.MinSize = new Vector2I(400, 200);
|
||||
dialog.DialogAutowrap = true;
|
||||
dialog.Canceled += () => {
|
||||
if (dialog.Title == "Session Created")
|
||||
global.RPClient.SessionAckCreate(dialog.GetMeta("sessionId").ToString(), false);
|
||||
// if (dialog.Title == "Session Created")
|
||||
// global.RPClient.SessionAckCreate(dialog.GetMeta("sessionId").ToString(), false);
|
||||
};
|
||||
dialog.Confirmed += () => {
|
||||
if (dialog.Title == "Session Created") {
|
||||
// FIXME
|
||||
isAcceptedPart = true;
|
||||
global.RPClient.SessionAckCreate(dialog.GetMeta("sessionId").ToString(), true);
|
||||
// global.RPClient.SessionAckCreate(dialog.GetMeta("sessionId").ToString(), true);
|
||||
}
|
||||
};
|
||||
|
||||
global.RPClient.OnOpen += (string eventName, object[] args) => {
|
||||
global.RPClient.UserInit(userName, "godot chessboard", () => {
|
||||
global.RPClient.UserRename(userName);
|
||||
return global.RPClient.RegionAdd("server");
|
||||
});
|
||||
};
|
||||
// global.RPClient.OnOpen += (eventName, args) => {
|
||||
// global.RPClient.UserInit(userName, "godot chessboard", () => {
|
||||
// global.RPClient.UserRename(userName);
|
||||
// return global.RPClient.RegionAdd("server");
|
||||
// });
|
||||
// };
|
||||
// global.RPClient.OnOpen += (eventName, args) => {
|
||||
// global.RPClient.UserInit(userName, "none", () => {
|
||||
// GD.PrintErr($"User Init Success");
|
||||
@ -49,59 +48,59 @@ public partial class GameLobby : Control {
|
||||
// });
|
||||
// // global.RPClient.UserRename(userName);
|
||||
// };
|
||||
global.RPClient.RegSessionAckCreateCallback((sessionId, res, reqUserId, reqUserName) => {
|
||||
if (reqUserId != null) {
|
||||
dialog.Title = "Session Created";
|
||||
dialog.SetMeta("reqUserName", reqUserName);
|
||||
dialog.SetMeta("reqUserId", reqUserId);
|
||||
dialog.SetMeta("sessionId", sessionId);
|
||||
// dialog.GetLabel==>Text = $"{sessdata["reqUserName"]}";
|
||||
dialog.DialogText = $"username: {reqUserName}\n" +
|
||||
$"reqUserId: {reqUserId}\n";
|
||||
dialog.Visible = true;
|
||||
} else {
|
||||
if (res) {
|
||||
// TODO FIXME
|
||||
global.sessionId = sessionId;
|
||||
if (!isAcceptedPart) {
|
||||
global.GlobalData["player_color"] = "red";
|
||||
} else {
|
||||
global.GlobalData["player_color"] = "black";
|
||||
}
|
||||
// GD.PrintErr("sessionId: ", reqUserId, "color: ", global.GlobalData["player_color"].AsString());
|
||||
global.GotoScene("res://Scenes/ChessGame.tscn");
|
||||
} else {
|
||||
dialog.Title = "Failed";
|
||||
dialog.DialogText = $"session create failed";
|
||||
dialog.Visible = true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
// global.RPClient.RegSessionAckCreateCallback((sessionId, res, reqUserId, reqUserName) => {
|
||||
// if (reqUserId != null) {
|
||||
// dialog.Title = "Session Created";
|
||||
// dialog.SetMeta("reqUserName", reqUserName);
|
||||
// dialog.SetMeta("reqUserId", reqUserId);
|
||||
// dialog.SetMeta("sessionId", sessionId);
|
||||
// // dialog.GetLabel==>Text = $"{sessdata["reqUserName"]}";
|
||||
// dialog.DialogText = $"username: {reqUserName}\n" +
|
||||
// $"reqUserId: {reqUserId}\n";
|
||||
// dialog.Visible = true;
|
||||
// } else {
|
||||
// if (res) {
|
||||
// // TODO FIXME
|
||||
// global.sessionId = sessionId;
|
||||
// if (!isAcceptedPart) {
|
||||
// global.GlobalData["player_color"] = "red";
|
||||
// } else {
|
||||
// global.GlobalData["player_color"] = "black";
|
||||
// }
|
||||
// // GD.PrintErr("sessionId: ", reqUserId, "color: ", global.GlobalData["player_color"].AsString());
|
||||
// global.GotoScene("res://Scenes/ChessGame.tscn");
|
||||
// } else {
|
||||
// dialog.Title = "Failed";
|
||||
// dialog.DialogText = $"session create failed";
|
||||
// dialog.Visible = true;
|
||||
// }
|
||||
// }
|
||||
// return true;
|
||||
// });
|
||||
|
||||
timer = new Timer();
|
||||
AddChild(timer);
|
||||
// timer = new Timer();
|
||||
// AddChild(timer);
|
||||
ColorRect colorRect = GetNode<ColorRect>("MarginContainer/VBoxContainer/MarginContainer2/MarginContainer2/ColorRect");
|
||||
timer.Connect("timeout", Callable.From(() => {
|
||||
if (global.RPClient.GetIsConnected()) {
|
||||
colorRect.Color = Colors.Green;
|
||||
} else {
|
||||
colorRect.Color = Colors.Red;
|
||||
}
|
||||
FlushData();
|
||||
}));
|
||||
timer.Start(1);
|
||||
// timer.Connect("timeout", Callable.From(() => {
|
||||
// if (global.RPClient.GetIsConnected()) {
|
||||
// colorRect.Color = Colors.Green;
|
||||
// } else {
|
||||
// colorRect.Color = Colors.Red;
|
||||
// }
|
||||
// FlushData();
|
||||
// }));
|
||||
// timer.Start(1);
|
||||
|
||||
Connect();
|
||||
}
|
||||
|
||||
public void Connect() {
|
||||
GD.Print("Connect");
|
||||
if (global.RPClient.GetIsConnected()) {
|
||||
return;
|
||||
}
|
||||
// if (global.RPClient.GetIsConnected()) {
|
||||
// return;
|
||||
// }
|
||||
// global.RPClient.ExitServer();
|
||||
global.RPClient.ConnectToUrlEx(URL);
|
||||
// global.RPClient.ConnectToUrlEx(URL);
|
||||
global.SetProcess(true);
|
||||
}
|
||||
|
||||
@ -109,33 +108,33 @@ public partial class GameLobby : Control {
|
||||
Dictionary item = lists.GetItemMetadata(index).AsGodotDictionary();
|
||||
GD.Print($"Item {index} selected, {item}");
|
||||
string[] strings = { item["id"].ToString() };
|
||||
global.RPClient.SessionCreate(strings);
|
||||
// global.RPClient.SessionCreate(strings);
|
||||
}
|
||||
|
||||
private void FlushData() {
|
||||
global.RPClient.RegionInspect("server", (data) => {
|
||||
// GD.Print(data);
|
||||
lists?.Clear();
|
||||
foreach (Dictionary<string, string> user in data) {
|
||||
string userId = user["id"].ToString();
|
||||
string userName = user["name"].ToString();
|
||||
if (userId == global.RPClient.GetUserId()) {
|
||||
lists.SetItemDisabled(
|
||||
lists.AddItem($"Name: {userName}"),
|
||||
true);
|
||||
continue;
|
||||
}
|
||||
var idx = lists.AddItem($"Name: {userName}");
|
||||
lists.SetItemMetadata(idx, user);
|
||||
lists.SetItemTooltip(idx, $"User ID: {userId}");
|
||||
}
|
||||
return true;
|
||||
});
|
||||
// global.RPClient.RegionInspect("server", (data) => {
|
||||
// // GD.Print(data);
|
||||
// lists?.Clear();
|
||||
// foreach (Dictionary<string, string> user in data) {
|
||||
// string userId = user["id"].ToString();
|
||||
// string userName = user["name"].ToString();
|
||||
// if (userId == global.RPClient.GetUserId()) {
|
||||
// lists.SetItemDisabled(
|
||||
// lists.AddItem($"Name: {userName}"),
|
||||
// true);
|
||||
// continue;
|
||||
// }
|
||||
// var idx = lists.AddItem($"Name: {userName}");
|
||||
// lists.SetItemMetadata(idx, user);
|
||||
// lists.SetItemTooltip(idx, $"User ID: {userId}");
|
||||
// }
|
||||
// return true;
|
||||
// });
|
||||
}
|
||||
|
||||
|
||||
private void OnBack() {
|
||||
global.RPClient.ExitServer();
|
||||
// global.RPClient.ExitServer();
|
||||
global.GotoScene("res://Main.tscn");
|
||||
}
|
||||
}
|
||||
|
30
Scripts/Controllers/Mods.cs
Normal file
30
Scripts/Controllers/Mods.cs
Normal file
@ -0,0 +1,30 @@
|
||||
using Godot;
|
||||
using System;
|
||||
|
||||
public partial class Mods : Control {
|
||||
GlobalManager global = GlobalManager.Instance;
|
||||
public override void _Ready() {
|
||||
// RunDemo();
|
||||
|
||||
// ModManager modManager = new();
|
||||
// modManager.RegistryFunc("OnInit", () => { GD.Print("OnInit"); }, true);
|
||||
// modManager.RegistryFunc("foo", () => { GD.Print("Hello"); });
|
||||
// LuaMod mod = new(ProjectSettings.GlobalizePath("res://Protos/test.lua"));
|
||||
// mod.BindFunc(modManager);
|
||||
// try {
|
||||
// modManager.InvokeFunc<Action>("OnInit");
|
||||
// }
|
||||
// catch (System.Exception e) {
|
||||
// GD.PrintErr("OnInit error: ", e.Message, e.StackTrace);
|
||||
// }
|
||||
}
|
||||
|
||||
public void OnOpenModFileDir() {
|
||||
OS.ShellOpen(global.ConfigManager.GetValue<string>("mods_fpath") ?? "user://Mods/");
|
||||
}
|
||||
|
||||
public void OnBack() {
|
||||
ArgumentNullException.ThrowIfNull(global);
|
||||
global.GotoScene("res://Main.tscn");
|
||||
}
|
||||
}
|
1
Scripts/Controllers/Mods.cs.uid
Normal file
1
Scripts/Controllers/Mods.cs.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://c8t8d8e7inajy
|
@ -1,35 +1,32 @@
|
||||
using Godot;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
public partial class Setting : Control
|
||||
{
|
||||
Global global;
|
||||
public partial class Setting : Control {
|
||||
private GlobalManager global = GlobalManager.Instance;
|
||||
private IConfigManager config = GlobalManager.Instance.ConfigManager;
|
||||
int font_size;
|
||||
LineEdit fontOut;
|
||||
private LineEdit fontOut = null!;
|
||||
|
||||
// Called when the node enters the scene tree for the first time.
|
||||
public override void _Ready()
|
||||
{
|
||||
global = GetNode<Global>("/root/Global");
|
||||
public override void _Ready() {
|
||||
fontOut = GetNode<LineEdit>("BoxContainer/MarginContainer5/HBoxContainer/FontSize");
|
||||
font_size = (int)global.GlobalConfigDict["font_size"];
|
||||
font_size = config.GetValue<int>("font_size");
|
||||
GetNode<HSlider>("BoxContainer/MarginContainer6/FontSizeBar")
|
||||
.Value = font_size;
|
||||
fontOut.Text = font_size.ToString();
|
||||
|
||||
FillingData();
|
||||
}
|
||||
private void FillingData()
|
||||
{
|
||||
private void FillingData() {
|
||||
GetNode<LineEdit>("BoxContainer/MarginContainer2/Server/LineEdit")
|
||||
.Text = global.GlobalConfigDict["server_url"].ToString();
|
||||
.Text = config.GetValue<string>("server_url");
|
||||
GetNode<LineEdit>("BoxContainer/MarginContainer3/Name/LineEdit")
|
||||
.Text = global.GlobalConfigDict["user_name"].ToString();
|
||||
.Text = config.GetValue<string>("user_name");
|
||||
}
|
||||
|
||||
// Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
public override void _Process(double delta)
|
||||
{
|
||||
public override void _Process(double delta) {
|
||||
}
|
||||
|
||||
private void OnBack() {
|
||||
@ -41,23 +38,20 @@ public partial class Setting : Control
|
||||
// OS.Alert("Saved", "Setting");
|
||||
}
|
||||
|
||||
void OnNameChanged(string Value)
|
||||
{
|
||||
global.GlobalConfigDict["user_name"] = Value;
|
||||
// global.ConfigFlush();
|
||||
void OnNameChanged(string Value) {
|
||||
config.SetValue("user_name", Value);
|
||||
// config.GetValue<>Flush();
|
||||
}
|
||||
|
||||
private void OnServerUrlChanged(string Value)
|
||||
{
|
||||
global.GlobalConfigDict["server_url"] = Value;
|
||||
// global.ConfigFlush();
|
||||
private void OnServerUrlChanged(string Value) {
|
||||
config.SetValue("server_url", Value);
|
||||
// config.GetValue<>Flush();
|
||||
}
|
||||
|
||||
private void OnFontSizeChanged(float Value)
|
||||
{
|
||||
private void OnFontSizeChanged(float Value) {
|
||||
font_size = (int)Value;
|
||||
global.GlobalConfigDict["font_size"] = font_size;
|
||||
global.ConfigFlush();
|
||||
config.SetValue("font_size", font_size);
|
||||
global.GlobalThemeConfigFlush();
|
||||
fontOut.Text = font_size.ToString();
|
||||
}
|
||||
|
||||
@ -77,6 +71,11 @@ public partial class Setting : Control
|
||||
}
|
||||
}
|
||||
|
||||
private static void OnGetSettingsFile() {
|
||||
string path = ProjectSettings.GlobalizePath(GlobalManager.ConfigPath);
|
||||
OS.ShellOpen(Path.GetDirectoryName(path));
|
||||
}
|
||||
|
||||
private static void OnGetCacheDir() {
|
||||
OS.Alert(OS.GetCacheDir(), "Cache Dir");
|
||||
}
|
||||
@ -92,4 +91,7 @@ public partial class Setting : Control
|
||||
private static void OnGetUserDataDir() {
|
||||
OS.Alert(OS.GetUserDataDir(), "User Data Dir");
|
||||
}
|
||||
|
||||
private static void ChangeLangZHCN(bool _) => TranslationServer.SetLocale("zh_CN");
|
||||
private static void ChangeLangEN(bool _) => TranslationServer.SetLocale("en");
|
||||
}
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Chesspiece.cs
|
||||
using Godot;
|
||||
using ChineseChess;
|
||||
using System.Linq;
|
||||
using System;
|
||||
|
||||
using static IPiece;
|
||||
public partial class ChessPiece : Sprite2D, IPieceOn {
|
||||
|
@ -1 +0,0 @@
|
||||
uid://dd84v12101t1n
|
@ -1,49 +1,69 @@
|
||||
#nullable disable
|
||||
using System.Collections.Generic;
|
||||
using Godot;
|
||||
using RPPackage;
|
||||
|
||||
public partial class Global : Node {
|
||||
public RPClientEDWS RPClient = new();
|
||||
public string sessionId;
|
||||
public Node CurrentScene { get; set; }
|
||||
public Theme GlobalTheme = null;
|
||||
public partial class GlobalManager : Node {
|
||||
public static GlobalManager Instance { get; private set; } = null!;
|
||||
public static string ConfigPath { get; private set; } = "user://config.json";
|
||||
private GlobalManager() {
|
||||
ConfigManager.SetFilePath(ProjectSettings.GlobalizePath(ConfigPath));
|
||||
ConfigManager.SetDefault(_default_config);
|
||||
ConfigManager.LoadFromFile();
|
||||
GD.Print("GameSystem Singleton Initialized");
|
||||
}
|
||||
|
||||
readonly GodotConfigManager GlobalConfig = new("user://config.cfg");
|
||||
public Dictionary<string, Variant> GlobalConfigDict = new() {
|
||||
// TODO Will Change It
|
||||
public readonly IConfigManager ConfigManager = new JsonConfigManager();
|
||||
private static readonly Dictionary<string, object> _default_config = new() {
|
||||
{"font_size", 20},
|
||||
{"server_url", "wss://game.zzyxyz.com/"},
|
||||
{"user_name", "undefined"}
|
||||
{"user_name", "undefined"},
|
||||
|
||||
{"mods_fpath", "user://Mods/"},
|
||||
{"mods_allowed", false},
|
||||
};
|
||||
|
||||
public string sessionId = "";
|
||||
public Node CurrentScene { get; set; } = null!;
|
||||
public Theme GlobalTheme = null!;
|
||||
|
||||
// readonly GodotConfigManager GlobalConfig = new("user://config.cfg");
|
||||
|
||||
// TODO will remove this
|
||||
public Dictionary<string, Variant> GlobalData = new() {
|
||||
{"player_color", "red"},
|
||||
};
|
||||
|
||||
// Called when the node enters the scene tree for the first time.
|
||||
public override void _Ready() {
|
||||
if (Instance == null) {
|
||||
Instance = this;
|
||||
}
|
||||
else {
|
||||
GD.PushError("GlobalManager already exists");
|
||||
QueueFree();
|
||||
}
|
||||
|
||||
if (OS.GetName() == "Android") {
|
||||
bool ret = OS.RequestPermissions();
|
||||
GD.Print($"RequestPermissions ret is {ret}");
|
||||
}
|
||||
|
||||
// OS.RequestPermissions();
|
||||
RPClient.OnRPCError += (string errCode, string type, string cmd, string errMsg) => {
|
||||
GD.PrintErr($"errCode {errCode}, type/cmd {type}/{cmd}, errMsg {errMsg}");
|
||||
};
|
||||
RPClient.OnClose += (string eventName, object[] args) => {
|
||||
SetProcess(false);
|
||||
};
|
||||
// RPClient.OnRPCError += (errCode, type, cmd, errMsg) => {
|
||||
// GD.PrintErr($"errCode {errCode}, type/cmd {type}/{cmd}, errMsg {errMsg}");
|
||||
// };
|
||||
// RPClient.OnClose += (eventName, args) => {
|
||||
// SetProcess(false);
|
||||
// };
|
||||
|
||||
Viewport root = GetTree().Root;
|
||||
CurrentScene = root.GetChild(root.GetChildCount() - 1);
|
||||
|
||||
GlobalConfig.LoadConfig("Global", GlobalConfigDict);
|
||||
SetProcess(false);
|
||||
}
|
||||
|
||||
public void ConfigFlush() {
|
||||
int font_size = (int)GlobalConfigDict["font_size"];
|
||||
public void GlobalThemeConfigFlush() {
|
||||
int font_size = ConfigManager.GetValue<int>("font_size");
|
||||
GlobalTheme.DefaultFontSize = font_size;
|
||||
// GlobalTheme?.SetFontSize("font_size", "Label", font_size);
|
||||
// GlobalTheme?.SetFontSize("font_size", "Button", font_size);
|
||||
@ -53,29 +73,30 @@ public partial class Global : Node {
|
||||
}
|
||||
|
||||
private void OnGotoScene() {
|
||||
ConfigFlush();
|
||||
GlobalThemeConfigFlush();
|
||||
}
|
||||
|
||||
public void SaveConfig() {
|
||||
GlobalConfig.SaveConfig("Global", GlobalConfigDict);
|
||||
ConfigManager.SaveToFile();
|
||||
// GlobalConfig.SaveConfig("Global", _conf_dict);
|
||||
}
|
||||
|
||||
// Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
public override void _Process(double delta) {
|
||||
RPClient.PollEx(delta);
|
||||
// RPClient.PollEx(delta);
|
||||
}
|
||||
|
||||
public override void _Notification(int what) {
|
||||
if (what == NotificationWMCloseRequest) {
|
||||
// SaveConfig();
|
||||
RPClient.Close();
|
||||
// RPClient.Close();
|
||||
GetTree().Quit(); // default behavior
|
||||
}
|
||||
}
|
||||
|
||||
public delegate void ChangeSceneCallback(Node newSence);
|
||||
private static ChangeSceneCallback changeSceneCallback = null;
|
||||
public void GotoScene(string path, ChangeSceneCallback callback = null) {
|
||||
private static ChangeSceneCallback? changeSceneCallback = null;
|
||||
public void GotoScene(string path, ChangeSceneCallback? callback = null) {
|
||||
// This function will usually be called from a signal callback,
|
||||
// or some other function from the current scene.
|
||||
// Deleting the current scene at this point is
|
1
Scripts/GlobalManager.cs.uid
Normal file
1
Scripts/GlobalManager.cs.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://gfwgyu7p8hoi
|
@ -1,328 +0,0 @@
|
||||
using Godot;
|
||||
using Godot.Collections;
|
||||
|
||||
namespace RPPackage {
|
||||
public partial class RPClientBaseEDWS : EventDrivenWebSocket {
|
||||
|
||||
public delegate void RPClientEventHandler(string cmd, Dictionary? data);
|
||||
public delegate void RPClientErrorHandler(string errCode, string type, string cmd, string errMsg);
|
||||
|
||||
public event RPClientEventHandler? OnRPCUser;
|
||||
public event RPClientEventHandler? OnRPCRegion;
|
||||
public event RPClientEventHandler? OnRPCSession;
|
||||
public event RPClientEventHandler? OnRPCMsg;
|
||||
public event RPClientErrorHandler? OnRPCError;
|
||||
|
||||
public RPClientBaseEDWS() : base() {
|
||||
OnText += (text) => {
|
||||
// GD.Print($"response: {text}");
|
||||
RPMessage? msg = RPHelper.HandleIncomingMessage(text);
|
||||
if (msg == null) {
|
||||
MakeRPCError("9999", "Unknown Msg", "Error", null);
|
||||
return;
|
||||
}
|
||||
if (msg.Code != "0000") {
|
||||
OnRPCError?.Invoke(msg.Code ?? "9999", msg.Type, msg.Cmd,
|
||||
msg.Data?.ToString() ?? "");
|
||||
return;
|
||||
}
|
||||
switch (msg.Type) {
|
||||
case "user":
|
||||
OnRPCUser?.Invoke(msg.Cmd, msg.Data);
|
||||
break;
|
||||
case "region":
|
||||
OnRPCRegion?.Invoke(msg.Cmd, msg.Data);
|
||||
break;
|
||||
case "session":
|
||||
OnRPCSession?.Invoke(msg.Cmd, msg.Data);
|
||||
break;
|
||||
case "msg":
|
||||
OnRPCMsg?.Invoke(msg.Cmd, msg.Data);
|
||||
break;
|
||||
default:
|
||||
MakeRPCError(msg.Code, "unknown", msg.Cmd, msg.Data?.ToString());
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected void MakeRPCError(string errCode, string type, string cmd, string? errMsg) {
|
||||
OnRPCError?.Invoke(errCode, type, cmd, errMsg ?? "null");
|
||||
}
|
||||
}
|
||||
|
||||
public partial class RPClientEDWS : RPClientBaseEDWS {
|
||||
string? userName;
|
||||
string? userId;
|
||||
string? userToken;
|
||||
string? regionId;
|
||||
|
||||
public string? GetUserId() { return userId; }
|
||||
|
||||
public delegate void SessionRecvHandle(Dictionary? msg);
|
||||
public event SessionRecvHandle? OnPRCSessionRecv;
|
||||
|
||||
public event RPClientEventHandler? OnPRCSessionExit;
|
||||
|
||||
public RPClientEDWS() : base() {
|
||||
OnRPCUser += (cmd, msg) => {
|
||||
if (msg == null) {
|
||||
MakeRPCError("0000", "User", "unknown", "unknown");
|
||||
return;
|
||||
}
|
||||
switch (cmd) {
|
||||
case "init":
|
||||
userId = msg["userId"].AsString();
|
||||
userToken = msg["token"].AsString();
|
||||
_userInitCallback?.Invoke();
|
||||
break;
|
||||
case "rename":
|
||||
userName = msg["_"].AsString();
|
||||
break;
|
||||
default:
|
||||
MakeRPCError("0000", "user", "unknown", msg?.ToString());
|
||||
break;
|
||||
}
|
||||
};
|
||||
OnRPCRegion += (cmd, msg) => {
|
||||
switch (cmd) {
|
||||
case "add":
|
||||
break;
|
||||
case "inspect":
|
||||
// var regions = msg["_"].AsGodotArray<Dictionary>();
|
||||
_regionRecvCallback?.Invoke(cmd, msg);
|
||||
break;
|
||||
case "list":
|
||||
// var users = msg["_"].AsGodotArray<Dictionary>();
|
||||
_regionRecvCallback?.Invoke(cmd, msg);
|
||||
break;
|
||||
default:
|
||||
MakeRPCError("0000", "region", "unknown", msg?.ToString());
|
||||
break;
|
||||
}
|
||||
};
|
||||
OnRPCSession += (cmd, msg) => {
|
||||
switch (cmd) {
|
||||
case "sendAll":
|
||||
OnPRCSessionRecv?.Invoke(msg);
|
||||
break;
|
||||
case "create":
|
||||
break;
|
||||
case "ackCreate":
|
||||
// GD.PrintErr($"{cmd} {msg} {__SessionAckCreateCallback__ == null}");
|
||||
_sessionAckCreateCallback?.Invoke(cmd, msg);
|
||||
break;
|
||||
case "exit":
|
||||
OnPRCSessionExit?.Invoke(cmd, msg);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
OnRPCMsg += (cmd, msg) => {
|
||||
switch(cmd) {
|
||||
case "echo":
|
||||
GD.Print(msg?["_"].AsString());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
OnRPCError += (code, type, cmd, msg) => {
|
||||
};
|
||||
}
|
||||
|
||||
public static void ClearRPCClientFunc() {
|
||||
|
||||
}
|
||||
|
||||
public bool IsOnline() {
|
||||
return GetIsConnected() && userId != null;
|
||||
}
|
||||
|
||||
public static void ConnectServer(string url) {
|
||||
|
||||
}
|
||||
|
||||
public void ExitServer() {
|
||||
this.SendRPMessage(new RPMessage {
|
||||
Type = "user",
|
||||
Cmd = "exit",
|
||||
Uid = userId,
|
||||
Token = userToken,
|
||||
});
|
||||
userId = null;
|
||||
userToken = null;
|
||||
this.Close();
|
||||
}
|
||||
|
||||
public delegate bool UserInitCallback();
|
||||
private UserInitCallback? _userInitCallback;
|
||||
public bool UserInit(string userName, string fingerPrint, UserInitCallback callback) {
|
||||
if (this.GetIsConnected() == false) {
|
||||
return false;
|
||||
}
|
||||
this.SendRPMessage(new RPMessage{
|
||||
Type = "user",
|
||||
Cmd = "init",
|
||||
Data = new Dictionary {
|
||||
{ "userName", userName },
|
||||
{ "fingerPrint", fingerPrint }
|
||||
}
|
||||
});
|
||||
_userInitCallback = null;
|
||||
if (callback != null) _userInitCallback += callback;
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool UserRename(string newName) {
|
||||
if (this.GetIsConnected() == false) {
|
||||
return false;
|
||||
}
|
||||
this.SendRPMessage(new RPMessage{
|
||||
Type = "user",
|
||||
Cmd = "rename",
|
||||
Uid = userId,
|
||||
Token = userToken,
|
||||
Data = new Dictionary {
|
||||
{ "_", newName }
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool RegionAdd(string regionId) {
|
||||
if (this.GetIsConnected() == false || this.userId == null) {
|
||||
return false;
|
||||
}
|
||||
this.SendRPMessage(new RPMessage{
|
||||
Type = "region",
|
||||
Cmd = "add",
|
||||
Uid = userId,
|
||||
Token = userToken,
|
||||
Data = new Dictionary {
|
||||
{ "regionId", regionId }
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
public delegate bool RegionInspectCallback(
|
||||
Array<Dictionary<string, string>> _
|
||||
);
|
||||
private RPClientEventHandler? _regionRecvCallback;
|
||||
public bool RegionInspect(string regionId, RegionInspectCallback callback) {
|
||||
if (this.GetIsConnected() == false || this.userId == null) {
|
||||
return false;
|
||||
}
|
||||
_regionRecvCallback = null;
|
||||
_regionRecvCallback += (cmd, msg) => {
|
||||
if (cmd != "inspect" || msg == null) {
|
||||
return;
|
||||
}
|
||||
callback(msg["_"].AsGodotArray<Dictionary<string, string>>());
|
||||
};
|
||||
this.SendRPMessage(new RPMessage{
|
||||
Type = "region",
|
||||
Cmd = "inspect",
|
||||
Uid = userId,
|
||||
Token = userToken,
|
||||
Data = new Dictionary {
|
||||
{ "regionId", regionId }
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
public delegate bool SessionAckCreateCallback(
|
||||
string sessionId,
|
||||
bool res,
|
||||
string? reqUserId,
|
||||
string? reqUserName
|
||||
);
|
||||
private RPClientEventHandler? _sessionAckCreateCallback;
|
||||
public void RegSessionAckCreateCallback(SessionAckCreateCallback recvCallback) {
|
||||
_sessionAckCreateCallback = null;
|
||||
_sessionAckCreateCallback += (cmd, msg) => {
|
||||
if (msg == null) return;
|
||||
string sessionId = msg["sessionId"].AsString();
|
||||
bool res = msg.ContainsKey("res") && msg["res"].AsBool();
|
||||
string? reqUserId = msg.ContainsKey("reqUserId") ? msg["reqUserId"].AsString() : null;
|
||||
string? reqUserName = msg.ContainsKey("reqUserName") ? msg["reqUserName"].AsString() : null;
|
||||
recvCallback(sessionId, res, reqUserId, reqUserName);
|
||||
};
|
||||
}
|
||||
public bool SessionCreate(string[] usersId) {
|
||||
if (this.GetIsConnected() == false || this.userId == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.SendRPMessage(new RPMessage {
|
||||
Type = "session",
|
||||
Cmd = "create",
|
||||
Uid = userId,
|
||||
Token = userToken,
|
||||
Data = new Dictionary {
|
||||
{ "_", usersId }
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool SessionAckCreate(string sessionId, bool response)
|
||||
{
|
||||
if (this.GetIsConnected() == false || this.userId == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 根据响应情况发送确认消息给服务器
|
||||
string code = response ? "0000" : "0001";
|
||||
this.SendRPMessage(new RPMessage {
|
||||
Type = "session",
|
||||
Cmd = "ackCreate",
|
||||
Uid = userId,
|
||||
Token = userToken,
|
||||
Code = code,
|
||||
Data = new Dictionary {
|
||||
{ "sessionId", sessionId },
|
||||
{ "res", response }
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool SendSessionToAll(string sessionId, Variant data) {
|
||||
if (this.GetIsConnected() == false || this.userId == null || sessionId == null) {
|
||||
return false;
|
||||
}
|
||||
this.SendRPMessage(new RPMessage{
|
||||
Type = "session",
|
||||
Cmd = "sendAll",
|
||||
Uid = userId,
|
||||
Token = userToken,
|
||||
Data = new Dictionary {
|
||||
{ "sessionId", sessionId },
|
||||
{ "msg", data },
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
// ws.OnOpen += (eventName, args) => {
|
||||
// ws.SendRPMessage(new RPMessage{
|
||||
// Type = "user",
|
||||
// Cmd = "tmp",
|
||||
// });
|
||||
// };
|
||||
|
||||
// ws.OnError += (eventName, args) => {
|
||||
// GD.PrintErr(args);
|
||||
// // SetProcess(false);
|
||||
// };
|
||||
|
||||
// ws.OnClose += (eventName, args) => {
|
||||
// // GD.Print("close");
|
||||
// SetProcess(false);
|
||||
// };
|
||||
}
|
||||
}
|
@ -1 +0,0 @@
|
||||
uid://piu7vpl63m2m
|
@ -1,47 +0,0 @@
|
||||
using Godot;
|
||||
using Godot.Collections;
|
||||
|
||||
namespace RPPackage {
|
||||
public static class RPHelper
|
||||
{
|
||||
public static Dictionary SerializeRPMessage(RPMessage message)
|
||||
{
|
||||
return message.ToDictionary();
|
||||
}
|
||||
|
||||
public static RPMessage? DeserializeRPMessage(Dictionary data)
|
||||
{
|
||||
if (!data.ContainsKey("type") || !data.ContainsKey("cmd")) {
|
||||
return null;
|
||||
}
|
||||
return new RPMessage {
|
||||
Type = (string)data["type"],
|
||||
Cmd = (string)data["cmd"],
|
||||
Code = data.ContainsKey("code") ? (string)data["code"] : null,
|
||||
Uid = data.ContainsKey("uid") ? (string)data["uid"] : null,
|
||||
Token = data.ContainsKey("token") ? (string)data["token"] : null,
|
||||
Data = data.ContainsKey("data") ? data["data"].AsGodotDictionary() : null,
|
||||
};
|
||||
}
|
||||
|
||||
// 假设你有WebSocket通信的实现,这里仅展示如何使用上述方法
|
||||
public static void SendRPMessage(this EventDrivenWebSocket ws, RPMessage message)
|
||||
{
|
||||
ws.SendJsonEx(RPHelper.SerializeRPMessage(message));
|
||||
}
|
||||
|
||||
public static RPMessage? HandleIncomingMessage(string jsonMessage)
|
||||
{
|
||||
var dataDict = Json.ParseString(jsonMessage).AsGodotDictionary();
|
||||
if (dataDict != null)
|
||||
{
|
||||
return RPHelper.DeserializeRPMessage(dataDict);
|
||||
}
|
||||
else
|
||||
{
|
||||
GD.PrintErr("Failed to parse incoming message.");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1 +0,0 @@
|
||||
uid://bg8nobv3n6cek
|
@ -1,34 +0,0 @@
|
||||
using Godot;
|
||||
using Godot.Collections;
|
||||
|
||||
namespace RPPackage {
|
||||
public class RPMessage
|
||||
{
|
||||
public string Type { get; set; } = string.Empty;
|
||||
public string Cmd { get; set; } = string.Empty;
|
||||
public Dictionary? Data { get; set; }
|
||||
|
||||
public string? Uid { get; set; }
|
||||
public string? Token { get; set; }
|
||||
public string? Code { get; set; }
|
||||
public Dictionary ToDictionary()
|
||||
{
|
||||
var dict = new Dictionary {
|
||||
// if (Type != null)
|
||||
{ "type", Type },
|
||||
// if (Cmd != null)
|
||||
{ "cmd", Cmd }
|
||||
};
|
||||
if (Data != null)
|
||||
dict.Add("data", Data);
|
||||
|
||||
if (Uid != null)
|
||||
dict.Add("uid", Uid);
|
||||
if (Token != null)
|
||||
dict.Add("token", Token);
|
||||
if (Code != null)
|
||||
dict.Add("code", Code);
|
||||
return dict;
|
||||
}
|
||||
}
|
||||
}
|
@ -1 +0,0 @@
|
||||
uid://bunvpv6p54l78
|
@ -1,114 +0,0 @@
|
||||
using Godot;
|
||||
using Godot.Collections;
|
||||
|
||||
public partial class EventDrivenWebSocket : WebSocketPeer {
|
||||
public delegate void WebSocketEventHandler(string eventName, params object[]? args);
|
||||
public delegate void WSBinMsgEventHandler(byte[] args);
|
||||
public delegate void WSMsgEventHandler(string args);
|
||||
|
||||
public event WebSocketEventHandler? OnOpen;
|
||||
public event WSBinMsgEventHandler? OnMessage;
|
||||
public event WSMsgEventHandler? OnText;
|
||||
public event WSBinMsgEventHandler? OnBinary;
|
||||
public event WebSocketEventHandler? OnClose;
|
||||
public event WebSocketEventHandler? OnError;
|
||||
|
||||
private bool isConnected = false;
|
||||
private bool isCloseEventFired = false;
|
||||
private double connectingTime = double.NegativeInfinity;
|
||||
|
||||
|
||||
public EventDrivenWebSocket() : base() {
|
||||
isConnected = false;
|
||||
}
|
||||
|
||||
public bool GetIsConnected() {
|
||||
return isConnected;
|
||||
}
|
||||
|
||||
public void PollEx(double delta) {
|
||||
base.Poll();
|
||||
CheckAndDispatchEvents(delta);
|
||||
}
|
||||
|
||||
public void ConnectToUrlEx(string url, double delayTime = 3,
|
||||
TlsOptions? tlsClientOptions = null) {
|
||||
if (connectingTime >= 0) {
|
||||
return;
|
||||
}
|
||||
Error err = ConnectToUrl(url, tlsClientOptions);
|
||||
if (err != Error.Ok) {
|
||||
OnError?.Invoke("error", err);
|
||||
}
|
||||
connectingTime = delayTime;
|
||||
}
|
||||
|
||||
protected void CheckAndDispatchEvents(double delta) {
|
||||
var state = GetReadyState();
|
||||
switch (state) {
|
||||
case State.Open when !isConnected:
|
||||
isConnected = true;
|
||||
OnOpen?.Invoke("open", null);
|
||||
break;
|
||||
case State.Open:
|
||||
while (GetAvailablePacketCount() > 0) {
|
||||
byte[] packet = GetPacket();
|
||||
OnMessage?.Invoke(packet);
|
||||
if (WasStringPacket()) {
|
||||
OnText?.Invoke(packet.GetStringFromUtf8());
|
||||
} else {
|
||||
OnBinary?.Invoke(packet);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case State.Closed:
|
||||
connectingTime = double.NegativeInfinity;
|
||||
OnClose?.Invoke("closed", GetCloseCode(), GetCloseReason());
|
||||
isConnected = false;
|
||||
break;
|
||||
case State.Closing:
|
||||
// OnClose?.Invoke("closing");
|
||||
break;
|
||||
case State.Connecting:
|
||||
if (connectingTime >= 0) {
|
||||
connectingTime -= delta;
|
||||
} else if (connectingTime != double.NegativeInfinity){
|
||||
connectingTime = double.NegativeInfinity;
|
||||
Close();
|
||||
OnError?.Invoke("connectTimeOut", Error.Timeout);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// 可以在这里处理其他状态或错误
|
||||
OnError?.Invoke("error", "Unknown WebSocket state.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void SendBinaryEx(byte[] data) {
|
||||
SendEx(data);
|
||||
}
|
||||
|
||||
public void SendJsonEx(Dictionary msg) {
|
||||
SendTextEx(Json.Stringify(msg));
|
||||
}
|
||||
|
||||
public Error SendTextEx(string message) {
|
||||
if (isConnected) {
|
||||
return SendText(message);
|
||||
} else {
|
||||
OnError?.Invoke("error", "Attempt to send on a closed connection.");
|
||||
return Error.ConnectionError;
|
||||
}
|
||||
}
|
||||
|
||||
public Error SendEx(byte[] message, WriteMode writeMode = WriteMode.Binary) {
|
||||
if (isConnected) {
|
||||
return Send(message, writeMode);
|
||||
} else {
|
||||
OnError?.Invoke("error", "Attempt to send on a closed connection.");
|
||||
return Error.ConnectionError;
|
||||
}
|
||||
}
|
||||
}
|
@ -1 +0,0 @@
|
||||
uid://bsali4mwx62tt
|
69
Scripts/Mods/GlobalModManager.cs
Normal file
69
Scripts/Mods/GlobalModManager.cs
Normal file
@ -0,0 +1,69 @@
|
||||
using Godot;
|
||||
using NLua;
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
public class GlobalModManager
|
||||
{
|
||||
public readonly Lua lua = new();
|
||||
private readonly string modsPath;
|
||||
|
||||
public GlobalModManager(string modsPath = "user://Mods/") {
|
||||
this.modsPath = modsPath;
|
||||
lua.State.Encoding = Encoding.UTF8;
|
||||
// lua.State.SetHook(KeraLua.LuaHookMask.Count, 1000000);
|
||||
|
||||
InitSandBox();
|
||||
// RegisterAPI();
|
||||
}
|
||||
|
||||
public void LoadAllMods()
|
||||
{
|
||||
if (!DirAccess.DirExistsAbsolute(modsPath))
|
||||
return;
|
||||
|
||||
using var dir = DirAccess.Open(modsPath);
|
||||
if (dir == null) return;
|
||||
|
||||
dir.ListDirBegin();
|
||||
string fileName = dir.GetNext();
|
||||
while (!string.IsNullOrEmpty(fileName))
|
||||
{
|
||||
if (fileName.EndsWith(".lua"))
|
||||
{
|
||||
LoadMod(fileName);
|
||||
}
|
||||
fileName = dir.GetNext();
|
||||
}
|
||||
}
|
||||
|
||||
private void InitSandBox() {
|
||||
}
|
||||
|
||||
private void LoadMod(string filePath)
|
||||
{
|
||||
try
|
||||
{
|
||||
string luaCode = LoadFile(filePath);
|
||||
lua.DoString(luaCode);
|
||||
GD.Print($"成功加载Mod: {filePath}");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
GD.PrintErr($"加载Mod {filePath} 失败: {e.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private static void SaveFile(string path, string content)
|
||||
{
|
||||
using var file = FileAccess.Open(path, FileAccess.ModeFlags.Write);
|
||||
file.StoreString(content);
|
||||
}
|
||||
|
||||
private static string LoadFile(string path)
|
||||
{
|
||||
using var file = FileAccess.Open(path, FileAccess.ModeFlags.Read);
|
||||
string content = file.GetAsText();
|
||||
return content;
|
||||
}
|
||||
}
|
1
Scripts/Mods/GlobalModManager.cs.uid
Normal file
1
Scripts/Mods/GlobalModManager.cs.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://c45a7ldunixnh
|
40
Scripts/Mods/LuaModManager.cs
Normal file
40
Scripts/Mods/LuaModManager.cs
Normal file
@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Godot;
|
||||
using NLua;
|
||||
|
||||
class LuaMod : IDisposable {
|
||||
private readonly Lua lua = new();
|
||||
|
||||
public LuaMod(string path, string? package_path = null) {
|
||||
lua.LoadCLRPackage();
|
||||
lua.State.Encoding = System.Text.Encoding.UTF8;
|
||||
lua["package.path"] = package_path ?? Path.GetDirectoryName(path) + "/?.lua;";
|
||||
lua.RegisterFunction("print", new Action<object[]>(GD.Print).Method);
|
||||
// Action bar = () => { GD.Print("bar"); };
|
||||
// lua.RegisterFunction("bar", bar.Target, bar.Method);
|
||||
lua.DoFile(path);
|
||||
}
|
||||
|
||||
public void BindFunc(ModManager mod) {
|
||||
foreach (var api in mod.GetAPIs()) {
|
||||
lua.RegisterFunction(api.Key, api.Value.Target, api.Value.Method);
|
||||
}
|
||||
foreach (var hook in mod.GetHooks()) {
|
||||
if (lua[hook.Key] is LuaFunction func) {
|
||||
mod.AddHook(hook.Key, (args) => {
|
||||
var rets = func.Call(args).FirstOrDefault();
|
||||
if (rets is bool b) return b;
|
||||
return false;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose() {
|
||||
lua?.Dispose();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
|
1
Scripts/Mods/LuaModManager.cs.uid
Normal file
1
Scripts/Mods/LuaModManager.cs.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://dtqaboju24vmn
|
45
Scripts/Mods/ModManager.cs
Normal file
45
Scripts/Mods/ModManager.cs
Normal file
@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Reflection;
|
||||
|
||||
class ModManager {
|
||||
private readonly Dictionary<string, Delegate> _api = [];
|
||||
private readonly Dictionary<string, Delegate> _hooks = [];
|
||||
public delegate bool OnCallback(params object[] args);
|
||||
private readonly Dictionary<string, List<OnCallback>> _callbackList = [];
|
||||
|
||||
public ReadOnlyDictionary<string, Delegate> GetAPIs() => new(_api);
|
||||
public ReadOnlyDictionary<string, Delegate> GetHooks() => new(_hooks);
|
||||
|
||||
public ModManager RegistryFunc<TDelegate>(string name, TDelegate handler, bool isHook = false)
|
||||
where TDelegate : Delegate {
|
||||
MethodInfo _ = handler.Method;
|
||||
Dictionary<string, Delegate> dict = isHook ? _hooks : _api;
|
||||
dict.Add(name, handler);
|
||||
return this;
|
||||
}
|
||||
|
||||
public bool AddHook(string name, OnCallback handler) {
|
||||
if (_hooks.ContainsKey(name)) {
|
||||
if (!_callbackList.TryGetValue(name, out var list)) {
|
||||
list = [];
|
||||
_callbackList[name] = list;
|
||||
}
|
||||
list.Add(handler);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool InvokeFunc<TDelegate>(string name, params object[] args)
|
||||
where TDelegate : Delegate {
|
||||
List<object> res = [];
|
||||
if (_callbackList.TryGetValue(name, out var callback)) {
|
||||
foreach (var func in callback) {
|
||||
func?.Invoke(args);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
1
Scripts/Mods/ModManager.cs.uid
Normal file
1
Scripts/Mods/ModManager.cs.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://lmuddan86bi8
|
@ -1,6 +1,5 @@
|
||||
using Godot;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
class GodotConfigManager {
|
||||
private readonly string ConfigFilePath;
|
||||
@ -41,8 +40,8 @@ class GodotConfigManager {
|
||||
}
|
||||
}
|
||||
|
||||
public void SaveConfig(string SessionName,
|
||||
Dictionary<string, Variant> data) {
|
||||
public void SaveConfig(string SessionName, Dictionary<string, Variant> data)
|
||||
{
|
||||
// 将 GlobalConfig 中的键值对写入配置文件
|
||||
foreach (var key in data.Keys)
|
||||
{
|
||||
|
17
Scripts/Utilities/IConfig.cs
Normal file
17
Scripts/Utilities/IConfig.cs
Normal file
@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
public interface IConfigManager {
|
||||
void SetFilePath(string filePath);
|
||||
void SetDefault(Dictionary<string, object> defalutConfig);
|
||||
T GetValue<T>(string key);
|
||||
void SetValue<T>(string key, [NotNull]T value) {
|
||||
ArgumentNullException.ThrowIfNull(key);
|
||||
SetValue(key, (object?)value);
|
||||
}
|
||||
void SetValue(string key, [NotNull]object? value);
|
||||
bool HasKey(string key);
|
||||
void SaveToFile();
|
||||
void LoadFromFile();
|
||||
}
|
1
Scripts/Utilities/IConfig.cs.uid
Normal file
1
Scripts/Utilities/IConfig.cs.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://b8jvplvi4a7iv
|
53
Scripts/Utilities/JsonConfig.cs
Normal file
53
Scripts/Utilities/JsonConfig.cs
Normal file
@ -0,0 +1,53 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
|
||||
public class JsonConfigManager : IConfigManager {
|
||||
private string? filePath;
|
||||
private Dictionary<string, object> config = [];
|
||||
private Dictionary<string, object>? defaultConfig;
|
||||
|
||||
public T GetValue<T>(string key) {
|
||||
if (config.TryGetValue(key, out object? val)) {
|
||||
if (val is T t) {
|
||||
return t;
|
||||
} else if (val is JsonElement element) {
|
||||
return element.Deserialize<T>() ??
|
||||
throw new InvalidCastException($"无法将键'{key}'的值转换为类型{typeof(T).Name}");
|
||||
}
|
||||
}
|
||||
if (
|
||||
defaultConfig != null &&
|
||||
defaultConfig.TryGetValue(key, out object? dval) &&
|
||||
dval is T ret) {
|
||||
return ret;
|
||||
}
|
||||
throw new KeyNotFoundException($"Key '{key}' not found in config.");
|
||||
}
|
||||
|
||||
public bool HasKey(string key) => config.ContainsKey(key);
|
||||
public void SaveToFile() {
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(filePath);
|
||||
File.WriteAllText(filePath, JsonSerializer.Serialize(config));
|
||||
}
|
||||
|
||||
public void LoadFromFile() {
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(filePath);
|
||||
if (!File.Exists(filePath)) {
|
||||
return;
|
||||
}
|
||||
config = JsonSerializer.Deserialize
|
||||
<Dictionary<string, object>>(File.ReadAllText(filePath)) ?? [];
|
||||
}
|
||||
|
||||
public void SetDefault(Dictionary<string, object> defaultConfig) => this.defaultConfig = defaultConfig;
|
||||
|
||||
public void SetFilePath(string filePath) => this.filePath = filePath;
|
||||
|
||||
public void SetValue(string key, [NotNull]object? value) {
|
||||
ArgumentNullException.ThrowIfNull(value);
|
||||
config[key] = value;
|
||||
}
|
||||
}
|
1
Scripts/Utilities/JsonConfig.cs.uid
Normal file
1
Scripts/Utilities/JsonConfig.cs.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://ddvrwflje2x87
|
@ -14,11 +14,10 @@ config/name="ChessGame"
|
||||
config/version="0.0.6"
|
||||
run/main_scene="res://Main.tscn"
|
||||
config/features=PackedStringArray("4.4", "C#", "Mobile")
|
||||
config/icon="uid://c0wpthj7y1ayp"
|
||||
|
||||
[autoload]
|
||||
|
||||
Global="*res://Scripts/Global.cs"
|
||||
GlobalManager="*res://Scripts/GlobalManager.cs"
|
||||
|
||||
[display]
|
||||
|
||||
@ -31,6 +30,10 @@ window/handheld/orientation=1
|
||||
|
||||
project/assembly_name="ChessGame"
|
||||
|
||||
[internationalization]
|
||||
|
||||
locale/translations=PackedStringArray("res://Lang/godot_chessgame/content/zh_Hans.po", "res://Lang/godot_chessgame/content/en_devel.po")
|
||||
|
||||
[navigation]
|
||||
|
||||
2d/name_localized={}
|
||||
|
Reference in New Issue
Block a user