Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(Automatically?) document classes not being inheritable (virtual, ...) #3460

Open
mrimvo opened this issue Apr 27, 2020 · 6 comments
Open

(Automatically?) document classes not being inheritable (virtual, ...) #3460

mrimvo opened this issue Apr 27, 2020 · 6 comments
Labels
area:class reference Issues and PRs about the class reference, which should be addressed on the Godot engine repository enhancement

Comments

@mrimvo
Copy link

mrimvo commented Apr 27, 2020

In this section of the documentation, it says:

Godot uses a mid-level object NetworkedMultiplayerPeer. This object is not meant to be created directly, but is designed so that several implementations can provide it.

Since I need to implement a custom client (based on web socket), but want to use the higher-level networking like get_tree().set_network_peer(my_custom_client) and rpc() later on, I went ahead and tried to extend NetworkedMultiplayerPeer. This is the minimal example I came up with:

1 extends Node
2 
3 class MyPeer extends NetworkedMultiplayerPeer:
4     func _init():
5 	    	pass
6  
7 var peer = MyPeer.new()

However, turns out the super class is a virtual class, and I can't create a new instance with MyPeer.new(). The Error log says:

E 0:00:00.772   instance: Condition "!ti->creation_func" is true. Returned: __null
  <C++ Source>  core/class_db.cpp:540 @ instance()
  <Stack Trace> Node.gd:7 @ _init()
E 0:00:00.772   _new: Can't inherit from a virtual class.
  <C++ Error>   Condition "!owner" is true. Returned: Variant()
  <C++ Source>  modules/gdscript/gdscript.cpp:158 @ _new()
  <Stack Trace> Node.gd:7 @ _init()

Is there a simple trick I just don't know about? Or is it entirely impossible to provide an implementation of NetworkedMultiplayerPeer in GDScript? If the latter is the case, please clarify on how to provide an custom implementation of NetworkedMultiplayerPeer.

@Calinou Calinou transferred this issue from godotengine/godot Apr 27, 2020
@Calinou
Copy link
Member

Calinou commented Apr 27, 2020

I think it can only be extended from C++, not GDScript.

cc @Faless

@mhilbrunner
Copy link
Member

mhilbrunner commented Apr 27, 2020

@Calinou is correct.

This means you are not supposed to use NetworkedMultiplayerPeer directly, but one of the implementations, e.g. if you want to use the ENet backed implementation, use NetworkedMultiplayerEnet (which extends NetworkedMultiplayerPeer if you look closely).

Or if you're writing a plugin/module for a new networking protocol or solution like Websockets, create a new C++ class extending NetworkedMultiplayerPeer. Thats more of an advanced use case though. :)

Maybe the docs could be clearer here.

If you really want to extend the Engine to use Websockets, you'd need to either do this in C++ or maybe using GDNative.

Alternatively, the WebRTC stuff here may be of interest:
https://docs.godotengine.org/en/stable/tutorials/networking/webrtc.html

There is also some Websocket stuff here:
https://docs.godotengine.org/en/stable/tutorials/networking/websocket.html

@mhilbrunner
Copy link
Member

Is there a simple trick I just don't know about? Or is it entirely impossible to provide an implementation of NetworkedMultiplayerPeer in GDScript? If the latter is the case, please clarify on how to provide an custom implementation of NetworkedMultiplayerPeer.

In short, yes I think that's currently not possible.
It may be something to consider, but I'm not sure whether GDScript is the best tool to create new networking subsystems for the engine.

@mrimvo
Copy link
Author

mrimvo commented Apr 28, 2020

Thank you guys for clarification. :)

It may be something to consider, but I'm not sure whether GDScript is the best tool to create new networking subsystems for the engine.

Not sure if it's the best tool, but it would be the easiest way to do it. My idea was the following (and I was lured into that by the belief you could extend any class available to GDScript).

extends NetworkedMultiplayerPeer

class_name MyWebSocket

# implementing all the methods, signals and properties
# NetworkedMultiplayerPeer requires to have.
# It's not too much and pretty straight forward.
func get_connection_status(): client.get_connection_status()
func poll(): client.poll()
func set_target_peer( id ): .... # my custom protocol
...

# using the existing websocket client
var client = WebSocket.new()

func init():
    ...
    client.connect("data_received", self, "_on_data")

func connect():
    client.connect_to_url(...)

func _on_data():
    # ... evaluate our custom server's replies
    var packet = get_peer(1).get_packet()

func put_packet(packet):
    # send packets to our custom server
    get_peer(1).put_packet(packet.to_utf8())

It looks like it's an easy way to enable higher-level networking with MultiplayerApi, while communicating with our custom server (which is written in Java). I would then just do get_tree().set_network_peer(MyWebSocket.new()), and I'm ready to go. Our server is set up to handle some lobbying and for the game itself would just broadcast messages of everybody to everybody. MyWebSocket (extending NetworkedMultiplayerPeer) would then act like a bridge/adapter to make godot's MultiplayerAPI understand which peers are there and how to communicate with them.

As for the documentation, it would be nice if each virtual class had a hint saying "This is a virtual class. you can not extend it using GDScript. Consider using C++/GDNative". Something along these lines.

Another related question: Is it possible to extend non-virtual classes like WebSocket with GDScript and override functions of the super class?

Thank you so much for your answers and support, I appreciate! :) 👍

@mhilbrunner
Copy link
Member

You're welcome. :)

Thanks for bringing this to our attention, we'll think about making the networking more extendable from GDScript.

Another related question: Is it possible to extend non-virtual classes like WebSocket with GDScript and override functions of the super class?

For most classes it should be possible, depends on if they're bound/exposed to GDScript and a little bit on how they work.

Thank you so much for your answers and support, I appreciate! :)

Again, you're welcome :)

I'll rename this issue to be about documenting classes being virtual, as that is a documentation issue, and then I'll open a issue on the main repo about making the networking extendable from GDScript and link it here.

@mhilbrunner mhilbrunner changed the title How to extend NetworkedMultiplayerPeer in GDScript (Automatically?) document classes not being inheritable (virtual, ...) Apr 28, 2020
@Faless
Copy link
Contributor

Faless commented May 1, 2020

As @mhilbrunner mentioned, the main reason for not having a GDScript implementable interface for NetworkedMultiplayerPeer is performance.
Mainly, GDScript does not support raw memory pointers, and implementing that interface using PoolByteArray(s) conversion would cause a lot of memory allocations, affecting performance quite a bit.
I agree though, that allowing it will help in the prototyping stage before moving it to GDNative.

It's also worth mentioning, that the Godot WebSocket implementation already supports the MultiplayerAPI.

@skyace65 skyace65 added the area:class reference Issues and PRs about the class reference, which should be addressed on the Godot engine repository label Dec 31, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:class reference Issues and PRs about the class reference, which should be addressed on the Godot engine repository enhancement
Projects
None yet
Development

No branches or pull requests

5 participants