Custom ClassiCube CPE Extensions

"UTF-8", Version 1

All instances of 64-byte space-padded string fields are instead replaced with a length-prefixed variable-length unpadded string field. An exception to this is that the string fields inside the initial login and CPE negotiation packets remain fixed-length, space-padded ASCII strings as they are sent before extension negotiation takes place.

A client may offer support for the EmoteFix, LongerMessages, and FullCP437 extensions alongside UTF-8, but a server that supports the UTF-8 extension must use it if the client advertises support for it. A client that support both UTF-8 and LongerMessages should not use the LongerMessages chunking system unless it is trying to send a string longer than 1024 bytes.

Implementation Requirements

This extension does not specify text rendering, only the delivery of Unicode codepoints.

A valid string may not exceed 1024 bytes in length.

Clients and servers should not use over-long byte sequences or use surrogates, but may optionally attempt to decode them.

Examples

Packet 0x0D "Message", Base protocol
struct {
    packet_id: u8,
    dummy_ff:  u8,
    data:      [u8; 64]
}
Packet 0x0D "Message", UTF-8 extension enabled
struct {
    packet_id: u8,
    dummy_ff:  u8,
    data_len:  u16,
    data:      [u8; data_len]
}

"KeyAuth", Version 0 (UNFINISHED)

This extension replaces the centralised vanilla MD5 hash-based authentication and skin retrieval scheme with public-key authentication and URI-based skins.

The initial login packets should follow the base protocol spec, as they are sent before CPE negotiation.

Immediately after CPE negotiation, the server sends its public key and the client-to-server login packet's 64-byte username field data encrypted with its private key. The client sends its own public key, along with a user-changeable nickname and the 64-byte challenge, decrypted with the server's public key and then encrypted with the client's private key.

Implementation Requirements

Implementations must support the 'data' URI scheme, and may optionally support other schemes/protocols.

Clients that support URI schemes other than 'data' should have an easily-accessible setting to disable remote downloads for users concerned about potentially malicious skin servers.

Clients should have a mechanism of easily managing keypairs and skin data. Clients may optionally support password-protected keys.

Servers that support both KeyAuth and vanilla authentication should have a setting for allowing or disallowing clients that don't support KeyAuth.

Packet Structures

The client's nickname and skin URI field is always encoded as length-prefixed UTF-8, never 64-byte ASCII or CP437. See the UTF-8 extension above for more details.

TODO: Determine the contents of the key field, needs more research (difficult bc of modern search engine behavior)

The player ID field of the client skin URI packet is 0xFF when sent from the client, and an actual player ID when broadcast from the server to the other clients. Clients sending skin URI packets should also be prepared to have their own skin URI temporarily set by the server with the player ID 0xFF.

Packet 0xA0 "Client Key"
struct {
    packet_id: u8,
    name_len: u16,
    name_data: [u8; name_len],
    key_len: u16,
    key_data: [u8; key_len],
    challenge_len: u16,
    challenge_data: [u8; challenge_len],
}
Packet 0xA1 "Server Key"
struct {
    packet_id: u8,
    key_len: u16,
    key_data: [u8; key_len],
    challenge_len: u16,
    challenge_data: [u8; challenge_len]
}
Packet 0xA2 "Client Key Challenge Response"
struct {
    packet_id: u8,
    challenge_len: u16,
    challenge_data: [u8; challenge_len],
}
Packet 0xA3 "Client Skin URI"
struct {
    packet_id: u8,
    player_id: u8,
    skin_uri_len: u16,
    skin_uri_data: [u8; skin_uri_len],
}