├── .gitignore
├── LICENSE.txt
├── README.md
├── demo
└── EnetNode
│ ├── client.gd
│ ├── client.xscn
│ ├── engine.cfg
│ ├── export.cfg
│ ├── fonts
│ ├── mono-bold-20.fnt
│ ├── mono-bold-20.inc
│ ├── mono-bold-20.sv.png
│ ├── mono-bold-20.sv.png.flags
│ ├── mono-regular-18.fnt
│ ├── mono-regular-18.inc
│ ├── mono-regular-18.sv.png
│ ├── mono-regular-18.sv.png.flags
│ └── originals
│ │ ├── AUTHORS
│ │ ├── LICENSE
│ │ ├── LiberationMono-Bold.ttf
│ │ └── LiberationMono-Regular.ttf
│ ├── icon.png
│ ├── icon.png.flags
│ ├── server.gd
│ └── server.xscn
└── modules
└── benet
├── SCsub
├── config.py
├── enet_node.cpp
├── enet_node.h
├── enet_packet_peer.cpp
├── enet_packet_peer.h
├── register_types.cpp
└── register_types.h
/.gitignore:
--------------------------------------------------------------------------------
1 | *.o
2 | *.a
3 | *.pyc
4 | *.swp
5 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016-2017 Fabio Alessandrelli
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # About
2 | The `benet` module for Godot is a fork of `NetworkedMultiplayerPacketPeer` (although it stays compatible) to allow access to multiple channels and the ability to run multiple clients/servers in the same scene.
3 |
4 | The module is composed by two parts:
5 |
6 | - `ENetPacketPeer`: The fork of `NetworkedMultiplayerPacketPeer`
7 | - `create_server`: Add parameter to specify max channels (default 1)
8 | - `create_client`: Add parameter to specify max channels (default 1)
9 | - `put_packet_channel`: New method, allow to put a packet in the specified channel
10 | - `send` (`_unreliable`, `_ordered`) allow to send to specific client in reliable, unreliable, ordered way whlie selecting the channel
11 | - `broadcast` (`_unreliable`, `_ordered`) allow to broadcast a packet in a reliable, unreliable, ordered way while selecting the channel
12 |
13 | - `ENetNode`: Act like `SceneTree`:
14 | - Poll on idle/fixed time (must be in tree to work!)
15 | - Emit signals on idle/fixed time (must be in tree to work!)
16 | - Emit additional `server_packet` and `client_packet` signals when receiving packets
17 | - Allow kicking clients by unique id.
18 | - Will hopefully support RPC in the future
19 |
20 | # Installation
21 | Being a module you will need to recompile godot from source. To do that:
22 |
23 | 1. Clone the godot engine repository
24 | 2. Copy the `benet` folder from this repository into the godot `modules` folder
25 | 3. Recompile godot (see http://docs.godotengine.org/en/latest/reference/_compiling.html )
26 |
27 | # Usage
28 |
29 | For usage examples please refer to the project in the `demo` folder.
30 |
31 | The methods should be self explainatory.
32 |
33 | # Disclaimer
34 |
35 | > THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 |
--------------------------------------------------------------------------------
/demo/EnetNode/client.gd:
--------------------------------------------------------------------------------
1 |
2 | extends Control
3 |
4 | var id = 0
5 | var connected = false
6 |
7 | var client_peer = ENetPacketPeer.new()
8 | onready var client = get_node("ENetNode")
9 | onready var client_log = get_node("ScrollContainer/ClientLog")
10 | onready var scroll_container = get_node("ScrollContainer")
11 |
12 | func _ready():
13 | # Sent when the client disconnects
14 | client.connect("server_disconnected", self, "disconnected")
15 | # Sent when the client disconnects
16 | client.connect("connection_failed", self, "connect_failed")
17 | # Sent when the client connects to the server
18 | client.connect("connected_to_server", self, "connected")
19 | # Sent when a valid packet is received from the server
20 | client.connect("server_packet", self, "on_server_packet")
21 | # Sent when a valid packet is received from another peer
22 | client.connect("peer_packet", self, "on_peer_packet")
23 |
24 | # Sent when another peer connect to this server (will be called once for every connected client when you first connect)
25 | client.connect("network_peer_connected", self, "peer_connect")
26 | # Sent when another peer disconnect from the server
27 | client.connect("network_peer_disconnected", self, "peer_disconnect")
28 |
29 | # Create a client to 127.0.0.1 on port 4666 with 16 custom channels
30 | client_peer.create_client("127.0.0.1", 4666, 16)
31 | client.set_network_peer(client_peer)
32 |
33 | client_log.set_text("")
34 | write_log("Connecting...")
35 | set_fixed_process(true)
36 | set_process(true)
37 |
38 | func disconnected():
39 | write_log("Client Disconnected!")
40 | call_deferred("queue_free")
41 |
42 | func connected():
43 | write_log("Just Connected! My ID is: " + str(client.get_network_unique_id()) )
44 |
45 | func connect_failed():
46 | write_log("Connection failed!")
47 |
48 | func peer_connect(id):
49 | write_log(str(id) + " - Connect")
50 |
51 | func peer_disconnect(id):
52 | write_log(str(id) + " - Disconnect")
53 |
54 | func on_server_packet(cmd, pkt):
55 | write_log("SERVER - CMD: " + str(cmd) + " DATA:" + str(Array(pkt)))
56 |
57 | func on_peer_packet(id, cmd, pkt):
58 | write_log(str(id), " - CMD: " + str(cmd) + " DATA:" + str(Array(pkt)))
59 |
60 | func _process(delta):
61 | scroll_container.set_v_scroll(scroll_container.get_v_scroll()+100)
62 |
63 | ### Scene functions
64 | func write_log(msg):
65 | print(msg)
66 | client_log.set_text(client_log.get_text()+"\n"+str(msg))
67 |
68 | func _on_Button_pressed():
69 | client.send_ordered(1, RawArray([2,52,12]), 2)
70 |
71 | func _on_TCP_pressed():
72 | client.send(1, RawArray([22,36,89]), 1)
73 |
74 | func _exit_tree():
75 | client_peer.close_connection()
76 |
--------------------------------------------------------------------------------
/demo/EnetNode/client.xscn:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | "conn_count"
8 | 2
9 | "conns"
10 | 4, 0, 34, 33, 2, 0, 5, 0, 34, 35, 2, 0
11 | "editable_instances"
12 |
13 |
14 | "names"
15 |
16 | "Scrollable"
17 | "anchor/right"
18 | "anchor/bottom"
19 | "focus/ignore_mouse"
20 | "focus/stop_mouse"
21 | "size_flags/horizontal"
22 | "size_flags/vertical"
23 | "margin/left"
24 | "margin/top"
25 | "margin/right"
26 | "margin/bottom"
27 | "script/script"
28 | "Control"
29 | "ScrollContainer"
30 | "editor/display_folded"
31 | "scroll/horizontal"
32 | "scroll/vertical"
33 | "ClientLog"
34 | "custom_fonts/font"
35 | "percent_visible"
36 | "lines_skipped"
37 | "max_lines_visible"
38 | "Label"
39 | "ENetNode"
40 | "signal_mode"
41 | "UDP"
42 | "toggle_mode"
43 | "enabled_focus_mode"
44 | "shortcut"
45 | "text"
46 | "flat"
47 | "Button"
48 | "TCP"
49 | "_on_Button_pressed"
50 | "pressed"
51 | "_on_TCP_pressed"
52 |
53 | "node_count"
54 | 6
55 | "node_paths"
56 |
57 |
58 | "nodes"
59 | -1, -1, 12, 0, -1, 11, 1, 0, 2, 0, 3, 1, 4, 2, 5, 3, 6, 3, 7, 4, 8, 4, 9, 4, 10, 4, 11, 5, 0, 0, 0, 13, 13, -1, 13, 14, 2, 1, 0, 2, 0, 3, 1, 4, 2, 5, 3, 6, 3, 7, 4, 8, 4, 9, 4, 10, 4, 15, 2, 16, 2, 0, 1, 0, 22, 17, -1, 12, 3, 1, 4, 2, 5, 6, 6, 6, 7, 7, 8, 7, 9, 4, 10, 8, 18, 9, 19, 10, 20, 11, 21, 12, 0, 0, 0, 23, 23, -1, 1, 24, 0, 0, 0, 0, 31, 25, -1, 14, 3, 1, 4, 2, 5, 6, 6, 6, 7, 4, 8, 4, 9, 13, 10, 14, 18, 9, 26, 1, 27, 6, 28, 15, 29, 16, 30, 1, 0, 0, 0, 31, 32, -1, 14, 3, 1, 4, 2, 5, 6, 6, 6, 7, 13, 8, 4, 9, 17, 10, 14, 18, 9, 26, 1, 27, 6, 28, 15, 29, 18, 30, 1, 0
60 | "variants"
61 |
62 | 1
63 | False
64 | True
65 | 3
66 | 0
67 |
68 | 2
69 | -0
70 | 18
71 |
72 | 1
73 | 0
74 | -1
75 | 56
76 | 24
77 | "UDP"
78 | 112
79 | "TCP"
80 |
81 | "version"
82 | 2
83 |
84 |
85 |
86 |
--------------------------------------------------------------------------------
/demo/EnetNode/engine.cfg:
--------------------------------------------------------------------------------
1 | [application]
2 |
3 | name="EnetNode"
4 | main_scene="res://server.xscn"
5 | target_fps=60
6 | icon="res://icon.png"
7 |
--------------------------------------------------------------------------------
/demo/EnetNode/export.cfg:
--------------------------------------------------------------------------------
1 | [convert_images]
2 |
3 | action="none"
4 | compress_quality=0.7
5 | formats="png"
6 | shrink=1.0
7 |
8 | [convert_samples]
9 |
10 | action="none"
11 | max_hz=44100
12 | trim=false
13 |
14 | [convert_scenes]
15 |
16 | convert_text_scenes=true
17 |
18 | [export_filter]
19 |
20 | filter=""
21 | filter_exclude=""
22 | type="resources"
23 |
24 | [platform:Android]
25 |
26 | apk_expansion/SALT=""
27 | apk_expansion/enable=false
28 | apk_expansion/public_key=""
29 | architecture/arm=true
30 | architecture/x86=false
31 | command_line/extra_args=""
32 | custom_package/debug=""
33 | custom_package/release=""
34 | debug/debugging_enabled=true
35 | keystore/release=""
36 | keystore/release_password=""
37 | keystore/release_user=""
38 | one_click_deploy/clear_previous_install=true
39 | package/icon=""
40 | package/name=""
41 | package/signed=true
42 | package/unique_name="org.godotengine.$genname"
43 | permissions/access_checkin_properties=false
44 | permissions/access_coarse_location=false
45 | permissions/access_fine_location=false
46 | permissions/access_location_extra_commands=false
47 | permissions/access_mock_location=false
48 | permissions/access_network_state=false
49 | permissions/access_surface_flinger=false
50 | permissions/access_wifi_state=false
51 | permissions/account_manager=false
52 | permissions/add_voicemail=false
53 | permissions/authenticate_accounts=false
54 | permissions/battery_stats=false
55 | permissions/bind_accessibility_service=false
56 | permissions/bind_appwidget=false
57 | permissions/bind_device_admin=false
58 | permissions/bind_input_method=false
59 | permissions/bind_nfc_service=false
60 | permissions/bind_notification_listener_service=false
61 | permissions/bind_print_service=false
62 | permissions/bind_remoteviews=false
63 | permissions/bind_text_service=false
64 | permissions/bind_vpn_service=false
65 | permissions/bind_wallpaper=false
66 | permissions/bluetooth=false
67 | permissions/bluetooth_admin=false
68 | permissions/bluetooth_privileged=false
69 | permissions/brick=false
70 | permissions/broadcast_package_removed=false
71 | permissions/broadcast_sms=false
72 | permissions/broadcast_sticky=false
73 | permissions/broadcast_wap_push=false
74 | permissions/call_phone=false
75 | permissions/call_privileged=false
76 | permissions/camera=false
77 | permissions/capture_audio_output=false
78 | permissions/capture_secure_video_output=false
79 | permissions/capture_video_output=false
80 | permissions/change_component_enabled_state=false
81 | permissions/change_configuration=false
82 | permissions/change_network_state=false
83 | permissions/change_wifi_multicast_state=false
84 | permissions/change_wifi_state=false
85 | permissions/clear_app_cache=false
86 | permissions/clear_app_user_data=false
87 | permissions/control_location_updates=false
88 | permissions/delete_cache_files=false
89 | permissions/delete_packages=false
90 | permissions/device_power=false
91 | permissions/diagnostic=false
92 | permissions/disable_keyguard=false
93 | permissions/dump=false
94 | permissions/expand_status_bar=false
95 | permissions/factory_test=false
96 | permissions/flashlight=false
97 | permissions/force_back=false
98 | permissions/get_accounts=false
99 | permissions/get_package_size=false
100 | permissions/get_tasks=false
101 | permissions/get_top_activity_info=false
102 | permissions/global_search=false
103 | permissions/hardware_test=false
104 | permissions/inject_events=false
105 | permissions/install_location_provider=false
106 | permissions/install_packages=false
107 | permissions/install_shortcut=false
108 | permissions/internal_system_window=false
109 | permissions/internet=false
110 | permissions/kill_background_processes=false
111 | permissions/location_hardware=false
112 | permissions/manage_accounts=false
113 | permissions/manage_app_tokens=false
114 | permissions/manage_documents=false
115 | permissions/master_clear=false
116 | permissions/media_content_control=false
117 | permissions/modify_audio_settings=false
118 | permissions/modify_phone_state=false
119 | permissions/mount_format_filesystems=false
120 | permissions/mount_unmount_filesystems=false
121 | permissions/nfc=false
122 | permissions/persistent_activity=false
123 | permissions/process_outgoing_calls=false
124 | permissions/read_calendar=false
125 | permissions/read_call_log=false
126 | permissions/read_contacts=false
127 | permissions/read_external_storage=false
128 | permissions/read_frame_buffer=false
129 | permissions/read_history_bookmarks=false
130 | permissions/read_input_state=false
131 | permissions/read_logs=false
132 | permissions/read_phone_state=false
133 | permissions/read_profile=false
134 | permissions/read_sms=false
135 | permissions/read_social_stream=false
136 | permissions/read_sync_settings=false
137 | permissions/read_sync_stats=false
138 | permissions/read_user_dictionary=false
139 | permissions/reboot=false
140 | permissions/receive_boot_completed=false
141 | permissions/receive_mms=false
142 | permissions/receive_sms=false
143 | permissions/receive_wap_push=false
144 | permissions/record_audio=false
145 | permissions/reorder_tasks=false
146 | permissions/restart_packages=false
147 | permissions/send_respond_via_message=false
148 | permissions/send_sms=false
149 | permissions/set_activity_watcher=false
150 | permissions/set_alarm=false
151 | permissions/set_always_finish=false
152 | permissions/set_animation_scale=false
153 | permissions/set_debug_app=false
154 | permissions/set_orientation=false
155 | permissions/set_pointer_speed=false
156 | permissions/set_preferred_applications=false
157 | permissions/set_process_limit=false
158 | permissions/set_time=false
159 | permissions/set_time_zone=false
160 | permissions/set_wallpaper=false
161 | permissions/set_wallpaper_hints=false
162 | permissions/signal_persistent_processes=false
163 | permissions/status_bar=false
164 | permissions/subscribed_feeds_read=false
165 | permissions/subscribed_feeds_write=false
166 | permissions/system_alert_window=false
167 | permissions/transmit_ir=false
168 | permissions/uninstall_shortcut=false
169 | permissions/update_device_stats=false
170 | permissions/use_credentials=false
171 | permissions/use_sip=false
172 | permissions/vibrate=false
173 | permissions/wake_lock=false
174 | permissions/write_apn_settings=false
175 | permissions/write_calendar=false
176 | permissions/write_call_log=false
177 | permissions/write_contacts=false
178 | permissions/write_external_storage=false
179 | permissions/write_gservices=false
180 | permissions/write_history_bookmarks=false
181 | permissions/write_profile=false
182 | permissions/write_secure_settings=false
183 | permissions/write_settings=false
184 | permissions/write_sms=false
185 | permissions/write_social_stream=false
186 | permissions/write_sync_settings=false
187 | permissions/write_user_dictionary=false
188 | screen/immersive_mode=true
189 | screen/orientation=0
190 | screen/support_large=true
191 | screen/support_normal=true
192 | screen/support_small=true
193 | screen/support_xlarge=true
194 | screen/use_32_bits_view=true
195 | user_permissions/0=""
196 | user_permissions/1=""
197 | user_permissions/10=""
198 | user_permissions/11=""
199 | user_permissions/12=""
200 | user_permissions/13=""
201 | user_permissions/14=""
202 | user_permissions/15=""
203 | user_permissions/16=""
204 | user_permissions/17=""
205 | user_permissions/18=""
206 | user_permissions/19=""
207 | user_permissions/2=""
208 | user_permissions/3=""
209 | user_permissions/4=""
210 | user_permissions/5=""
211 | user_permissions/6=""
212 | user_permissions/7=""
213 | user_permissions/8=""
214 | user_permissions/9=""
215 | version/code=1
216 | version/name="1.0"
217 |
218 | [platform:BlackBerry 10]
219 |
220 | debug/debugging_enabled=true
221 | package/category="core.games"
222 | package/custom_template=""
223 | package/description="Game made with Godot Engine"
224 | package/icon=""
225 | package/name=""
226 | package/unique_name="com.godot.noname"
227 | release/author="Cert. Name"
228 | release/author_id="Cert. ID"
229 | version/code=1
230 | version/name="1.0"
231 |
232 | [platform:HTML5]
233 |
234 | browser/enable_run=false
235 | custom_package/debug=""
236 | custom_package/release=""
237 | debug/debugging_enabled=true
238 | html/controls_enabled=true
239 | html/font_family="arial,sans-serif"
240 | html/head_include=""
241 | html/style_include=""
242 | html/title=""
243 | options/memory_size=3
244 |
245 | [platform:Linux X11]
246 |
247 | binary/64_bits=true
248 | custom_binary/debug="/home/fales/Programming/workspaces/git/godot/bin/godot_server.server.opt.debug.64"
249 | custom_binary/release=""
250 | debug/debugging_enabled=true
251 | resources/bundle_dependencies_(for_optical_disc)=false
252 | resources/pack_mode=0
253 |
254 | [platform:Mac OSX]
255 |
256 | application/bits_mode=0
257 | application/copyright=""
258 | application/icon=""
259 | application/identifier="org.godotengine.macgame"
260 | application/info="Made with Godot Engine"
261 | application/name=""
262 | application/short_version="1.0"
263 | application/signature="godotmacgame"
264 | application/version="1.0"
265 | custom_package/debug=""
266 | custom_package/release=""
267 | debug/debugging_enabled=true
268 | display/high_res=false
269 |
270 | [platform:Windows Desktop]
271 |
272 | binary/64_bits=true
273 | custom_binary/debug=""
274 | custom_binary/release=""
275 | debug/debugging_enabled=true
276 | resources/bundle_dependencies_(for_optical_disc)=false
277 | resources/pack_mode=1
278 |
279 | [platform:Windows Universal]
280 |
281 | architecture/target=1
282 | capabilities/all_Joyn=false
283 | capabilities/appointments=false
284 | capabilities/blocked_Chat_Messages=false
285 | capabilities/bluetooth=false
286 | capabilities/chat=false
287 | capabilities/code_Generation=false
288 | capabilities/contacts=false
289 | capabilities/enterprise_Authentication=false
290 | capabilities/internet_Client=false
291 | capabilities/internet_Client_Server=false
292 | capabilities/location=false
293 | capabilities/microphone=false
294 | capabilities/music_Library=false
295 | capabilities/objects3_D=false
296 | capabilities/phone_Call=false
297 | capabilities/pictures_Library=false
298 | capabilities/private_Network_Client_Server=false
299 | capabilities/proximity=false
300 | capabilities/removable_Storage=false
301 | capabilities/shared_User_Certificates=false
302 | capabilities/user_Account_Information=false
303 | capabilities/videos_Library=false
304 | capabilities/voip_Call=false
305 | capabilities/webcam=false
306 | command_line/extra_args=""
307 | custom_package/debug=""
308 | custom_package/release=""
309 | debug/debugging_enabled=true
310 | identity/product_guid="00000000-0000-0000-0000-000000000000"
311 | identity/publisher_guid="00000000-0000-0000-0000-000000000000"
312 | images/background_color="transparent"
313 | images/splash_screen=null
314 | images/square150x150_logo=null
315 | images/square310x310_logo=null
316 | images/square44x44_logo=null
317 | images/square71x71_logo=null
318 | images/store_logo=null
319 | images/wide310x150_logo=null
320 | orientation/landscape=true
321 | orientation/landscape_flipped=true
322 | orientation/portrait=true
323 | orientation/portrait_flipped=true
324 | package/description="Godot Engine"
325 | package/display_name=""
326 | package/publisher="CN=GodotEngine"
327 | package/publisher_display_name="Godot Engine"
328 | package/short_name="Godot"
329 | package/unique_name="Godot.Engine"
330 | tiles/show_name_on_square150x150=false
331 | tiles/show_name_on_square310x310=false
332 | tiles/show_name_on_wide310x150=false
333 | version/build=0
334 | version/major=1
335 | version/minor=0
336 | version/revision=0
337 |
338 | [script]
339 |
340 | action="compile"
341 | encrypt_key=""
342 |
--------------------------------------------------------------------------------
/demo/EnetNode/fonts/mono-bold-20.fnt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Faless/godot-enet-better/fc294ca1f418cfcd8e9864620dee8b52fbc49eca/demo/EnetNode/fonts/mono-bold-20.fnt
--------------------------------------------------------------------------------
/demo/EnetNode/fonts/mono-bold-20.sv.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Faless/godot-enet-better/fc294ca1f418cfcd8e9864620dee8b52fbc49eca/demo/EnetNode/fonts/mono-bold-20.sv.png
--------------------------------------------------------------------------------
/demo/EnetNode/fonts/mono-bold-20.sv.png.flags:
--------------------------------------------------------------------------------
1 | gen_mipmaps=false
2 |
--------------------------------------------------------------------------------
/demo/EnetNode/fonts/mono-regular-18.fnt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Faless/godot-enet-better/fc294ca1f418cfcd8e9864620dee8b52fbc49eca/demo/EnetNode/fonts/mono-regular-18.fnt
--------------------------------------------------------------------------------
/demo/EnetNode/fonts/mono-regular-18.sv.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Faless/godot-enet-better/fc294ca1f418cfcd8e9864620dee8b52fbc49eca/demo/EnetNode/fonts/mono-regular-18.sv.png
--------------------------------------------------------------------------------
/demo/EnetNode/fonts/mono-regular-18.sv.png.flags:
--------------------------------------------------------------------------------
1 | gen_mipmaps=false
2 |
--------------------------------------------------------------------------------
/demo/EnetNode/fonts/originals/AUTHORS:
--------------------------------------------------------------------------------
1 | AUTHORS
2 |
3 | Current Contributors (sorted alphabetically):
4 | - Pravin Satpute
5 | Project Owner (Current)
6 | Red Hat, Inc.
7 |
8 | Previous Contributors
9 |
10 | - Steve Matteson
11 | Original Designer
12 | Ascender, Inc.
13 |
--------------------------------------------------------------------------------
/demo/EnetNode/fonts/originals/LICENSE:
--------------------------------------------------------------------------------
1 | Digitized data copyright (c) 2010 Google Corporation
2 | with Reserved Font Arimo, Tinos and Cousine.
3 | Copyright (c) 2012 Red Hat, Inc.
4 | with Reserved Font Name Liberation.
5 |
6 | This Font Software is licensed under the SIL Open Font License,
7 | Version 1.1.
8 |
9 | This license is copied below, and is also available with a FAQ at:
10 | http://scripts.sil.org/OFL
11 |
12 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
13 |
14 | PREAMBLE The goals of the Open Font License (OFL) are to stimulate
15 | worldwide development of collaborative font projects, to support the font
16 | creation efforts of academic and linguistic communities, and to provide
17 | a free and open framework in which fonts may be shared and improved in
18 | partnership with others.
19 |
20 | The OFL allows the licensed fonts to be used, studied, modified and
21 | redistributed freely as long as they are not sold by themselves.
22 | The fonts, including any derivative works, can be bundled, embedded,
23 | redistributed and/or sold with any software provided that any reserved
24 | names are not used by derivative works. The fonts and derivatives,
25 | however, cannot be released under any other type of license. The
26 | requirement for fonts to remain under this license does not apply to
27 | any document created using the fonts or their derivatives.
28 |
29 |
30 |
31 | DEFINITIONS
32 | "Font Software" refers to the set of files released by the Copyright
33 | Holder(s) under this license and clearly marked as such.
34 | This may include source files, build scripts and documentation.
35 |
36 | "Reserved Font Name" refers to any names specified as such after the
37 | copyright statement(s).
38 |
39 | "Original Version" refers to the collection of Font Software components
40 | as distributed by the Copyright Holder(s).
41 |
42 | "Modified Version" refers to any derivative made by adding to, deleting,
43 | or substituting ? in part or in whole ?
44 | any of the components of the Original Version, by changing formats or
45 | by porting the Font Software to a new environment.
46 |
47 | "Author" refers to any designer, engineer, programmer, technical writer
48 | or other person who contributed to the Font Software.
49 |
50 |
51 | PERMISSION & CONDITIONS
52 |
53 | Permission is hereby granted, free of charge, to any person obtaining a
54 | copy of the Font Software, to use, study, copy, merge, embed, modify,
55 | redistribute, and sell modified and unmodified copies of the Font
56 | Software, subject to the following conditions:
57 |
58 | 1) Neither the Font Software nor any of its individual components,in
59 | Original or Modified Versions, may be sold by itself.
60 |
61 | 2) Original or Modified Versions of the Font Software may be bundled,
62 | redistributed and/or sold with any software, provided that each copy
63 | contains the above copyright notice and this license. These can be
64 | included either as stand-alone text files, human-readable headers or
65 | in the appropriate machine-readable metadata fields within text or
66 | binary files as long as those fields can be easily viewed by the user.
67 |
68 | 3) No Modified Version of the Font Software may use the Reserved Font
69 | Name(s) unless explicit written permission is granted by the
70 | corresponding Copyright Holder. This restriction only applies to the
71 | primary font name as presented to the users.
72 |
73 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
74 | Software shall not be used to promote, endorse or advertise any
75 | Modified Version, except to acknowledge the contribution(s) of the
76 | Copyright Holder(s) and the Author(s) or with their explicit written
77 | permission.
78 |
79 | 5) The Font Software, modified or unmodified, in part or in whole, must
80 | be distributed entirely under this license, and must not be distributed
81 | under any other license. The requirement for fonts to remain under
82 | this license does not apply to any document created using the Font
83 | Software.
84 |
85 |
86 |
87 | TERMINATION
88 | This license becomes null and void if any of the above conditions are not met.
89 |
90 |
91 |
92 | DISCLAIMER
93 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
94 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
95 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
96 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
97 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
98 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
99 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
100 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER
101 | DEALINGS IN THE FONT SOFTWARE.
102 |
103 |
--------------------------------------------------------------------------------
/demo/EnetNode/fonts/originals/LiberationMono-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Faless/godot-enet-better/fc294ca1f418cfcd8e9864620dee8b52fbc49eca/demo/EnetNode/fonts/originals/LiberationMono-Bold.ttf
--------------------------------------------------------------------------------
/demo/EnetNode/fonts/originals/LiberationMono-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Faless/godot-enet-better/fc294ca1f418cfcd8e9864620dee8b52fbc49eca/demo/EnetNode/fonts/originals/LiberationMono-Regular.ttf
--------------------------------------------------------------------------------
/demo/EnetNode/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Faless/godot-enet-better/fc294ca1f418cfcd8e9864620dee8b52fbc49eca/demo/EnetNode/icon.png
--------------------------------------------------------------------------------
/demo/EnetNode/icon.png.flags:
--------------------------------------------------------------------------------
1 | gen_mipmaps=false
2 |
--------------------------------------------------------------------------------
/demo/EnetNode/server.gd:
--------------------------------------------------------------------------------
1 |
2 | extends Panel
3 |
4 | var client = preload("res://client.xscn")
5 | var clients = []
6 | var server_peer = ENetPacketPeer.new()
7 |
8 | var udp_port = 4666
9 |
10 | onready var container = get_node("Client/Container")
11 | onready var server_log = get_node("Server/ScrollContainer/ServerLog")
12 | onready var server = get_node("Server/ScrollContainer/ENetNode")
13 | onready var scroll = get_node("Server/ScrollContainer")
14 |
15 | func _ready():
16 | # Sent when a client disconnects
17 | server.connect("network_peer_disconnected", self, "server_client_disconnect")
18 | # Sent when a new client connects
19 | server.connect("network_peer_connected", self, "server_client_connect")
20 | # Sent when a valid UDP packet is received from a client
21 | server.connect("peer_packet", self, "on_peer_packet")
22 |
23 | # Create a server on port udp_port with 16 custom channels
24 | server_peer.create_server(udp_port, 16)
25 | server.set_network_peer(server_peer)
26 |
27 | set_process(true)
28 |
29 |
30 | func on_peer_packet(id, cmd, pkt):
31 | write_log(str(id) + " - CMD: " + str(cmd) + " DATA:" + str(Array(pkt)))
32 |
33 | func server_client_connect(id):
34 | write_log(str(id) + " - Connected")
35 | clients.append(id)
36 |
37 | func server_client_disconnect(id):
38 | write_log(str(id) + " - Disconnected")
39 |
40 |
41 |
42 | ### Scene functions
43 | func _process(delta):
44 | scroll.set_v_scroll(scroll.get_v_scroll()+1000)
45 |
46 | func spawn_client():
47 | var spawn = client.instance()
48 | container.add_child(spawn)
49 |
50 | func write_log(msg):
51 | print(msg)
52 | server_log.set_text(server_log.get_text()+"\n"+str(msg))
53 |
54 | func _on_RemoveClient_pressed():
55 | if clients.size() > 0:
56 | var c = clients[0]
57 | server.kick_client(c)
58 | clients.remove(0)
59 |
60 | func _on_AddClient_pressed():
61 | spawn_client()
62 |
63 | func _on_BcastTCP_pressed():
64 | server.broadcast(RawArray([11,12,23]), 1)
65 |
66 | func _on_BcastUDP_pressed():
67 | server.broadcast_ordered(RawArray([57,12,23,1,1,1,2,3]), 0)
68 |
--------------------------------------------------------------------------------
/demo/EnetNode/server.xscn:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | "conn_count"
9 | 4
10 | "conns"
11 | 3, 0, 46, 45, 2, 0, 5, 0, 46, 47, 2, 0, 11, 0, 46, 48, 2, 0, 13, 0, 46, 49, 2, 0
12 | "editable_instances"
13 |
14 |
15 | "names"
16 |
17 | "Panel"
18 | "anchor/right"
19 | "anchor/bottom"
20 | "focus/ignore_mouse"
21 | "focus/stop_mouse"
22 | "size_flags/horizontal"
23 | "size_flags/vertical"
24 | "margin/left"
25 | "margin/top"
26 | "margin/right"
27 | "margin/bottom"
28 | "script/script"
29 | "Server"
30 | "HBoxContainer"
31 | "custom_constants/separation"
32 | "alignment"
33 | "BcastUDP"
34 | "custom_fonts/font"
35 | "toggle_mode"
36 | "enabled_focus_mode"
37 | "shortcut"
38 | "text"
39 | "flat"
40 | "Button"
41 | "ServerTitle"
42 | "align"
43 | "valign"
44 | "percent_visible"
45 | "lines_skipped"
46 | "max_lines_visible"
47 | "Label"
48 | "BcastTCP"
49 | "ScrollContainer"
50 | "scroll/horizontal"
51 | "scroll/vertical"
52 | "ServerLog"
53 | "ENetNode"
54 | "signal_mode"
55 | "Client"
56 | "anchor/top"
57 | "editor/display_folded"
58 | "RemoveClient"
59 | "ClientTitle"
60 | "AddClient"
61 | "Container"
62 | "_on_BcastUDP_pressed"
63 | "pressed"
64 | "_on_BcastTCP_pressed"
65 | "_on_RemoveClient_pressed"
66 | "_on_AddClient_pressed"
67 |
68 | "node_count"
69 | 15
70 | "node_paths"
71 |
72 |
73 | "nodes"
74 | -1, -1, 0, 0, -1, 11, 1, 0, 2, 0, 3, 1, 4, 2, 5, 3, 6, 3, 7, 4, 8, 4, 9, 4, 10, 4, 11, 5, 0, 0, 0, 0, 12, -1, 10, 1, 0, 2, 3, 3, 1, 4, 2, 5, 3, 6, 3, 7, 4, 8, 4, 9, 4, 10, 6, 0, 1, 0, 13, 13, -1, 11, 1, 0, 3, 1, 4, 1, 5, 3, 6, 3, 7, 4, 8, 4, 9, 4, 10, 7, 14, 8, 15, 0, 0, 2, 0, 23, 16, -1, 14, 3, 1, 4, 2, 5, 3, 6, 3, 7, 9, 8, 4, 9, 10, 10, 7, 17, 11, 18, 1, 19, 3, 20, 12, 21, 13, 22, 1, 0, 2, 0, 30, 24, -1, 15, 3, 2, 4, 2, 5, 3, 6, 14, 7, 15, 8, 16, 9, 17, 10, 18, 17, 19, 21, 20, 25, 0, 26, 0, 27, 21, 28, 14, 29, 22, 0, 2, 0, 23, 31, -1, 14, 3, 1, 4, 2, 5, 3, 6, 3, 7, 23, 8, 4, 9, 24, 10, 7, 17, 11, 18, 1, 19, 3, 20, 12, 21, 25, 22, 1, 0, 1, 0, 32, 32, -1, 12, 1, 0, 2, 0, 3, 1, 4, 2, 5, 3, 6, 3, 7, 4, 8, 7, 9, 4, 10, 4, 33, 2, 34, 2, 0, 6, 0, 30, 35, -1, 12, 3, 1, 4, 2, 5, 3, 6, 3, 7, 26, 8, 26, 9, 4, 10, 27, 17, 19, 27, 21, 28, 14, 29, 22, 0, 6, 0, 36, 36, -1, 1, 37, 0, 0, 0, 0, 0, 38, -1, 11, 39, 3, 1, 0, 2, 0, 3, 2, 4, 2, 5, 3, 6, 14, 7, 4, 8, 6, 9, 4, 10, 4, 0, 9, 0, 13, 13, -1, 12, 40, 2, 1, 0, 3, 1, 4, 1, 5, 3, 6, 3, 7, 4, 8, 4, 9, 4, 10, 7, 14, 8, 15, 0, 0, 10, 0, 23, 41, -1, 13, 3, 1, 4, 2, 5, 3, 6, 3, 7, 28, 8, 4, 9, 29, 10, 7, 18, 1, 19, 3, 20, 12, 21, 30, 22, 1, 0, 10, 0, 30, 42, -1, 15, 3, 2, 4, 2, 5, 3, 6, 14, 7, 31, 8, 16, 9, 32, 10, 18, 17, 19, 21, 33, 25, 0, 26, 0, 27, 21, 28, 14, 29, 22, 0, 10, 0, 23, 43, -1, 13, 3, 1, 4, 2, 5, 3, 6, 3, 7, 34, 8, 4, 9, 35, 10, 7, 18, 1, 19, 3, 20, 12, 21, 36, 22, 1, 0, 9, 0, 13, 44, -1, 11, 1, 0, 2, 0, 3, 1, 4, 1, 5, 3, 6, 3, 7, 4, 8, 7, 9, 4, 10, 4, 15, 14, 0
75 | "variants"
76 |
77 | 1
78 | False
79 | True
80 | 2
81 | 0
82 |
83 | 0.5
84 | 50
85 | 20
86 | 282
87 | 426
88 |
89 | "Broacast UDP"
90 | 0
91 | 446
92 | 15
93 | 566
94 | 34
95 |
96 | "Server Log"
97 | 1
98 | -1
99 | 586
100 | 741
101 | "Broadcast TCP"
102 | -0
103 | 19
104 | 334
105 | 439
106 | "Remove Client"
107 | 459
108 | 591
109 | "Client Logs"
110 | 611
111 | 689
112 | "Add Client"
113 |
114 | "version"
115 | 2
116 |
117 |
118 |
119 |
--------------------------------------------------------------------------------
/modules/benet/SCsub:
--------------------------------------------------------------------------------
1 | Import('env')
2 | Import('env_modules')
3 |
4 | # Thirdparty source files
5 |
6 | env_benet = env_modules.Clone()
7 |
8 | if env["builtin_enet"]: # builtin
9 | thirdparty_dir = "#thirdparty/enet/"
10 | thirdparty_sources = [
11 | "callbacks.c",
12 | "compress.c",
13 | "host.c",
14 | "list.c",
15 | "packet.c",
16 | "peer.c",
17 | "protocol.c",
18 | "godot.cpp"
19 | ]
20 | thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
21 |
22 | # env_benet.add_source_files(env.modules_sources, thirdparty_sources)
23 | env_benet.Append(CPPPATH=[thirdparty_dir])
24 | env_benet.Append(CPPFLAGS=["-DGODOT_ENET"])
25 |
26 | env_benet.add_source_files(env.modules_sources, "*.cpp")
27 |
--------------------------------------------------------------------------------
/modules/benet/config.py:
--------------------------------------------------------------------------------
1 | def can_build(env, platform):
2 | return True
3 |
4 |
5 | def configure(env):
6 | pass
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/modules/benet/enet_node.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include "modules/benet/enet_node.h"
3 | #include "core/engine.h"
4 |
5 | void ENetNode::_notification(int p_what) {
6 | if(!is_inside_tree() || Engine::get_singleton()->is_editor_hint() || !network_peer.is_valid())
7 | return;
8 |
9 | if(p_what == NOTIFICATION_PHYSICS_PROCESS) {
10 | if(poll_mode == MODE_PHYSICS)
11 | _network_poll();
12 | if(signal_mode == MODE_PHYSICS)
13 | _network_process();
14 | } else if (p_what == NOTIFICATION_PROCESS) {
15 | if(poll_mode == MODE_IDLE)
16 | _network_poll();
17 | if(signal_mode == MODE_IDLE)
18 | _network_process();
19 | }
20 | }
21 |
22 | void ENetNode::_update_process_mode() {
23 |
24 | bool idle = signal_mode == MODE_IDLE || poll_mode == MODE_IDLE;
25 | bool physics = signal_mode == MODE_PHYSICS || poll_mode == MODE_PHYSICS;
26 |
27 | if (is_physics_processing() && !physics) {
28 | set_physics_process(false);
29 | }
30 | if (is_processing() && !idle) {
31 | set_process(false);
32 | }
33 |
34 | if(idle && !is_processing()) {
35 | set_process(true);
36 | }
37 | if(physics && !is_physics_processing()) {
38 | set_physics_process(true);
39 | }
40 | }
41 |
42 | void ENetNode::set_signal_mode(NetProcessMode p_mode) {
43 |
44 | if(signal_mode == p_mode)
45 | return;
46 |
47 | signal_mode = p_mode;
48 |
49 | _update_process_mode();
50 | }
51 |
52 | ENetNode::NetProcessMode ENetNode::get_signal_mode() const{
53 | return signal_mode;
54 | }
55 |
56 | void ENetNode::set_poll_mode(NetProcessMode p_mode) {
57 |
58 | if(poll_mode == p_mode)
59 | return;
60 |
61 | poll_mode = p_mode;
62 |
63 | _update_process_mode();
64 | }
65 |
66 | ENetNode::NetProcessMode ENetNode::get_poll_mode() const{
67 | return poll_mode;
68 | }
69 |
70 | void ENetNode::set_network_peer(const Ref& p_network_peer) {
71 | if (network_peer.is_valid()) {
72 | network_peer->disconnect("peer_connected",this,"_network_peer_connected");
73 | network_peer->disconnect("peer_disconnected",this,"_network_peer_disconnected");
74 | network_peer->disconnect("connection_succeeded",this,"_connected_to_server");
75 | network_peer->disconnect("connection_failed",this,"_connection_failed");
76 | network_peer->disconnect("server_disconnected",this,"_server_disconnected");
77 | connected_peers.clear();
78 | //path_get_cache.clear();
79 | //path_send_cache.clear();
80 | //last_send_cache_id=1;
81 | }
82 |
83 | ERR_FAIL_COND_MSG(p_network_peer.is_valid() && p_network_peer->get_connection_status()==NetworkedMultiplayerPeer::CONNECTION_DISCONNECTED, "Supplied NetworkedNetworkPeer must be connecting or connected.");
84 |
85 | network_peer=p_network_peer;
86 |
87 | if (network_peer.is_valid()) {
88 | network_peer->connect("peer_connected",this,"_network_peer_connected");
89 | network_peer->connect("peer_disconnected",this,"_network_peer_disconnected");
90 | network_peer->connect("connection_succeeded",this,"_connected_to_server");
91 | network_peer->connect("connection_failed",this,"_connection_failed");
92 | network_peer->connect("server_disconnected",this,"_server_disconnected");
93 | }
94 | }
95 |
96 | bool ENetNode::is_network_server() const {
97 |
98 | ERR_FAIL_COND_V(!network_peer.is_valid(),false);
99 | return network_peer->is_server();
100 |
101 | }
102 |
103 | int ENetNode::get_network_unique_id() const {
104 |
105 | ERR_FAIL_COND_V(!network_peer.is_valid(),0);
106 | return network_peer->get_unique_id();
107 | }
108 |
109 | Error ENetNode::kick_client(int p_id) {
110 |
111 | ERR_FAIL_COND_V(!network_peer.is_valid(),ERR_UNCONFIGURED);
112 |
113 | return network_peer->disconnect_peer(p_id);
114 | }
115 |
116 | void ENetNode::_network_peer_connected(int p_id) {
117 |
118 | connected_peers.insert(p_id);
119 | //path_get_cache.insert(p_id,PathGetCache());
120 | emit_signal("network_peer_connected",p_id);
121 | }
122 |
123 | void ENetNode::_network_peer_disconnected(int p_id) {
124 |
125 | connected_peers.erase(p_id);
126 | //path_get_cache.erase(p_id); //I no longer need your cache, sorry
127 | emit_signal("network_peer_disconnected",p_id);
128 | }
129 |
130 | void ENetNode::_connected_to_server() {
131 |
132 | emit_signal("connected_to_server");
133 | }
134 |
135 | void ENetNode::_connection_failed() {
136 |
137 | emit_signal("connection_failed");
138 | }
139 |
140 | void ENetNode::_server_disconnected() {
141 |
142 | emit_signal("server_disconnected");
143 | }
144 |
145 | Error ENetNode::broadcast(const PoolVector &p_packet, int p_channel) {
146 | return put_packet(NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE, 0, p_packet, p_channel);
147 | }
148 |
149 | Error ENetNode::send(int p_id, const PoolVector &p_packet, int p_channel) {
150 | return put_packet(NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE, p_id, p_packet, p_channel);
151 | }
152 |
153 | Error ENetNode::broadcast_unreliable(const PoolVector &p_packet, int p_channel) {
154 | return put_packet(NetworkedMultiplayerPeer::TRANSFER_MODE_UNRELIABLE, 0, p_packet, p_channel);
155 | }
156 |
157 | Error ENetNode::send_unreliable(int p_id, const PoolVector &p_packet, int p_channel) {
158 | return put_packet(NetworkedMultiplayerPeer::TRANSFER_MODE_UNRELIABLE, p_id, p_packet, p_channel);
159 | }
160 |
161 | Error ENetNode::broadcast_ordered(const PoolVector &p_packet, int p_channel) {
162 | return put_packet(NetworkedMultiplayerPeer::TRANSFER_MODE_UNRELIABLE_ORDERED, 0, p_packet, p_channel);
163 | }
164 |
165 | Error ENetNode::send_ordered(int p_id, const PoolVector &p_packet, int p_channel) {
166 | return put_packet(NetworkedMultiplayerPeer::TRANSFER_MODE_UNRELIABLE_ORDERED, p_id, p_packet, p_channel);
167 | }
168 |
169 | Error ENetNode::put_packet(NetworkedMultiplayerPeer::TransferMode p_mode, int p_target, const PoolVector &p_packet, int p_channel) {
170 | ERR_FAIL_COND_V(!network_peer.is_valid(),ERR_UNCONFIGURED);
171 |
172 | network_peer->set_transfer_mode(p_mode);
173 | network_peer->set_target_peer(p_target);
174 | return network_peer->_put_packet_channel(p_packet, p_channel);
175 | }
176 |
177 | void ENetNode::_network_poll() {
178 |
179 | if (!network_peer.is_valid() || network_peer->get_connection_status()==NetworkedMultiplayerPeer::CONNECTION_DISCONNECTED)
180 | return;
181 |
182 | network_peer->poll();
183 | }
184 |
185 | void ENetNode::_network_process() {
186 |
187 | if (!network_peer.is_valid() || network_peer->get_connection_status()==NetworkedMultiplayerPeer::CONNECTION_DISCONNECTED)
188 | return;
189 |
190 | while(network_peer->get_available_packet_count()) {
191 |
192 | int sender = network_peer->get_packet_peer();
193 | int channel = network_peer->get_packet_channel();
194 |
195 | if(channel==-1) {
196 |
197 | int len;
198 | const uint8_t *packet;
199 |
200 | Error err = network_peer->get_packet(&packet,len);
201 | if (err!=OK) {
202 | ERR_PRINT("Error getting packet!");
203 | }
204 |
205 | _network_process_packet(sender,packet,len);
206 |
207 | } else {
208 |
209 | PoolVector pkt;
210 |
211 | Error err = network_peer->get_packet_buffer(pkt);
212 | if (err!=OK) {
213 | ERR_PRINT("Error getting packet!");
214 | }
215 |
216 | if(sender == 1) {
217 | emit_signal("server_packet", channel, pkt);
218 | }
219 | else {
220 | emit_signal("peer_packet", sender, channel, pkt);
221 | }
222 |
223 | }
224 |
225 | if (!network_peer.is_valid()) {
226 | break; //it's also possible that a packet or RPC caused a disconnection, so also check here
227 | }
228 | }
229 |
230 |
231 | }
232 |
233 | void ENetNode::_network_process_packet(int p_from, const uint8_t* p_packet, int p_packet_len) {
234 | // Not implemented yet!
235 | /*
236 | ERR_FAIL_COND(p_packet_len<5);
237 |
238 | uint8_t packet_type = p_packet[0];
239 |
240 | switch(packet_type) {
241 |
242 | case NETWORK_COMMAND_REMOTE_CALL:
243 | case NETWORK_COMMAND_REMOTE_SET: {
244 |
245 | ERR_FAIL_COND(p_packet_len<5);
246 | uint32_t target = decode_uint32(&p_packet[1]);
247 |
248 |
249 | Node *node=NULL;
250 |
251 | if (target&0x80000000) {
252 |
253 | int ofs = target&0x7FFFFFFF;
254 | ERR_FAIL_COND(ofs>=p_packet_len);
255 |
256 | String paths;
257 | paths.parse_utf8((const char*)&p_packet[ofs],p_packet_len-ofs);
258 |
259 | NodePath np = paths;
260 |
261 | node = get_root()->get_node(np);
262 | if (node==NULL) {
263 | ERR_EXPLAIN("Failed to get path from RPC: "+String(np));
264 | ERR_FAIL_COND(node==NULL);
265 | }
266 | } else {
267 |
268 | int id = target;
269 |
270 | Map::Element *E=path_get_cache.find(p_from);
271 | ERR_FAIL_COND(!E);
272 |
273 | Map::Element *F=E->get().nodes.find(id);
274 | ERR_FAIL_COND(!F);
275 |
276 | PathGetCache::NodeInfo *ni = &F->get();
277 | //do proper caching later
278 |
279 | node = get_root()->get_node(ni->path);
280 | if (node==NULL) {
281 | ERR_EXPLAIN("Failed to get cached path from RPC: "+String(ni->path));
282 | ERR_FAIL_COND(node==NULL);
283 | }
284 |
285 |
286 | }
287 |
288 | ERR_FAIL_COND(p_packet_len<6);
289 |
290 | //detect cstring end
291 | int len_end=5;
292 | for(;len_end=p_packet_len);
299 |
300 | StringName name = String::utf8((const char*)&p_packet[5]);
301 |
302 |
303 |
304 |
305 | if (packet_type==NETWORK_COMMAND_REMOTE_CALL) {
306 |
307 | if (!node->can_call_rpc(name))
308 | return;
309 |
310 | int ofs = len_end+1;
311 |
312 | ERR_FAIL_COND(ofs>=p_packet_len);
313 |
314 | int argc = p_packet[ofs];
315 | Vector args;
316 | Vector argp;
317 | args.resize(argc);
318 | argp.resize(argc);
319 |
320 | ofs++;
321 |
322 | for(int i=0;i=p_packet_len);
325 | int vlen;
326 | Error err = decode_variant(args[i],&p_packet[ofs],p_packet_len-ofs,&vlen);
327 | ERR_FAIL_COND(err!=OK);
328 | //args[i]=p_packet[3+i];
329 | argp[i]=&args[i];
330 | ofs+=vlen;
331 | }
332 |
333 | Variant::CallError ce;
334 |
335 | node->call(name,argp.ptr(),argc,ce);
336 | if (ce.error!=Variant::CallError::CALL_OK) {
337 | String error = Variant::get_call_error_text(node,name,argp.ptr(),argc,ce);
338 | error="RPC - "+error;
339 | ERR_PRINTS(error);
340 | }
341 |
342 | } else {
343 |
344 | if (!node->can_call_rset(name))
345 | return;
346 |
347 | int ofs = len_end+1;
348 |
349 | ERR_FAIL_COND(ofs>=p_packet_len);
350 |
351 | Variant value;
352 | decode_variant(value,&p_packet[ofs],p_packet_len-ofs);
353 |
354 | bool valid;
355 |
356 | node->set(name,value,&valid);
357 | if (!valid) {
358 | String error = "Error setting remote property '"+String(name)+"', not found in object of type "+node->get_type();
359 | ERR_PRINTS(error);
360 | }
361 | }
362 |
363 | } break;
364 | case NETWORK_COMMAND_SIMPLIFY_PATH: {
365 |
366 | ERR_FAIL_COND(p_packet_len<5);
367 | int id = decode_uint32(&p_packet[1]);
368 |
369 | String paths;
370 | paths.parse_utf8((const char*)&p_packet[5],p_packet_len-5);
371 |
372 | NodePath path = paths;
373 |
374 | if (!path_get_cache.has(p_from)) {
375 | path_get_cache[p_from]=PathGetCache();
376 | }
377 |
378 | PathGetCache::NodeInfo ni;
379 | ni.path=path;
380 | ni.instance=0;
381 |
382 | path_get_cache[p_from].nodes[id]=ni;
383 |
384 |
385 | {
386 | //send ack
387 |
388 | //encode path
389 | CharString pname = String(path).utf8();
390 | int len = encode_cstring(pname.get_data(),NULL);
391 |
392 | Vector packet;
393 |
394 | packet.resize(1+len);
395 | packet[0]=NETWORK_COMMAND_CONFIRM_PATH;
396 | encode_cstring(pname.get_data(),&packet[1]);
397 |
398 | network_peer->set_transfer_mode(NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE);
399 | network_peer->set_target_peer(p_from);
400 | network_peer->put_packet(packet.ptr(),packet.size(),0);
401 | }
402 | } break;
403 | case NETWORK_COMMAND_CONFIRM_PATH: {
404 |
405 | String paths;
406 | paths.parse_utf8((const char*)&p_packet[1],p_packet_len-1);
407 |
408 | NodePath path = paths;
409 |
410 | PathSentCache *psc = path_send_cache.getptr(path);
411 | ERR_FAIL_COND(!psc);
412 |
413 | Map::Element *E=psc->confirmed_peers.find(p_from);
414 | ERR_FAIL_COND(!E);
415 | E->get()=true;
416 | } break;
417 | }
418 | */
419 | }
420 |
421 | void ENetNode::_bind_methods() {
422 | ADD_SIGNAL( MethodInfo("network_peer_connected",PropertyInfo(Variant::INT,"id")));
423 | ADD_SIGNAL( MethodInfo("network_peer_disconnected",PropertyInfo(Variant::INT,"id")));
424 |
425 | ADD_SIGNAL( MethodInfo("connected_to_server"));
426 | ADD_SIGNAL( MethodInfo("connection_failed"));
427 | ADD_SIGNAL( MethodInfo("server_disconnected"));
428 |
429 | ADD_SIGNAL( MethodInfo("server_packet",PropertyInfo(Variant::INT,"channel"),PropertyInfo(Variant::POOL_BYTE_ARRAY,"packet")));
430 | ADD_SIGNAL( MethodInfo("peer_packet",PropertyInfo(Variant::INT,"peer"),PropertyInfo(Variant::INT,"channel"),PropertyInfo(Variant::POOL_BYTE_ARRAY,"packet")));
431 |
432 | ClassDB::bind_method(D_METHOD("set_network_peer","peer"),&ENetNode::set_network_peer);
433 | ClassDB::bind_method(D_METHOD("_network_peer_connected"),&ENetNode::_network_peer_connected);
434 | ClassDB::bind_method(D_METHOD("_network_peer_disconnected"),&ENetNode::_network_peer_disconnected);
435 | ClassDB::bind_method(D_METHOD("_connected_to_server"),&ENetNode::_connected_to_server);
436 | ClassDB::bind_method(D_METHOD("_connection_failed"),&ENetNode::_connection_failed);
437 | ClassDB::bind_method(D_METHOD("_server_disconnected"),&ENetNode::_server_disconnected);
438 |
439 | // Basic infos
440 | ClassDB::bind_method(D_METHOD("is_network_server"),&ENetNode::is_network_server);
441 | ClassDB::bind_method(D_METHOD("get_network_unique_id"),&ENetNode::get_network_unique_id);
442 |
443 |
444 | // Signal Handling
445 | BIND_ENUM_CONSTANT(MODE_IDLE);
446 | BIND_ENUM_CONSTANT(MODE_PHYSICS);
447 | ClassDB::bind_method(D_METHOD("set_signal_mode","mode"),&ENetNode::set_signal_mode);
448 | ClassDB::bind_method(D_METHOD("get_signal_mode"),&ENetNode::get_signal_mode);
449 | ADD_PROPERTY( PropertyInfo(Variant::INT,"signal_mode",PROPERTY_HINT_ENUM,"Idle,Fixed"),"set_signal_mode","get_signal_mode");
450 | ClassDB::bind_method(D_METHOD("set_poll_mode","mode"),&ENetNode::set_poll_mode);
451 | ClassDB::bind_method(D_METHOD("get_poll_mode"),&ENetNode::get_poll_mode);
452 | ADD_PROPERTY( PropertyInfo(Variant::INT,"poll_mode",PROPERTY_HINT_ENUM,"Idle,Fixed"),"set_poll_mode","get_poll_mode");
453 |
454 |
455 | // General purpose method
456 | ClassDB::bind_method(D_METHOD("put_packet", "mode", "target", "pkt","channel"),&ENetNode::put_packet);
457 | ClassDB::bind_method(D_METHOD("kick_client", "id"),&ENetNode::kick_client);
458 |
459 | // Reliable
460 | ClassDB::bind_method(D_METHOD("broadcast", "pkt","channel"),&ENetNode::broadcast);
461 | ClassDB::bind_method(D_METHOD("send", "target", "pkt","channel"),&ENetNode::send);
462 | // Unreliable
463 | ClassDB::bind_method(D_METHOD("broadcast_unreliable", "pkt","channel"),&ENetNode::broadcast_unreliable);
464 | ClassDB::bind_method(D_METHOD("send_unreliable", "target", "pkt","channel"),&ENetNode::send_unreliable);
465 | // Ordered
466 | ClassDB::bind_method(D_METHOD("broadcast_ordered", "pkt","channel"),&ENetNode::broadcast_ordered);
467 | ClassDB::bind_method(D_METHOD("send_ordered", "target", "pkt","channel"),&ENetNode::send_ordered);
468 | }
469 |
470 | ENetNode::ENetNode() {
471 | poll_mode = MODE_IDLE;
472 | signal_mode = MODE_IDLE;
473 |
474 | network_peer = Ref();
475 |
476 | _update_process_mode();
477 | }
478 |
479 | ENetNode::~ENetNode() {
480 |
481 | }
482 |
483 |
484 |
--------------------------------------------------------------------------------
/modules/benet/enet_node.h:
--------------------------------------------------------------------------------
1 | #ifndef NETWORKED_MULTIPLAYER_NODE_H
2 | #define NETWORKED_MULTIPLAYER_NODE_H
3 |
4 | #include "scene/main/node.h"
5 | #include "core/io/networked_multiplayer_peer.h"
6 | #include "modules/benet/enet_packet_peer.h"
7 |
8 | class ENetNode: public Node {
9 |
10 | GDCLASS( ENetNode, Node );
11 |
12 | public:
13 |
14 | enum NetProcessMode {
15 | MODE_IDLE,
16 | MODE_PHYSICS
17 | };
18 |
19 | private:
20 |
21 | Ref network_peer;
22 | Set connected_peers;
23 | NetProcessMode poll_mode;
24 | NetProcessMode signal_mode;
25 |
26 | void _network_poll();
27 | void _network_process();
28 | void _network_process_packet(int p_from, const uint8_t* p_packet, int p_packet_len);
29 |
30 | void _network_peer_connected(int p_id);
31 | void _network_peer_disconnected(int p_id);
32 |
33 | void _connected_to_server();
34 | void _connection_failed();
35 | void _server_disconnected();
36 | void _update_process_mode();
37 |
38 | protected:
39 | void _notification(int p_what);
40 | static void _bind_methods();
41 |
42 | public:
43 |
44 | void set_network_peer(const Ref& p_network_peer);
45 |
46 | void set_signal_mode(NetProcessMode p_mode);
47 | NetProcessMode get_signal_mode() const;
48 | void set_poll_mode(NetProcessMode p_mode);
49 | NetProcessMode get_poll_mode() const;
50 |
51 | bool is_network_server() const;
52 | int get_network_unique_id() const;
53 | Error kick_client(int p_id);
54 |
55 | Error broadcast(const PoolVector &p_packet, int p_channel=0);
56 | Error send(int p_id, const PoolVector &p_packet, int p_channel=0);
57 | Error broadcast_unreliable(const PoolVector &p_packet, int p_channel=0);
58 | Error send_unreliable(int p_id, const PoolVector &p_packet, int p_channel=0);
59 | Error broadcast_ordered(const PoolVector &p_packet, int p_channel=0);
60 | Error send_ordered(int p_id, const PoolVector &p_packet, int p_channel=0);
61 | Error put_packet(NetworkedMultiplayerPeer::TransferMode p_mode, int p_target, const PoolVector &p_packet, int p_channel=0);
62 |
63 | ENetNode();
64 | ~ENetNode();
65 |
66 | };
67 |
68 | VARIANT_ENUM_CAST(ENetNode::NetProcessMode);
69 |
70 | #endif
71 |
--------------------------------------------------------------------------------
/modules/benet/enet_packet_peer.cpp:
--------------------------------------------------------------------------------
1 | #include "enet_packet_peer.h"
2 | #include "core/io/marshalls.h"
3 | #include "core/os/os.h"
4 |
5 | void ENetPacketPeer::set_transfer_mode(TransferMode p_mode) {
6 |
7 | transfer_mode = p_mode;
8 | }
9 |
10 | NetworkedMultiplayerPeer::TransferMode ENetPacketPeer::get_transfer_mode() const {
11 |
12 | return transfer_mode;
13 | }
14 |
15 | void ENetPacketPeer::set_target_peer(int p_peer) {
16 |
17 | target_peer = p_peer;
18 | }
19 |
20 | int ENetPacketPeer::get_packet_peer() const {
21 |
22 | ERR_FAIL_COND_V(!active, 1);
23 | ERR_FAIL_COND_V(incoming_packets.size() == 0, 1);
24 |
25 | return incoming_packets.front()->get().from;
26 | }
27 |
28 | int ENetPacketPeer::get_packet_channel() const {
29 |
30 | ERR_FAIL_COND_V(!active, 1);
31 | ERR_FAIL_COND_V(incoming_packets.size() == 0, 1);
32 |
33 | return incoming_packets.front()->get().channel;
34 | }
35 |
36 | Error ENetPacketPeer::disconnect_peer(int p_id) {
37 |
38 | ERR_FAIL_COND_V(!active, ERR_UNCONFIGURED);
39 | ERR_FAIL_COND_V(!peer_map.has(p_id), ERR_DOES_NOT_EXIST);
40 |
41 | enet_peer_disconnect(peer_map[p_id], 0);
42 | return OK;
43 | }
44 |
45 | Error ENetPacketPeer::create_server(int p_port, int p_channels, int p_max_clients, int p_in_bandwidth, int p_out_bandwidth) {
46 |
47 | ERR_FAIL_COND_V(active, ERR_ALREADY_IN_USE);
48 |
49 | ENetAddress address;
50 |
51 | #ifdef GODOT_ENET
52 | if (bind_ip.is_wildcard()) {
53 | address.wildcard = 1;
54 | } else {
55 | enet_address_set_ip(&address, bind_ip.get_ipv6(), 16);
56 | }
57 | #else
58 | if (bind_ip.is_wildcard()) {
59 | address.host = 0;
60 | } else {
61 | ERR_FAIL_COND_V(!bind_ip.is_ipv4(), ERR_INVALID_PARAMETER);
62 | address.host = *(uint32_t *)bind_ip.get_ipv4();
63 | }
64 | #endif
65 | address.port = p_port;
66 |
67 | host = enet_host_create(&address /* the address to bind the server host to */,
68 | p_max_clients /* allow up to 32 clients and/or outgoing connections */,
69 | p_channels + SYSCH_MAX /* allow up to SYSCH_MAX channels to be used */,
70 | p_in_bandwidth /* assume any amount of incoming bandwidth */,
71 | p_out_bandwidth /* assume any amount of outgoing bandwidth */);
72 |
73 | ERR_FAIL_COND_V(!host, ERR_CANT_CREATE);
74 |
75 | _setup_compressor();
76 | active = true;
77 | server = true;
78 | refuse_connections = false;
79 | channels = p_channels + SYSCH_MAX;
80 | unique_id = 1;
81 | connection_status = CONNECTION_CONNECTED;
82 | return OK;
83 | }
84 | Error ENetPacketPeer::create_client(const IP_Address &p_ip, int p_port, int p_channels, int p_in_bandwidth, int p_out_bandwidth) {
85 |
86 | ERR_FAIL_COND_V(active, ERR_ALREADY_IN_USE);
87 |
88 | host = enet_host_create(NULL /* create a client host */,
89 | 1 /* only allow 1 outgoing connection */,
90 | p_channels + SYSCH_MAX /* allow up to SYSCH_MAX channels to be used */,
91 | p_in_bandwidth /* 56K modem with 56 Kbps downstream bandwidth */,
92 | p_out_bandwidth /* 56K modem with 14 Kbps upstream bandwidth */);
93 |
94 | ERR_FAIL_COND_V(!host, ERR_CANT_CREATE);
95 |
96 | _setup_compressor();
97 |
98 | ENetAddress address;
99 | #ifdef GODOT_ENET
100 | enet_address_set_ip(&address, p_ip.get_ipv6(), 16);
101 | #else
102 | ERR_FAIL_COND_V(!p_ip.is_ipv4(), ERR_INVALID_PARAMETER);
103 | address.host = *(uint32_t *)p_ip.get_ipv4();
104 | #endif
105 | address.port = p_port;
106 |
107 | //enet_address_set_host (& address, "localhost");
108 | //address.port = p_port;
109 |
110 | unique_id = _gen_unique_id();
111 |
112 | /* Initiate the connection, allocating the enough channels */
113 | ENetPeer *peer = enet_host_connect(host, &address, p_channels + SYSCH_MAX, unique_id);
114 |
115 | if (peer == NULL) {
116 | enet_host_destroy(host);
117 | ERR_FAIL_COND_V(!peer, ERR_CANT_CREATE);
118 | }
119 |
120 | //technically safe to ignore the peer or anything else.
121 |
122 | connection_status = CONNECTION_CONNECTING;
123 | active = true;
124 | server = false;
125 | refuse_connections = false;
126 | channels = p_channels + SYSCH_MAX;
127 |
128 | return OK;
129 | }
130 |
131 | void ENetPacketPeer::poll() {
132 |
133 | ERR_FAIL_COND(!active);
134 |
135 | _pop_current_packet();
136 |
137 | ENetEvent event;
138 | /* Wait up to 1000 milliseconds for an event. */
139 | while (true) {
140 |
141 | if (!host || !active) //might have been disconnected while emitting a notification
142 | return;
143 |
144 | int ret = enet_host_service(host, &event, 1);
145 |
146 | if (ret < 0) {
147 | //error, do something?
148 | break;
149 | } else if (ret == 0) {
150 | break;
151 | }
152 |
153 | switch (event.type) {
154 | case ENET_EVENT_TYPE_CONNECT: {
155 | /* Store any relevant client information here. */
156 |
157 | if (server && refuse_connections) {
158 | enet_peer_reset(event.peer);
159 | break;
160 | }
161 |
162 | int *new_id = memnew(int);
163 | *new_id = event.data;
164 |
165 | if (*new_id == 0) { //data zero is sent by server (enet won't let you configure this). Server is always 1
166 | *new_id = 1;
167 | }
168 |
169 | event.peer->data = new_id;
170 |
171 | peer_map[*new_id] = event.peer;
172 |
173 | connection_status = CONNECTION_CONNECTED; //if connecting, this means it connected t something!
174 |
175 | emit_signal("peer_connected", *new_id);
176 |
177 | if (server) {
178 | //someone connected, let it know of all the peers available
179 | for (Map::Element *E = peer_map.front(); E; E = E->next()) {
180 |
181 | if (E->key() == *new_id)
182 | continue;
183 | //send existing peers to new peer
184 | ENetPacket *packet = enet_packet_create(NULL, 8, ENET_PACKET_FLAG_RELIABLE);
185 | encode_uint32(SYSMSG_ADD_PEER, &packet->data[0]);
186 | encode_uint32(E->key(), &packet->data[4]);
187 | enet_peer_send(event.peer, SYSCH_CONFIG, packet);
188 | //send the new peer to existing peers
189 | packet = enet_packet_create(NULL, 8, ENET_PACKET_FLAG_RELIABLE);
190 | encode_uint32(SYSMSG_ADD_PEER, &packet->data[0]);
191 | encode_uint32(*new_id, &packet->data[4]);
192 | enet_peer_send(E->get(), SYSCH_CONFIG, packet);
193 | }
194 | } else {
195 |
196 | emit_signal("connection_succeeded");
197 | }
198 |
199 | } break;
200 | case ENET_EVENT_TYPE_DISCONNECT: {
201 |
202 | /* Reset the peer's client information. */
203 |
204 | int *id = (int *)event.peer->data;
205 |
206 | if (!id) {
207 | if (!server) {
208 | emit_signal("connection_failed");
209 | }
210 | } else {
211 |
212 | if (server) {
213 | //someone disconnected, let it know to everyone else
214 | for (Map::Element *E = peer_map.front(); E; E = E->next()) {
215 |
216 | if (E->key() == *id)
217 | continue;
218 | //send the new peer to existing peers
219 | ENetPacket *packet = enet_packet_create(NULL, 8, ENET_PACKET_FLAG_RELIABLE);
220 | encode_uint32(SYSMSG_REMOVE_PEER, &packet->data[0]);
221 | encode_uint32(*id, &packet->data[4]);
222 | enet_peer_send(E->get(), SYSCH_CONFIG, packet);
223 | }
224 | } else if (!server) {
225 | emit_signal("server_disconnected");
226 | close_connection();
227 | return;
228 | }
229 |
230 | emit_signal("peer_disconnected", *id);
231 | peer_map.erase(*id);
232 | memdelete(id);
233 | }
234 |
235 | } break;
236 | case ENET_EVENT_TYPE_RECEIVE: {
237 |
238 | if (event.channelID == SYSCH_CONFIG) {
239 | //some config message
240 | ERR_CONTINUE(event.packet->dataLength < 8);
241 |
242 | // Only server can send config messages
243 | ERR_CONTINUE(server);
244 |
245 | int msg = decode_uint32(&event.packet->data[0]);
246 | int id = decode_uint32(&event.packet->data[4]);
247 |
248 | switch (msg) {
249 | case SYSMSG_ADD_PEER: {
250 |
251 | peer_map[id] = NULL;
252 | emit_signal("peer_connected", id);
253 |
254 | } break;
255 | case SYSMSG_REMOVE_PEER: {
256 |
257 | peer_map.erase(id);
258 | emit_signal("peer_disconnected", id);
259 | } break;
260 | }
261 |
262 | enet_packet_destroy(event.packet);
263 | } else {
264 |
265 | Packet packet;
266 | packet.packet = event.packet;
267 | packet.channel = -1;
268 |
269 | if (event.channelID >= SYSCH_MAX) {
270 | packet.channel = event.channelID - SYSCH_MAX;
271 | }
272 |
273 | uint32_t *id = (uint32_t *)event.peer->data;
274 |
275 | ERR_CONTINUE(event.packet->dataLength < 12)
276 |
277 | uint32_t source = decode_uint32(&event.packet->data[0]);
278 | int target = decode_uint32(&event.packet->data[4]);
279 | uint32_t flags = decode_uint32(&event.packet->data[8]);
280 |
281 | packet.from = source;
282 |
283 | if (server) {
284 | // Someone is cheating and trying to fake the source!
285 | ERR_CONTINUE(source != *id);
286 |
287 | packet.from = *id;
288 |
289 | if (target == 0) {
290 | //re-send the everyone but sender :|
291 |
292 | incoming_packets.push_back(packet);
293 | //and make copies for sending
294 | for (Map::Element *E = peer_map.front(); E; E = E->next()) {
295 |
296 | if (uint32_t(E->key()) == source) //do not resend to self
297 | continue;
298 |
299 | ENetPacket *packet2 = enet_packet_create(packet.packet->data, packet.packet->dataLength, flags);
300 |
301 | enet_peer_send(E->get(), event.channelID, packet2);
302 | }
303 |
304 | } else if (target < 0) {
305 | //to all but one
306 |
307 | //and make copies for sending
308 | for (Map::Element *E = peer_map.front(); E; E = E->next()) {
309 |
310 | if (uint32_t(E->key()) == source || E->key() == -target) //do not resend to self, also do not send to excluded
311 | continue;
312 |
313 | ENetPacket *packet2 = enet_packet_create(packet.packet->data, packet.packet->dataLength, flags);
314 |
315 | enet_peer_send(E->get(), event.channelID, packet2);
316 | }
317 |
318 | if (-target != 1) {
319 | //server is not excluded
320 | incoming_packets.push_back(packet);
321 | } else {
322 | //server is excluded, erase packet
323 | enet_packet_destroy(packet.packet);
324 | }
325 |
326 | } else if (target == 1) {
327 | //to myself and only myself
328 | incoming_packets.push_back(packet);
329 | } else {
330 | //to someone else, specifically
331 | ERR_CONTINUE(!peer_map.has(target));
332 | enet_peer_send(peer_map[target], event.channelID, packet.packet);
333 | }
334 | } else {
335 |
336 | incoming_packets.push_back(packet);
337 | }
338 | //destroy packet later..
339 | }
340 | } break;
341 | case ENET_EVENT_TYPE_NONE: {
342 | //do nothing
343 | } break;
344 | }
345 | }
346 | }
347 |
348 | bool ENetPacketPeer::is_server() const {
349 | ERR_FAIL_COND_V(!active, false);
350 |
351 | return server;
352 | }
353 |
354 | void ENetPacketPeer::close_connection() {
355 |
356 | if (!active)
357 | return;
358 |
359 | _pop_current_packet();
360 |
361 | bool peers_disconnected = false;
362 | for (Map::Element *E = peer_map.front(); E; E = E->next()) {
363 | if (E->get()) {
364 | enet_peer_disconnect_now(E->get(), unique_id);
365 | peers_disconnected = true;
366 | }
367 | }
368 |
369 | if (peers_disconnected) {
370 | enet_host_flush(host);
371 | OS::get_singleton()->delay_usec(100); //wait 100ms for disconnection packets to send
372 | }
373 |
374 | enet_host_destroy(host);
375 | active = false;
376 | incoming_packets.clear();
377 | unique_id = 1; //server is 1
378 | connection_status = CONNECTION_DISCONNECTED;
379 | }
380 |
381 | int ENetPacketPeer::get_available_packet_count() const {
382 |
383 | return incoming_packets.size();
384 | }
385 | Error ENetPacketPeer::get_packet(const uint8_t **r_buffer, int &r_buffer_size) {
386 |
387 | ERR_FAIL_COND_V(incoming_packets.size() == 0, ERR_UNAVAILABLE);
388 |
389 | _pop_current_packet();
390 |
391 | current_packet = incoming_packets.front()->get();
392 | incoming_packets.pop_front();
393 |
394 | *r_buffer = (const uint8_t *)(¤t_packet.packet->data[12]);
395 | r_buffer_size = current_packet.packet->dataLength - 12;
396 |
397 | return OK;
398 | }
399 | Error ENetPacketPeer::put_packet(const uint8_t *p_buffer, int p_buffer_size) {
400 |
401 | int channel = SYSCH_RELIABLE;
402 |
403 | switch (transfer_mode) {
404 | case TRANSFER_MODE_UNRELIABLE: {
405 | channel = SYSCH_UNRELIABLE;
406 | } break;
407 | case TRANSFER_MODE_UNRELIABLE_ORDERED: {
408 | channel = SYSCH_UNRELIABLE;
409 | } break;
410 | case TRANSFER_MODE_RELIABLE: {
411 | channel = SYSCH_RELIABLE;
412 | } break;
413 | }
414 |
415 | return put_packet_channel(p_buffer, p_buffer_size, channel);
416 | }
417 |
418 | Error ENetPacketPeer::_put_packet_channel(const PoolVector &p_buffer, int p_channel) {
419 |
420 | int len = p_buffer.size();
421 | if (len == 0)
422 | return OK;
423 |
424 | PoolVector::Read r = p_buffer.read();
425 | return put_packet_channel(&r[0], len, p_channel + SYSCH_MAX);
426 | }
427 |
428 | Error ENetPacketPeer::put_packet_channel(const uint8_t *p_buffer, int p_buffer_size, int p_channel) {
429 |
430 | ERR_FAIL_COND_V(!active, ERR_UNCONFIGURED);
431 | ERR_FAIL_COND_V(connection_status != CONNECTION_CONNECTED, ERR_UNCONFIGURED);
432 | ERR_FAIL_COND_V(p_channel >= channels, ERR_INVALID_PARAMETER);
433 |
434 | int packet_flags = 0;
435 |
436 | switch (transfer_mode) {
437 | case TRANSFER_MODE_UNRELIABLE: {
438 | packet_flags = ENET_PACKET_FLAG_UNSEQUENCED;
439 | } break;
440 | case TRANSFER_MODE_UNRELIABLE_ORDERED: {
441 | packet_flags = 0;
442 | } break;
443 | case TRANSFER_MODE_RELIABLE: {
444 | packet_flags = ENET_PACKET_FLAG_RELIABLE;
445 | } break;
446 | }
447 |
448 | Map::Element *E = NULL;
449 |
450 | if (target_peer != 0) {
451 |
452 | E = peer_map.find(ABS(target_peer));
453 | if (!E) {
454 | ERR_FAIL_V_MSG(ERR_INVALID_PARAMETER, "Invalid Target Peer: " + itos(target_peer));
455 | }
456 | }
457 |
458 | ENetPacket *packet = enet_packet_create(NULL, p_buffer_size + 12, packet_flags);
459 | encode_uint32(unique_id, &packet->data[0]); //source ID
460 | encode_uint32(target_peer, &packet->data[4]); //dest ID
461 | encode_uint32(packet_flags, &packet->data[8]); //dest ID
462 | copymem(&packet->data[12], p_buffer, p_buffer_size);
463 |
464 | if (server) {
465 |
466 | if (target_peer == 0) {
467 | enet_host_broadcast(host, p_channel, packet);
468 | } else if (target_peer < 0) {
469 | //send to all but one
470 | //and make copies for sending
471 |
472 | int exclude = -target_peer;
473 |
474 | for (Map::Element *F = peer_map.front(); F; F = F->next()) {
475 |
476 | if (F->key() == exclude) // exclude packet
477 | continue;
478 |
479 | ENetPacket *packet2 = enet_packet_create(packet->data, packet->dataLength, packet_flags);
480 |
481 | enet_peer_send(F->get(), p_channel, packet2);
482 | }
483 |
484 | enet_packet_destroy(packet); //original packet no longer needed
485 | } else {
486 | enet_peer_send(E->get(), p_channel, packet);
487 | }
488 | } else {
489 |
490 | ERR_FAIL_COND_V(!peer_map.has(1), ERR_BUG);
491 | enet_peer_send(peer_map[1], p_channel, packet); //send to server for broadcast..
492 | }
493 |
494 | enet_host_flush(host);
495 |
496 | return OK;
497 | }
498 |
499 | int ENetPacketPeer::get_max_packet_size() const {
500 |
501 | return 1 << 24; //anything is good
502 | }
503 |
504 | void ENetPacketPeer::_pop_current_packet() {
505 |
506 | if (current_packet.packet) {
507 | enet_packet_destroy(current_packet.packet);
508 | current_packet.packet = NULL;
509 | current_packet.from = 0;
510 | }
511 | }
512 |
513 | NetworkedMultiplayerPeer::ConnectionStatus ENetPacketPeer::get_connection_status() const {
514 |
515 | return connection_status;
516 | }
517 |
518 | uint32_t ENetPacketPeer::_gen_unique_id() const {
519 |
520 | uint32_t hash = 0;
521 |
522 | while (hash == 0 || hash == 1) {
523 |
524 | hash = hash_djb2_one_32(
525 | (uint32_t)OS::get_singleton()->get_ticks_usec());
526 | hash = hash_djb2_one_32(
527 | (uint32_t)OS::get_singleton()->get_unix_time(), hash);
528 | hash = hash_djb2_one_32(
529 | (uint32_t)OS::get_singleton()->get_data_path().hash64(), hash);
530 | /*
531 | hash = hash_djb2_one_32(
532 | (uint32_t)OS::get_singleton()->get_unique_ID().hash64(), hash );
533 | */
534 | hash = hash_djb2_one_32(
535 | (uint32_t)((uint64_t)this), hash); //rely on aslr heap
536 | hash = hash_djb2_one_32(
537 | (uint32_t)((uint64_t)&hash), hash); //rely on aslr stack
538 |
539 | hash = hash & 0x7FFFFFFF; // make it compatible with unsigned, since negatie id is used for exclusion
540 | }
541 |
542 | return hash;
543 | }
544 |
545 | int ENetPacketPeer::get_unique_id() const {
546 |
547 | ERR_FAIL_COND_V(!active, 0);
548 | return unique_id;
549 | }
550 |
551 | void ENetPacketPeer::set_refuse_new_connections(bool p_enable) {
552 |
553 | refuse_connections = p_enable;
554 | }
555 |
556 | bool ENetPacketPeer::is_refusing_new_connections() const {
557 |
558 | return refuse_connections;
559 | }
560 |
561 | void ENetPacketPeer::set_compression_mode(CompressionMode p_mode) {
562 |
563 | compression_mode = p_mode;
564 | }
565 |
566 | ENetPacketPeer::CompressionMode ENetPacketPeer::get_compression_mode() const {
567 |
568 | return compression_mode;
569 | }
570 |
571 | size_t ENetPacketPeer::enet_compress(void *context, const ENetBuffer *inBuffers, size_t inBufferCount, size_t inLimit, enet_uint8 *outData, size_t outLimit) {
572 |
573 | ENetPacketPeer *enet = (ENetPacketPeer *)(context);
574 |
575 | if (size_t(enet->src_compressor_mem.size()) < inLimit) {
576 | enet->src_compressor_mem.resize(inLimit);
577 | }
578 |
579 | int total = inLimit;
580 | int ofs = 0;
581 | while (total) {
582 | for (size_t i = 0; i < inBufferCount; i++) {
583 | int to_copy = MIN(total, int(inBuffers[i].dataLength));
584 | copymem(&enet->src_compressor_mem.write[ofs], inBuffers[i].data, to_copy);
585 | ofs += to_copy;
586 | total -= to_copy;
587 | }
588 | }
589 |
590 | Compression::Mode mode;
591 |
592 | switch (enet->compression_mode) {
593 | case COMPRESS_FASTLZ: {
594 | mode = Compression::MODE_FASTLZ;
595 | } break;
596 | case COMPRESS_ZLIB: {
597 | mode = Compression::MODE_DEFLATE;
598 | } break;
599 | default: { ERR_FAIL_V(0); }
600 | }
601 |
602 | int req_size = Compression::get_max_compressed_buffer_size(ofs, mode);
603 | if (enet->dst_compressor_mem.size() < req_size) {
604 | enet->dst_compressor_mem.resize(req_size);
605 | }
606 | int ret = Compression::compress(enet->dst_compressor_mem.ptrw(), enet->src_compressor_mem.ptr(), ofs, mode);
607 |
608 | if (ret < 0)
609 | return 0;
610 |
611 | if (ret > int(outLimit))
612 | return 0; //do not bother
613 |
614 | copymem(outData, enet->dst_compressor_mem.ptr(), ret);
615 |
616 | return ret;
617 | }
618 |
619 | size_t ENetPacketPeer::enet_decompress(void *context, const enet_uint8 *inData, size_t inLimit, enet_uint8 *outData, size_t outLimit) {
620 |
621 | ENetPacketPeer *enet = (ENetPacketPeer *)(context);
622 | int ret = -1;
623 | switch (enet->compression_mode) {
624 | case COMPRESS_FASTLZ: {
625 |
626 | ret = Compression::decompress(outData, outLimit, inData, inLimit, Compression::MODE_FASTLZ);
627 | } break;
628 | case COMPRESS_ZLIB: {
629 |
630 | ret = Compression::decompress(outData, outLimit, inData, inLimit, Compression::MODE_DEFLATE);
631 | } break;
632 | default: {}
633 | }
634 | if (ret < 0) {
635 | return 0;
636 | } else {
637 | return ret;
638 | }
639 | }
640 |
641 | void ENetPacketPeer::_setup_compressor() {
642 |
643 | switch (compression_mode) {
644 |
645 | case COMPRESS_NONE: {
646 |
647 | enet_host_compress(host, NULL);
648 | } break;
649 | case COMPRESS_RANGE_CODER: {
650 | enet_host_compress_with_range_coder(host);
651 | } break;
652 | case COMPRESS_FASTLZ:
653 | case COMPRESS_ZLIB: {
654 |
655 | enet_host_compress(host, &enet_compressor);
656 | } break;
657 | }
658 | }
659 |
660 | void ENetPacketPeer::enet_compressor_destroy(void *context) {
661 |
662 | //do none
663 | }
664 |
665 | void ENetPacketPeer::_bind_methods() {
666 |
667 | ClassDB::bind_method(D_METHOD("get_packet_channel"), &ENetPacketPeer::get_packet_channel);
668 | ClassDB::bind_method(D_METHOD("create_server", "port", "channels", "max_clients", "in_bandwidth", "out_bandwidth"), &ENetPacketPeer::create_server, DEFVAL(1), DEFVAL(32), DEFVAL(0), DEFVAL(0));
669 | ClassDB::bind_method(D_METHOD("create_client", "ip", "port", "channels", "in_bandwidth", "out_bandwidth"), &ENetPacketPeer::create_client, DEFVAL(1), DEFVAL(0), DEFVAL(0));
670 | ClassDB::bind_method(D_METHOD("close_connection"), &ENetPacketPeer::close_connection);
671 | ClassDB::bind_method(D_METHOD("set_compression_mode", "mode"), &ENetPacketPeer::set_compression_mode);
672 | ClassDB::bind_method(D_METHOD("put_packet_channel", "pkt", "channel"), &ENetPacketPeer::_put_packet_channel);
673 | ClassDB::bind_method(D_METHOD("get_compression_mode"), &ENetPacketPeer::get_compression_mode);
674 | ClassDB::bind_method(D_METHOD("set_bind_ip", "ip"), &ENetPacketPeer::set_bind_ip);
675 |
676 | BIND_ENUM_CONSTANT(COMPRESS_NONE);
677 | BIND_ENUM_CONSTANT(COMPRESS_RANGE_CODER);
678 | BIND_ENUM_CONSTANT(COMPRESS_FASTLZ);
679 | BIND_ENUM_CONSTANT(COMPRESS_ZLIB);
680 | }
681 |
682 | ENetPacketPeer::ENetPacketPeer() {
683 |
684 | active = false;
685 | server = false;
686 | refuse_connections = false;
687 | unique_id = 0;
688 | target_peer = 0;
689 | current_packet.packet = NULL;
690 | transfer_mode = TRANSFER_MODE_RELIABLE;
691 | connection_status = CONNECTION_DISCONNECTED;
692 | compression_mode = COMPRESS_NONE;
693 | enet_compressor.context = this;
694 | enet_compressor.compress = enet_compress;
695 | enet_compressor.decompress = enet_decompress;
696 | enet_compressor.destroy = enet_compressor_destroy;
697 |
698 | bind_ip = IP_Address("*");
699 | }
700 |
701 | ENetPacketPeer::~ENetPacketPeer() {
702 |
703 | close_connection();
704 | }
705 |
706 | // sets IP for ENet to bind when using create_server
707 | // if no IP is set, then ENet bind to ENET_HOST_ANY
708 | void ENetPacketPeer::set_bind_ip(const IP_Address &p_ip) {
709 | ERR_FAIL_COND(!p_ip.is_valid() && !p_ip.is_wildcard());
710 |
711 | bind_ip = p_ip;
712 | }
713 |
--------------------------------------------------------------------------------
/modules/benet/enet_packet_peer.h:
--------------------------------------------------------------------------------
1 | #ifndef ENET_PACKET_PEER_H
2 | #define ENET_PACKET_PEER_H
3 |
4 | #include "core/io/compression.h"
5 | #include "core/io/networked_multiplayer_peer.h"
6 |
7 | #include
8 |
9 | class ENetPacketPeer : public NetworkedMultiplayerPeer {
10 |
11 | GDCLASS(ENetPacketPeer, NetworkedMultiplayerPeer)
12 | public:
13 | enum CompressionMode {
14 | COMPRESS_NONE,
15 | COMPRESS_RANGE_CODER,
16 | COMPRESS_FASTLZ,
17 | COMPRESS_ZLIB
18 | };
19 |
20 | private:
21 | enum {
22 | SYSMSG_ADD_PEER,
23 | SYSMSG_REMOVE_PEER
24 | };
25 |
26 | enum {
27 | SYSCH_CONFIG,
28 | SYSCH_RELIABLE,
29 | SYSCH_UNRELIABLE,
30 | SYSCH_MAX
31 | };
32 |
33 | bool active;
34 | bool server;
35 |
36 | uint32_t unique_id;
37 |
38 | int channels;
39 | int target_peer;
40 | TransferMode transfer_mode;
41 |
42 | ENetEvent event;
43 | ENetPeer *peer;
44 | ENetHost *host;
45 |
46 | bool refuse_connections;
47 |
48 | ConnectionStatus connection_status;
49 |
50 | Map peer_map;
51 |
52 | struct Packet {
53 |
54 | ENetPacket *packet;
55 | int from;
56 | int channel;
57 | };
58 |
59 | CompressionMode compression_mode;
60 |
61 | List incoming_packets;
62 |
63 | Packet current_packet;
64 |
65 | uint32_t _gen_unique_id() const;
66 | void _pop_current_packet();
67 |
68 | Vector src_compressor_mem;
69 | Vector dst_compressor_mem;
70 |
71 | ENetCompressor enet_compressor;
72 | static size_t enet_compress(void *context, const ENetBuffer *inBuffers, size_t inBufferCount, size_t inLimit, enet_uint8 *outData, size_t outLimit);
73 | static size_t enet_decompress(void *context, const enet_uint8 *inData, size_t inLimit, enet_uint8 *outData, size_t outLimit);
74 | static void enet_compressor_destroy(void *context);
75 | void _setup_compressor();
76 |
77 | IP_Address bind_ip;
78 |
79 | protected:
80 | static void _bind_methods();
81 |
82 | public:
83 | virtual void set_transfer_mode(TransferMode p_mode);
84 | virtual NetworkedMultiplayerPeer::TransferMode get_transfer_mode() const;
85 | virtual void set_target_peer(int p_peer);
86 |
87 | virtual int get_packet_peer() const;
88 |
89 | Error create_server(int p_port, int p_channels = 2, int p_max_peers = 32, int p_in_bandwidth = 0, int p_out_bandwidth = 0);
90 | Error create_client(const IP_Address &p_ip, int p_port, int p_channels = 2, int p_in_bandwidth = 0, int p_out_bandwidth = 0);
91 |
92 | void close_connection();
93 |
94 | virtual void poll();
95 |
96 | virtual bool is_server() const;
97 |
98 | virtual int get_available_packet_count() const;
99 | virtual Error get_packet(const uint8_t **r_buffer, int &r_buffer_size); ///< buffer is GONE after next get_packet
100 | virtual Error put_packet(const uint8_t *p_buffer, int p_buffer_size);
101 | virtual Error put_packet_channel(const uint8_t *p_buffer, int p_buffer_size, int p_channel);
102 | Error _put_packet_channel(const PoolVector &p_buffer, int p_channel);
103 |
104 | virtual Error disconnect_peer(int p_id);
105 |
106 | virtual int get_packet_channel() const;
107 | virtual int get_max_packet_size() const;
108 |
109 | virtual ConnectionStatus get_connection_status() const;
110 |
111 | virtual void set_refuse_new_connections(bool p_enable);
112 | virtual bool is_refusing_new_connections() const;
113 |
114 | virtual int get_unique_id() const;
115 |
116 | void set_compression_mode(CompressionMode p_mode);
117 | CompressionMode get_compression_mode() const;
118 |
119 | ENetPacketPeer();
120 | ~ENetPacketPeer();
121 |
122 | void set_bind_ip(const IP_Address &p_ip);
123 | };
124 |
125 | VARIANT_ENUM_CAST(ENetPacketPeer::CompressionMode);
126 |
127 | #endif // ENET_PACKET_PEER_H
128 |
--------------------------------------------------------------------------------
/modules/benet/register_types.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include "register_types.h"
3 | #include "core/error_macros.h"
4 | #include "enet_packet_peer.h"
5 | #include "enet_node.h"
6 |
7 | static bool enet_ok=false;
8 |
9 | void register_benet_types() {
10 |
11 | if (enet_initialize() !=0 ) {
12 | ERR_PRINT("ENet initialization failure");
13 | } else {
14 | enet_ok=true;
15 | }
16 |
17 | ClassDB::register_class();
18 | ClassDB::register_class();
19 | }
20 |
21 | void unregister_benet_types() {
22 |
23 | if (enet_ok)
24 | enet_deinitialize();
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/modules/benet/register_types.h:
--------------------------------------------------------------------------------
1 |
2 | void register_benet_types();
3 | void unregister_benet_types();
4 |
--------------------------------------------------------------------------------