大更新,太多了,具体进游戏查看详细更新内容
反正很多
This commit is contained in:
157
Network/TCPClient.gd
Normal file
157
Network/TCPClient.gd
Normal file
@@ -0,0 +1,157 @@
|
||||
extends Node
|
||||
#一个基本的TCP客户端API
|
||||
class_name TCPClient
|
||||
|
||||
signal connected_to_server#连接到服务器信号
|
||||
signal connection_failed#连接失败信号
|
||||
signal connection_closed#连接关闭信号
|
||||
signal data_received(data)#收到数据信号
|
||||
|
||||
var tcp: StreamPeerTCP = StreamPeerTCP.new()
|
||||
var host: String = "127.0.0.1"
|
||||
var port: int = 4040
|
||||
var is_connected: bool = false
|
||||
var auto_reconnect: bool = true
|
||||
var reconnect_delay: float = 2.0
|
||||
|
||||
# 缓冲区管理
|
||||
var buffer = ""
|
||||
|
||||
func _ready():
|
||||
pass
|
||||
|
||||
func _process(_delta):
|
||||
# 更新连接状态
|
||||
tcp.poll()
|
||||
_update_connection_status()
|
||||
_check_for_data()
|
||||
|
||||
|
||||
func connect_to_server(custom_host = null, custom_port = null):
|
||||
if custom_host != null:
|
||||
host = custom_host
|
||||
if custom_port != null:
|
||||
port = custom_port
|
||||
|
||||
if tcp.get_status() != StreamPeerTCP.STATUS_CONNECTED:
|
||||
tcp.disconnect_from_host()
|
||||
print("连接到服务器: %s:%s" % [host, port])
|
||||
var error = tcp.connect_to_host(host, port)
|
||||
if error != OK:
|
||||
print("连接错误: %s" % error)
|
||||
emit_signal("connection_failed")
|
||||
|
||||
|
||||
func disconnect_from_server():
|
||||
tcp.disconnect_from_host()
|
||||
is_connected = false
|
||||
emit_signal("connection_closed")
|
||||
|
||||
|
||||
func _update_connection_status():
|
||||
var status = tcp.get_status()
|
||||
|
||||
match status:
|
||||
StreamPeerTCP.STATUS_NONE:
|
||||
if is_connected:
|
||||
is_connected = false
|
||||
print("连接已断开")
|
||||
emit_signal("connection_closed")
|
||||
|
||||
if auto_reconnect:
|
||||
var timer = get_tree().create_timer(reconnect_delay)
|
||||
await timer.timeout
|
||||
connect_to_server()
|
||||
|
||||
StreamPeerTCP.STATUS_CONNECTING:
|
||||
pass
|
||||
|
||||
StreamPeerTCP.STATUS_CONNECTED:
|
||||
if not is_connected:
|
||||
is_connected = true
|
||||
tcp.set_no_delay(true) # 禁用Nagle算法提高响应速度
|
||||
print("已连接到服务器")
|
||||
emit_signal("connected_to_server")
|
||||
|
||||
StreamPeerTCP.STATUS_ERROR:
|
||||
is_connected = false
|
||||
print("连接错误")
|
||||
emit_signal("connection_failed")
|
||||
|
||||
if auto_reconnect:
|
||||
var timer = get_tree().create_timer(reconnect_delay)
|
||||
await timer.timeout
|
||||
connect_to_server()
|
||||
|
||||
|
||||
func _check_for_data():
|
||||
if tcp.get_status() == StreamPeerTCP.STATUS_CONNECTED and tcp.get_available_bytes() > 0:
|
||||
var bytes = tcp.get_available_bytes()
|
||||
var data = tcp.get_utf8_string(bytes)
|
||||
|
||||
# 将数据添加到缓冲区进行处理
|
||||
buffer += data
|
||||
_process_buffer()
|
||||
|
||||
|
||||
func _process_buffer():
|
||||
# 处理缓冲区中的JSON消息
|
||||
# 假设每条消息以换行符结尾
|
||||
while "\n" in buffer:
|
||||
var message_end = buffer.find("\n")
|
||||
var message_text = buffer.substr(0, message_end)
|
||||
buffer = buffer.substr(message_end + 1)
|
||||
|
||||
# 处理JSON数据
|
||||
if message_text.strip_edges() != "":
|
||||
var json = JSON.new()
|
||||
var error = json.parse(message_text)
|
||||
|
||||
if error == OK:
|
||||
var data = json.get_data()
|
||||
#print("收到JSON数据: ", data)
|
||||
emit_signal("data_received", data)
|
||||
else:
|
||||
# 非JSON格式数据,直接传递
|
||||
#print("收到原始数据: ", message_text)
|
||||
emit_signal("data_received", message_text)
|
||||
|
||||
func send_data(data):
|
||||
if not is_connected:
|
||||
print("未连接,无法发送数据")
|
||||
return false
|
||||
|
||||
var message: String
|
||||
|
||||
# 如果是字典/数组,转换为JSON
|
||||
if typeof(data) == TYPE_DICTIONARY or typeof(data) == TYPE_ARRAY:
|
||||
message = JSON.stringify(data) + "\n"
|
||||
else:
|
||||
# 否则简单转换为字符串
|
||||
message = str(data) + "\n"
|
||||
|
||||
var result = tcp.put_data(message.to_utf8_buffer())
|
||||
return result == OK
|
||||
|
||||
func is_client_connected() -> bool:
|
||||
return is_connected
|
||||
|
||||
# 示例: 如何使用此客户端
|
||||
#
|
||||
# func _ready():
|
||||
# var client = TCPClient.new()
|
||||
# add_child(client)
|
||||
#
|
||||
# client.connected_to_server.connect(_on_connected)
|
||||
# client.connection_failed.connect(_on_connection_failed)
|
||||
# client.connection_closed.connect(_on_connection_closed)
|
||||
# client.data_received.connect(_on_data_received)
|
||||
#
|
||||
# client.connect_to_server("127.0.0.1", 9000)
|
||||
#
|
||||
# func _on_connected():
|
||||
# print("已连接")
|
||||
# client.send_data({"type": "greeting", "content": "Hello Server!"})
|
||||
#
|
||||
# func _on_data_received(data):
|
||||
# print("收到数据: ", data)
|
||||
1
Network/TCPClient.gd.uid
Normal file
1
Network/TCPClient.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://cylhhkh8ooxcu
|
||||
377
Network/TCPNetworkManager.gd
Normal file
377
Network/TCPNetworkManager.gd
Normal file
@@ -0,0 +1,377 @@
|
||||
extends Panel
|
||||
|
||||
# TCP客户端演示
|
||||
# 这个脚本展示如何在UI中使用TCPClient类
|
||||
|
||||
# UI组件引用
|
||||
@onready var status_label = $StatusLabel
|
||||
@onready var message_input = $MessageInput
|
||||
@onready var send_button = $SendButton
|
||||
@onready var response_label = $Scroll/ResponseLabel
|
||||
@onready var connection_button = $ConnectionButton
|
||||
@onready var login_panel = $"/root/main/UI/LoginPanel"
|
||||
@onready var main_game = get_node("/root/main")
|
||||
|
||||
# TCP客户端
|
||||
var client: TCPClient = TCPClient.new()
|
||||
|
||||
# 服务器配置 - 支持多个服务器地址
|
||||
var server_configs = [
|
||||
#{"host": "127.0.0.1", "port": 4040, "name": "本地服务器"},
|
||||
#{"host": "192.168.1.110", "port": 4040, "name": "局域网服务器"},
|
||||
{"host": "47.108.90.0", "port": 4040, "name": "公网服务器"}#成都内网穿透
|
||||
]
|
||||
|
||||
var current_server_index = 0
|
||||
var auto_retry = true
|
||||
var retry_delay = 3.0
|
||||
|
||||
func _ready():
|
||||
# 创建TCP客户端实例
|
||||
self.add_child(client)
|
||||
|
||||
# 连接信号
|
||||
client.connected_to_server.connect(_on_connected)
|
||||
client.connection_failed.connect(_on_connection_failed)
|
||||
client.connection_closed.connect(_on_connection_closed)
|
||||
client.data_received.connect(_on_data_received)
|
||||
|
||||
# 连接按钮事件
|
||||
connection_button.pressed.connect(_on_connection_button_pressed)
|
||||
send_button.pressed.connect(_on_send_button_pressed)
|
||||
|
||||
# 初始设置
|
||||
status_label.text = "未连接"
|
||||
response_label.text = "等待响应..."
|
||||
connection_button.text = "连接"
|
||||
|
||||
func _on_connected():
|
||||
status_label.text = "已连接"
|
||||
status_label.modulate = Color.GREEN
|
||||
connection_button.text = "断开"
|
||||
|
||||
# 发送连接成功消息
|
||||
client.send_data({
|
||||
"type": "greeting",
|
||||
"content": "你好,服务器!"
|
||||
})
|
||||
|
||||
# 连接成功后立即请求作物数据
|
||||
print("连接成功,正在请求最新作物数据...")
|
||||
sendGetCropData()
|
||||
|
||||
func _on_connection_failed():
|
||||
status_label.text = "连接失败"
|
||||
status_label.modulate = Color.RED
|
||||
connection_button.text = "连接"
|
||||
|
||||
# 自动尝试下一个服务器
|
||||
if auto_retry:
|
||||
try_next_server()
|
||||
|
||||
func _on_connection_closed():
|
||||
status_label.text = "连接断开"
|
||||
status_label.modulate = Color.RED
|
||||
connection_button.text = "连接"
|
||||
|
||||
# 自动重连当前服务器
|
||||
if auto_retry:
|
||||
var timer = get_tree().create_timer(retry_delay)
|
||||
await timer.timeout
|
||||
if not client.is_client_connected():
|
||||
_on_connection_button_pressed()
|
||||
|
||||
func _on_data_received(data):
|
||||
# 根据数据类型处理数据
|
||||
response_label.text = "收到: %s" % JSON.stringify(data)
|
||||
match typeof(data):
|
||||
|
||||
TYPE_DICTIONARY:
|
||||
# 处理JSON对象
|
||||
var message_type = data.get("type", "")
|
||||
|
||||
match message_type:
|
||||
"ping":
|
||||
return
|
||||
"response":
|
||||
# 显示服务器响应
|
||||
if data.has("original"):
|
||||
var original = data.get("original", {})
|
||||
return
|
||||
"login_response":
|
||||
# 处理登录响应
|
||||
var status = data.get("status", "")
|
||||
var message = data.get("message", "")
|
||||
var player_data = data.get("player_data", {})
|
||||
if login_panel:
|
||||
# 调用登录面板的响应处理方法
|
||||
login_panel._on_login_response_received(status == "success", message, player_data)
|
||||
"register_response":
|
||||
# 处理注册响应
|
||||
var status = data.get("status", "")
|
||||
var message = data.get("message", "")
|
||||
if login_panel:
|
||||
# 调用登录面板的响应处理方法
|
||||
login_panel._on_register_response_received(status == "success", message)
|
||||
"verification_code_response":
|
||||
# 处理验证码发送响应
|
||||
var success = data.get("success", false)
|
||||
var message = data.get("message", "")
|
||||
if login_panel:
|
||||
# 调用登录面板的验证码响应处理方法
|
||||
login_panel._on_verification_code_response(success, message)
|
||||
"verify_code_response":
|
||||
# 处理验证码验证响应
|
||||
var success = data.get("success", false)
|
||||
var message = data.get("message", "")
|
||||
if login_panel:
|
||||
# 调用登录面板的验证码验证响应处理方法
|
||||
login_panel._on_verify_code_response(success, message)
|
||||
"crop_update":
|
||||
# 处理作物生长更新
|
||||
if main_game:
|
||||
main_game._handle_crop_update(data)
|
||||
"action_response":
|
||||
# 处理玩家动作响应
|
||||
if main_game:
|
||||
main_game._handle_action_response(data)
|
||||
"play_time_response":
|
||||
# 处理玩家游玩时间响应
|
||||
if main_game and main_game.has_method("_handle_play_time_response"):
|
||||
main_game._handle_play_time_response(data)
|
||||
"player_rankings_response":
|
||||
# 处理玩家排行榜响应
|
||||
if main_game and main_game.has_method("_handle_player_rankings_response"):
|
||||
main_game._handle_player_rankings_response(data)
|
||||
"crop_data_response":
|
||||
# 处理作物数据响应
|
||||
if main_game and main_game.has_method("_handle_crop_data_response"):
|
||||
main_game._handle_crop_data_response(data)
|
||||
"visit_player_response":
|
||||
# 处理访问玩家响应
|
||||
if main_game and main_game.has_method("_handle_visit_player_response"):
|
||||
main_game._handle_visit_player_response(data)
|
||||
"return_my_farm_response":
|
||||
# 处理返回自己农场响应
|
||||
if main_game and main_game.has_method("_handle_return_my_farm_response"):
|
||||
main_game._handle_return_my_farm_response(data)
|
||||
_:
|
||||
# 显示其他类型的消息
|
||||
return
|
||||
_:
|
||||
# 处理非JSON数据
|
||||
return
|
||||
|
||||
func _on_connection_button_pressed():
|
||||
if client.is_client_connected():
|
||||
# 断开连接
|
||||
client.disconnect_from_server()
|
||||
else:
|
||||
# 连接服务器
|
||||
status_label.text = "正在连接..."
|
||||
client.connect_to_server(server_configs[current_server_index]["host"], server_configs[current_server_index]["port"])
|
||||
|
||||
func _on_send_button_pressed():
|
||||
if not client.is_client_connected():
|
||||
status_label.text = "未连接,无法发送"
|
||||
return
|
||||
|
||||
# 获取输入文本
|
||||
var text = message_input.text.strip_edges()
|
||||
if text.is_empty():
|
||||
return
|
||||
|
||||
# 发送消息
|
||||
client.send_data({
|
||||
"type": "message",
|
||||
"content": text,
|
||||
"timestamp": Time.get_unix_time_from_system()
|
||||
})
|
||||
|
||||
# 清空输入
|
||||
message_input.text = ""
|
||||
|
||||
#发送登录信息
|
||||
func sendLoginInfo(username, password):
|
||||
client.send_data({
|
||||
"type": "login",
|
||||
"username": username,
|
||||
"password": password
|
||||
})
|
||||
|
||||
#发送注册信息
|
||||
func sendRegisterInfo(username, password, farmname, player_name="", verification_code=""):
|
||||
client.send_data({
|
||||
"type": "register",
|
||||
"username": username,
|
||||
"password": password,
|
||||
"farm_name": farmname,
|
||||
"player_name": player_name,
|
||||
"verification_code": verification_code
|
||||
})
|
||||
|
||||
#发送收获作物信息
|
||||
func sendHarvestCrop(lot_index):
|
||||
if not client.is_client_connected():
|
||||
return false
|
||||
|
||||
client.send_data({
|
||||
"type": "harvest_crop",
|
||||
"lot_index": lot_index,
|
||||
"timestamp": Time.get_unix_time_from_system()
|
||||
})
|
||||
return true
|
||||
|
||||
#发送种植作物信息
|
||||
func sendPlantCrop(lot_index, crop_name):
|
||||
if not client.is_client_connected():
|
||||
return false
|
||||
|
||||
client.send_data({
|
||||
"type": "plant_crop",
|
||||
"lot_index": lot_index,
|
||||
"crop_name": crop_name,
|
||||
"timestamp": Time.get_unix_time_from_system()
|
||||
})
|
||||
return true
|
||||
|
||||
#发送开垦土地信息
|
||||
func sendDigGround(lot_index):
|
||||
if not client.is_client_connected():
|
||||
return false
|
||||
|
||||
client.send_data({
|
||||
"type": "dig_ground",
|
||||
"lot_index": lot_index,
|
||||
"timestamp": Time.get_unix_time_from_system()
|
||||
})
|
||||
return true
|
||||
|
||||
#发送购买种子信息
|
||||
func sendBuySeed(crop_name):
|
||||
if not client.is_client_connected():
|
||||
return false
|
||||
|
||||
client.send_data({
|
||||
"type": "buy_seed",
|
||||
"crop_name": crop_name,
|
||||
"timestamp": Time.get_unix_time_from_system()
|
||||
})
|
||||
return true
|
||||
|
||||
#发送获取游玩时间请求
|
||||
func sendGetPlayTime():
|
||||
if not client.is_client_connected():
|
||||
return false
|
||||
|
||||
client.send_data({
|
||||
"type": "get_play_time"
|
||||
})
|
||||
return true
|
||||
|
||||
#发送更新游玩时间请求
|
||||
func sendUpdatePlayTime():
|
||||
if not client.is_client_connected():
|
||||
return false
|
||||
|
||||
client.send_data({
|
||||
"type": "update_play_time"
|
||||
})
|
||||
return true
|
||||
|
||||
#发送获取玩家排行榜请求
|
||||
func sendGetPlayerRankings():
|
||||
if not client.is_client_connected():
|
||||
return false
|
||||
|
||||
client.send_data({
|
||||
"type": "request_player_rankings"
|
||||
})
|
||||
return true
|
||||
|
||||
#发送验证码请求
|
||||
func sendVerificationCodeRequest(qq_number):
|
||||
if not client.is_client_connected():
|
||||
return false
|
||||
|
||||
client.send_data({
|
||||
"type": "request_verification_code",
|
||||
"qq_number": qq_number,
|
||||
"timestamp": Time.get_unix_time_from_system()
|
||||
})
|
||||
return true
|
||||
|
||||
#发送验证码验证
|
||||
func sendVerifyCode(qq_number, code):
|
||||
if not client.is_client_connected():
|
||||
return false
|
||||
|
||||
client.send_data({
|
||||
"type": "verify_code",
|
||||
"qq_number": qq_number,
|
||||
"code": code,
|
||||
"timestamp": Time.get_unix_time_from_system()
|
||||
})
|
||||
return true
|
||||
|
||||
#发送获取作物数据请求
|
||||
func sendGetCropData():
|
||||
if not client.is_client_connected():
|
||||
return false
|
||||
|
||||
client.send_data({
|
||||
"type": "request_crop_data"
|
||||
})
|
||||
return true
|
||||
|
||||
#发送访问玩家请求
|
||||
func sendVisitPlayer(target_username):
|
||||
if not client.is_client_connected():
|
||||
return false
|
||||
|
||||
client.send_data({
|
||||
"type": "visit_player",
|
||||
"target_username": target_username,
|
||||
"timestamp": Time.get_unix_time_from_system()
|
||||
})
|
||||
return true
|
||||
|
||||
#发送返回自己农场请求
|
||||
func sendReturnMyFarm():
|
||||
if not client.is_client_connected():
|
||||
return false
|
||||
|
||||
client.send_data({
|
||||
"type": "return_my_farm",
|
||||
"timestamp": Time.get_unix_time_from_system()
|
||||
})
|
||||
return true
|
||||
|
||||
#检查是否连接到服务器
|
||||
func is_connected_to_server():
|
||||
return client.is_client_connected()
|
||||
|
||||
# 尝试连接下一个服务器
|
||||
func try_next_server():
|
||||
current_server_index = (current_server_index + 1) % server_configs.size()
|
||||
var config = server_configs[current_server_index]
|
||||
|
||||
status_label.text = "尝试连接 " + config["name"]
|
||||
print("尝试连接服务器: ", config["name"], " (", config["host"], ":", config["port"], ")")
|
||||
|
||||
var timer = get_tree().create_timer(retry_delay)
|
||||
await timer.timeout
|
||||
|
||||
if not client.is_client_connected():
|
||||
client.connect_to_server(config["host"], config["port"])
|
||||
|
||||
# 检查网络连接状态
|
||||
func check_network_status():
|
||||
# 检查设备是否有网络连接
|
||||
if OS.get_name() == "Android":
|
||||
# 在Android上检查网络状态
|
||||
status_label.text = "检查网络状态..."
|
||||
|
||||
# 尝试连接到当前配置的服务器
|
||||
if not client.is_client_connected():
|
||||
_on_connection_button_pressed()
|
||||
1
Network/TCPNetworkManager.gd.uid
Normal file
1
Network/TCPNetworkManager.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://q1f3tubmdsrk
|
||||
69
Network/TCPNetworkManager.tscn
Normal file
69
Network/TCPNetworkManager.tscn
Normal file
@@ -0,0 +1,69 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://cpxiaqh0y6a5d"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://q1f3tubmdsrk" path="res://Network/TCPNetworkManager.gd" id="1_tfd57"]
|
||||
|
||||
[node name="TCPNetworkManager" type="Panel"]
|
||||
script = ExtResource("1_tfd57")
|
||||
|
||||
[node name="Scroll" type="ScrollContainer" parent="."]
|
||||
layout_mode = 0
|
||||
offset_left = 1.0
|
||||
offset_top = 142.0
|
||||
offset_right = 401.0
|
||||
offset_bottom = 647.0
|
||||
horizontal_scroll_mode = 0
|
||||
|
||||
[node name="ResponseLabel" type="Label" parent="Scroll"]
|
||||
custom_minimum_size = Vector2(400, 500)
|
||||
layout_mode = 2
|
||||
theme_override_colors/font_outline_color = Color(1, 1, 1, 1)
|
||||
theme_override_font_sizes/font_size = 20
|
||||
text = "回应"
|
||||
autowrap_mode = 3
|
||||
|
||||
[node name="Title" type="Label" parent="."]
|
||||
layout_mode = 0
|
||||
offset_right = 400.0
|
||||
offset_bottom = 42.0
|
||||
theme_override_font_sizes/font_size = 30
|
||||
text = "TCP网络调试面板"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="ColorRect" type="ColorRect" parent="."]
|
||||
layout_mode = 0
|
||||
offset_right = 400.0
|
||||
offset_bottom = 647.0
|
||||
color = Color(0.104753, 0.146763, 0.23013, 0.427451)
|
||||
|
||||
[node name="StatusLabel" type="Label" parent="."]
|
||||
layout_mode = 0
|
||||
offset_top = 100.0
|
||||
offset_right = 120.0
|
||||
offset_bottom = 142.0
|
||||
theme_override_font_sizes/font_size = 30
|
||||
text = "连接状态"
|
||||
|
||||
[node name="MessageInput" type="LineEdit" parent="."]
|
||||
layout_mode = 0
|
||||
offset_left = 136.0
|
||||
offset_top = 50.0
|
||||
offset_right = 400.0
|
||||
offset_bottom = 100.0
|
||||
theme_override_font_sizes/font_size = 30
|
||||
|
||||
[node name="SendButton" type="Button" parent="."]
|
||||
layout_mode = 0
|
||||
offset_left = 68.0
|
||||
offset_top = 50.0
|
||||
offset_right = 136.0
|
||||
offset_bottom = 100.0
|
||||
theme_override_font_sizes/font_size = 30
|
||||
text = "发送"
|
||||
|
||||
[node name="ConnectionButton" type="Button" parent="."]
|
||||
layout_mode = 0
|
||||
offset_top = 50.0
|
||||
offset_right = 68.0
|
||||
offset_bottom = 100.0
|
||||
theme_override_font_sizes/font_size = 30
|
||||
text = "连接"
|
||||
Reference in New Issue
Block a user