rcelyte / beatuprcelyte Goto Github PK
View Code? Open in Web Editor NEWA lightweight modded Beat Saber multiplayer server
License: The Unlicense
A lightweight modded Beat Saber multiplayer server
License: The Unlicense
Windows fixes added yesterday seem to have broken ability to compile, at least under red hat (alma).
$ gcc --version
gcc (GCC) 11.2.1 20220127 (Red Hat 11.2.1-9)
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ make
[cc gen.x86_64]
Submodule 'mbedtls' (https://github.com/ARMmbed/mbedtls.git) registered for path 'mbedtls'
Cloning into '/home/frodo/rc-1/BeatUpRcelyte/mbedtls'...
[gen packets.gen.h]
Submodule path 'mbedtls': checked out '869298bffeea13b205343361b7a7daf2b210e33d'
[cc config.c.o]
[cc encryption.c.o]
[cc main.c.o]
[cc net.c.o]
[cc packets.c.o]
[cc ssl.c.o]
[cc wire.c.o]
[cc common.c.o]
[cc instance.c.o]
[cc master.c.o]
[cc pool.c.o]
[cc internal.c.o]
[cc status.c.o]
[cc status_ssl.c.o]
[make libmbedtls.a]
[make libmbedx509.a]
[make libmbedcrypto.a]
CC debug.c
CC net_sockets.c
CC x509.c
CC ssl_cache.c
CC x509_create.c
CC x509_crl.c
CC aes.c
CC ssl_ciphersuites.c
CC aesni.c
CC ssl_client.c
CC x509_crt.c
CC aria.c
CC ssl_cookie.c
CC x509_csr.c
CC asn1parse.c
CC x509write_crt.c
CC ssl_msg.c
CC asn1write.c
CC x509write_csr.c
CC ssl_ticket.c
CC ssl_tls.c
CC base64.c
CC bignum.c
CC ssl_tls12_client.c
CC ssl_tls12_server.c
CC ssl_tls13_keys.c
CC camellia.c
CC ccm.c
CC chacha20.c
CC ssl_tls13_client.c
CC ssl_tls13_server.c
CC chachapoly.c
CC cipher.c
CC ssl_tls13_generic.c
CC cipher_wrap.c
CC cmac.c
CC constant_time.c
CC ctr_drbg.c
CC des.c
CC dhm.c
CC ecdh.c
CC ecdsa.c
CC ecjpake.c
CC ecp.c
CC ecp_curves.c
CC entropy.c
CC entropy_poll.c
Gen error.c
CC gcm.c
CC hkdf.c
CC hmac_drbg.c
CC md.c
CC md5.c
CC memory_buffer_alloc.c
CC mps_reader.c
CC mps_trace.c
CC nist_kw.c
CC oid.c
CC padlock.c
CC pem.c
CC pk.c
CC pk_wrap.c
CC pkcs12.c
AR libmbedx509.a
CC pkcs5.c
CC pkparse.c
CC pkwrite.c
CC platform.c
CC platform_util.c
CC poly1305.c
CC psa_crypto.c
CC psa_crypto_aead.c
CC psa_crypto_cipher.c
CC psa_crypto_client.c
Gen psa_crypto_driver_wrappers.c
CC psa_crypto_ecp.c
CC psa_crypto_hash.c
CC psa_crypto_mac.c
CC psa_crypto_rsa.c
CC psa_crypto_se.c
CC psa_crypto_slot_management.c
CC psa_crypto_storage.c
CC psa_its_file.c
CC ripemd160.c
CC rsa.c
CC rsa_alt_helpers.c
CC sha1.c
CC sha256.c
CC sha512.c
Gen ssl_debug_helpers_generated.c
CC threading.c
CC timing.c
CC version.c
Gen version_features.c
CC ../3rdparty/everest/library/everest.c
CC ../3rdparty/everest/library/x25519.c
CC ../3rdparty/everest/library/Hacl_Curve25519_joined.c
CC error.c
CC psa_crypto_driver_wrappers.c
CC ssl_debug_helpers_generated.c
CC version_features.c
AR libmbedtls.a
AR libmbedcrypto.a
[cc beatupserver]
/opt/rh/gcc-toolset-11/root/usr/bin/ld: /opt/rh/gcc-toolset-11/root/usr/lib/gcc/x86_64-redhat-linux/11/libgcc_eh.a(unwind-dw2-fde-dip.o): in function __register_frame_info_bases': (.text+0x1acd): undefined reference to
pthread_mutex_lock'
/opt/rh/gcc-toolset-11/root/usr/bin/ld: /opt/rh/gcc-toolset-11/root/usr/lib/gcc/x86_64-redhat-linux/11/libgcc_eh.a(unwind-dw2-fde-dip.o): in function __register_frame_info': (.text+0x1b87): undefined reference to
pthread_mutex_lock'
/opt/rh/gcc-toolset-11/root/usr/bin/ld: /opt/rh/gcc-toolset-11/root/usr/lib/gcc/x86_64-redhat-linux/11/libgcc_eh.a(unwind-dw2-fde-dip.o): in function __register_frame_info_table_bases': (.text+0x1c5c): undefined reference to
pthread_mutex_lock'
/opt/rh/gcc-toolset-11/root/usr/bin/ld: /opt/rh/gcc-toolset-11/root/usr/lib/gcc/x86_64-redhat-linux/11/libgcc_eh.a(unwind-dw2-fde-dip.o): in function __register_frame_info_table': (.text+0x1cf4): undefined reference to
pthread_mutex_lock'
/opt/rh/gcc-toolset-11/root/usr/bin/ld: /opt/rh/gcc-toolset-11/root/usr/lib/gcc/x86_64-redhat-linux/11/libgcc_eh.a(unwind-dw2-fde-dip.o): in function __register_frame_table': (.text+0x1da1): undefined reference to
pthread_mutex_lock'
/opt/rh/gcc-toolset-11/root/usr/bin/ld: /opt/rh/gcc-toolset-11/root/usr/lib/gcc/x86_64-redhat-linux/11/libgcc_eh.a(unwind-dw2-fde-dip.o):(.text+0x1e32): more undefined references to pthread_mutex_lock' follow /opt/rh/gcc-toolset-11/root/usr/bin/ld: /opt/rh/gcc-toolset-11/root/usr/lib/gcc/x86_64-redhat-linux/11/libgcc_eh.a(unwind-dw2-fde-dip.o): in function
__deregister_frame_info_bases':
(.text+0x1e7a): undefined reference to pthread_mutex_unlock' /opt/rh/gcc-toolset-11/root/usr/bin/ld: (.text+0x1efd): undefined reference to
pthread_mutex_unlock'
/opt/rh/gcc-toolset-11/root/usr/bin/ld: /opt/rh/gcc-toolset-11/root/usr/lib/gcc/x86_64-redhat-linux/11/libgcc_eh.a(unwind-dw2-fde-dip.o): in function _Unwind_Find_FDE': (.text+0x2024): undefined reference to
pthread_mutex_lock'
/opt/rh/gcc-toolset-11/root/usr/bin/ld: (.text+0x2180): undefined reference to pthread_mutex_unlock' /opt/rh/gcc-toolset-11/root/usr/bin/ld: (.text+0x21bc): undefined reference to
pthread_mutex_unlock'
/opt/rh/gcc-toolset-11/root/usr/bin/ld: /opt/rh/gcc-toolset-11/root/usr/lib/gcc/x86_64-redhat-linux/11/libgcc_eh.a(unwind-dw2-fde-dip.o): in function __register_frame_info_bases': (.text+0x1b00): undefined reference to
pthread_mutex_unlock'
/opt/rh/gcc-toolset-11/root/usr/bin/ld: /opt/rh/gcc-toolset-11/root/usr/lib/gcc/x86_64-redhat-linux/11/libgcc_eh.a(unwind-dw2-fde-dip.o): in function __register_frame_info': (.text+0x1bba): undefined reference to
pthread_mutex_unlock'
/opt/rh/gcc-toolset-11/root/usr/bin/ld: /opt/rh/gcc-toolset-11/root/usr/lib/gcc/x86_64-redhat-linux/11/libgcc_eh.a(unwind-dw2-fde-dip.o): in function __register_frame_info_table_bases': (.text+0x1c8f): undefined reference to
pthread_mutex_unlock'
/opt/rh/gcc-toolset-11/root/usr/bin/ld: /opt/rh/gcc-toolset-11/root/usr/lib/gcc/x86_64-redhat-linux/11/libgcc_eh.a(unwind-dw2-fde-dip.o):(.text+0x1d27): more undefined references to pthread_mutex_unlock' follow /opt/rh/gcc-toolset-11/root/usr/bin/ld: .obj/x86_64-redhat-linux/src/net.c.o: in function
net_init':
net.c:(.text+0x231a): undefined reference to pthread_mutexattr_init' /opt/rh/gcc-toolset-11/root/usr/bin/ld: net.c:(.text+0x2332): undefined reference to
pthread_mutexattr_settype'
/opt/rh/gcc-toolset-11/root/usr/bin/ld: net.c:(.text+0x2353): undefined reference to pthread_mutex_init' /opt/rh/gcc-toolset-11/root/usr/bin/ld: .obj/x86_64-redhat-linux/src/net.c.o: in function
net_cleanup':
net.c:(.text+0x2c48): undefined reference to pthread_mutex_destroy' /opt/rh/gcc-toolset-11/root/usr/bin/ld: .obj/x86_64-redhat-linux/src/net.c.o: in function
net_lock':
net.c:(.text+0x2cd8): undefined reference to pthread_mutex_trylock' /opt/rh/gcc-toolset-11/root/usr/bin/ld: net.c:(.text+0x2cfb): undefined reference to
pthread_mutex_lock'
/opt/rh/gcc-toolset-11/root/usr/bin/ld: .obj/x86_64-redhat-linux/src/net.c.o: in function net_unlock': net.c:(.text+0x2d1c): undefined reference to
pthread_mutex_unlock'
/opt/rh/gcc-toolset-11/root/usr/bin/ld: .obj/x86_64-redhat-linux/src/instance/instance.c.o: in function instance_init': instance.c:(.text+0xf100): undefined reference to
pthread_create'
/opt/rh/gcc-toolset-11/root/usr/bin/ld: .obj/x86_64-redhat-linux/src/instance/instance.c.o: in function instance_cleanup': instance.c:(.text+0xf210): undefined reference to
pthread_join'
/opt/rh/gcc-toolset-11/root/usr/bin/ld: .obj/x86_64-redhat-linux/src/master/master.c.o: in function master_init': master.c:(.text+0x4c55): undefined reference to
pthread_create'
/opt/rh/gcc-toolset-11/root/usr/bin/ld: .obj/x86_64-redhat-linux/src/master/master.c.o: in function master_cleanup': master.c:(.text+0x4caf): undefined reference to
pthread_join'
/opt/rh/gcc-toolset-11/root/usr/bin/ld: .obj/x86_64-redhat-linux/src/status/status.c.o: in function status_handler': status.c:(.text+0x180e): undefined reference to
pthread_create'
/opt/rh/gcc-toolset-11/root/usr/bin/ld: .obj/x86_64-redhat-linux/src/status/status.c.o: in function status_init': status.c:(.text+0x18a2): undefined reference to
pthread_create'
/opt/rh/gcc-toolset-11/root/usr/bin/ld: .obj/x86_64-redhat-linux/src/status/status.c.o: in function status_cleanup': status.c:(.text+0x1926): undefined reference to
pthread_join'
/opt/rh/gcc-toolset-11/root/usr/bin/ld: .obj/x86_64-redhat-linux/src/status/status_ssl.c.o: in function status_ssl_handler': status_ssl.c:(.text+0x1976): undefined reference to
pthread_create'
/opt/rh/gcc-toolset-11/root/usr/bin/ld: .obj/x86_64-redhat-linux/src/status/status_ssl.c.o: in function status_ssl_init': status_ssl.c:(.text+0x1c07): undefined reference to
pthread_create'
/opt/rh/gcc-toolset-11/root/usr/bin/ld: .obj/x86_64-redhat-linux/src/status/status_ssl.c.o: in function status_ssl_cleanup': status_ssl.c:(.text+0x1cad): undefined reference to
pthread_join'
collect2: error: ld returned 1 exit status
make: *** [makefile:29: beatupserver] Error 1
BeatUpServer currently needs to be told it's own address via the config file so clients can deeplink properly. This process should be automated so the server can work out of the box and respond to address changes. A practical solution would be to ping a number of public STUN servers (specific domains should be configurable) on startup, gathering responses for IPv4 and optionally IPv6 (see #20).
src/log.h:30:1: error: expected identifier or ‘(’ before ‘[’ token
30 | [[maybe_unused]] static void uprintf(const char *format, ...) {
gen.c:174:1: error: expected identifier or ‘(’ before ‘[’ token
174 | [[nodiscard]] static const char *parse_struct_fields(const char *it, uint32_t indent, bool insideSwitch) {
gen.c:229:1: error: expected identifier or ‘(’ before ‘[’ token
229 | [[nodiscard]] static const char *parse_struct(const char *it) {
gen.c:244:1: error: expected identifier or ‘(’ before ‘[’ token
244 | [[nodiscard]] static const char *parse_enum(const char *it) {
In [[current year]], IPv6 is still not ubiquitous across residential networks internationally, so clients cannot be assumed to support deeplinking to IPv6 endpoints. Additionally, accessing legacy master servers via domain names containing AAAA records will fail for IPv4-only clients, since the game's code doesn't know to fall back on failure (this shouldn't an issue for graph connections, with C♯'s more intelligent HTTPS client). BeatUpServer should detect IPv6 clients and respond with IPv6 deeplink endpoints in such cases, while continuing to provide IPv4 endpoints for those stuck in the stone ages. Care should be taken to ensure IPv4 clients are never misidentified and supporting IPv6. This will require extensive testing from those affected by the global stagnation of internet protocol adoption.
I would personally gain a lot of utility on my server if there were a configurable message that pops up once when new players join, or it could be triggered by some other one-time-event. It doesn't need to be more than 100 - 200 characters.
The reasoning is that it seems people don't read (or aren't able to read?) the name of the instance when they join and get upset when they realize that others do not share their preferred style even though the map styles that are played are specifically named as the name of the lobby.
Or, if the server name could be floating in the lobby somewhere all the time that would be useful enough.
I thank you for you consideration.
Ran into an issue twice today where someone joined, the map ended, and then the 'start' button was greyed out. Unable to affect change by changing a new map or doing anything else. Left and created new server and it worked again.
I sent you the relevant logs in discord.
BeatUpClient 0.6.0 included incompatible changes to facilitate Beat Saber 1.31.0 support. The server will need to continue providing protocol support for legacy BeatUpClient versions until an updated mod is available for all game versions 1.20.0+
Detour
interface is an example of this, mimicing the beatsaber-hook
core mod)The current implementation spawns and detaches a new thread for every connection, making it extremely intensive and prone to resource exhaustion under load. It would be better to have a fixed pool of long running threads all simultaneously waiting on the listener socket, with each thread adding its share of incoming connections to a local connection list monitored via select/epoll/kqueue/IOCP.
Switching difficulties mid-level without NoFail can be near impossible on faster maps. Failing with per-player difficulty enabled should give a grace period for switching difficulties instead of immediately dropping out to spectator mode. This may benefit from UI feedback to avoid confusion over an awkward pause.
When I try to play online with my friends, and we try a song we don't all have it doesn't let us start and says we dont all own the song. Has anyone else had this issue?
How do you build and run this server? because i want to test it but there is no documentation or anything that says how to build it.
Sorry to do this, but I'm not sure how to enable BeatUpClient. I realize it is in BETA and as such, there is no documentation. Is there a high-level explanation I can start off from or should I just wait until it's out of beta?
Compiled fine on Ubuntu 22.04, but cannot start due to the following error:
~/BeatUpRcelyte$ ./beatupserver [net.c] Failed to open TCP socket: Address family not supported by protocol
Here is my beatupserver.json (Obviously my address is my public IPv4 address normally)
{ "instance": { "address": ["11.111.11.111", "[::]"], "count": 1 }, "master": {}, "status": { "url": "http://localhost" } }
Level fragment packets aren't getting through on ENet-based game versions.
Switching difficulties mid-level fails under some conditions, leaving the player with an empty track and no notes spawning.
BeatUpClient's Detour
interface should allow omitting arguments present in the original method, transparently passing them through to Base()
calls. This is necessary when targeting multiple game versions with different signatures for a given method, and will allow for the eventual deprecation of Harmony-based patching.
The BeatUpServer web frontend currently displays a placeholder page. The intent is to eventually provide a local listing for public rooms with details about player performance and level history, similar to https://bssb.app. Stretch goals include:
Running with both BeatUpClient and Custom Sabers Lite installed results in the following error on launch:
The AssetBundle 'IO.Stream' can't be loaded because another AssetBundle with the same files is already loaded.
beatupserver instance (not sure how to find version number but it was built on sept 9) one player (me) was connected and it allowed another player to join and when the player appeared they had a strange character in front the name entry on player board (looked like a p) followed by a space. Map was chosen but second player's name was unselectable and 'start' button could not be clicked. Second player looked confused then disconnected. Relevant server log section attached.
beatupserver_2023_12_16.log
When I created the server, "CFR-3" appeared after "performing hand shake". Is it because I didn't open some ports, I only opened ports: 80, 2328, 5000-7000, 8106-8200.
"beatupserver.json" is:
{
"instance": {
"address": ["139.196.158.xxx"],
"count": 1
},
"master": {},
"status": {
"url": "http://0.0.0.0"
}
}
lsof -i
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
systemd-n 418 systemd-network 19u IPv4 16091 0t0 UDP iZuf6bgmergurdaa7a5meyZ:bootpc
systemd-r 432 systemd-resolve 12u IPv4 16975 0t0 UDP localhost:domain
systemd-r 432 systemd-resolve 13u IPv4 16976 0t0 TCP localhost:domain (LISTEN)
chronyd 567 _chrony 5u IPv4 17984 0t0 UDP localhost:323
chronyd 567 _chrony 6u IPv6 17985 0t0 UDP localhost:323
beatupser 24436 root 3u IPv4 167638 0t0 UDP *:2328
beatupser 24436 root 4u IPv6 167639 0t0 TCP *:http (LISTEN)
beatupser 24436 root 5u IPv4 167640 0t0 UDP *:8106
./beatupserver --ipv4
[net.c] Bound 0.0.0.0:2328
[wire.c] TODO: remote wire
[master.c] Started
[net.c] Bound 0.0.0.0:8106
[status_ssl.c] Started HTTP
[pool.c] pool_host_attach()
[instance.c] Started
Press [enter] to exit
[internal.c] (HTTP,game): POST /beat_saber_get_multiplayer_instance?access_token=OC%7C238236400888545%7C
[internal.c] TODO: parse songPackMask
[pool.c] 1 room open
[instance.c] opening room (0,0)
[instance.c] state (none) -> Lobby.Idle
[instance.c] resolve | player slots (1/11): [⠁⠀]
[master.c] Sending player to room A
[internal.c] TODO: encode songPackMask
[internal.c] (HTTP,game): POST /beat_saber_get_multiplayer_instance?access_token=OC%7C238236400888545%7C
[internal.c] TODO: parse songPackMask
[pool.c] 2 rooms open
[instance.c] opening room (0,1)
[instance.c] state (none) -> Lobby.Idle
[instance.c] resolve | player slots (1/11): [⠁⠀]
[master.c] Sending player to room B
[internal.c] TODO: encode songPackMask
[internal.c] (HTTP,game): POST /beat_saber_get_multiplayer_instance?access_token=OC%7C238236400888545%7C
[internal.c] TODO: parse songPackMask
[pool.c] 3 rooms open
Room codes should be randomized for private rooms and mapped to wire handles via hash accelerated table lookup, avoiding duplicate codes. A filter is needed to avoid unfortunate strings showing up in codes from any source: indexed, random, or custom set by the host. Additionally, the following characters should be aliased due to similar appearance in-game:
B
-> 8
D
-> 0
I
-> 1
O
-> 0
When gameplay starts, normally a GUID is generated for each gameplay session.
The server usually sends this in SetGameplaySceneSyncFinishedRpc
or SetPlayerDidConnectLateRpc
.
BeatUpServer doesn't seem to do this, instead returning an empty GUID (00000000-0000-0000-0000-000000000000
).
BeatUpRcelyte/src/instance/instance.c
Line 452 in 4f110ee
Unfortunately this breaks the Server Browser's ability to track individual gameplay sessions.
BeatUpServer's current JSON configuration is somewhat convoluted and unintuitive for users. An INI-based format would be simpler to parse, less error prone for users (mismatched quotes, trailing commas, etc.), more extensible, provide more user-friendly errors, and allow for documentation to be included as comments in the default generated configuration file. This would additionally streamline the setup process described in #7.
For beatupserver updates to stdout
Instead of:
[internal.c] (HTTP,bssb): /
Could we have:
<YYYYMMDD-HHMMSS> [internal.c] (HTTP,bssb): /
or something similar?
It would be useful since I am piping this output to a file to use for logs.
Thanks.
Support for running different components of BeatUpServer in separate processes/machines was lost in 8f9ef33.
BeatUpServer instance port numbers are currently hardcoded to start at 8106 and count up, leading to issues if multiple instance processes exist behind the same IP address. Further, versatile port assignments may be desirable for more complex hosting setups with containers, network address translation, and whatnot. Ephemeral (auto-assigned) ports should also be supported, however these pose a unique challenge in that upstream firewalls must to be informed of the ports to forward (hole punching was deemed non-viable, as the server isn't necessarily aware of the address a given client will have when connecting to it). Additionally, there should be warnings for attempting to use port numbers which some ISPs are known to block (i.e. 5000, the hardcoded start port prior to 7fff22a).
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.