mirror of
https://github.com/smartcmd/MinecraftConsoles.git
synced 2026-08-20 09:57:09 +00:00
The old Windows64 port had no real player identity — it used hardcoded fake XUIDs, so anyone could impersonate anyone. This replaces that with proper auth supporting Mojang, Ely.by, and offline accounts. MCAuth library (new, MCAuth/): Mojang auth via MSA device code flow (XBL, SISU, MC services), Ely.by via Yggdrasil with 2FA, offline UUID generation matching Java Edition (MD5 v3 from "OfflinePlayer:<name>"). Multi-account manager with background token refresh, per-slot sessions, and on-disk token persistence. Server-side session verification via Mojang/Ely.by hasJoined API. Skin fetching and PNG validation from texture servers. Network protocol (version bumped to 80): Three new packets (AuthScheme, AuthResponse, AuthResult) implement a server-driven auth handshake before login completes. Player identity migrated from 64-bit XUID to 128-bit GameUUID backed by two uint64 fields (hi/lo). readPlayerUID/writePlayerUID now serialize 16 bytes on the wire. Old and new clients cannot connect to each other — version mismatch is rejected at PreLogin. Save migration: Map data mappings auto-migrate from old format: the old 64-bit XUID is placed in hi, lo is set to 0 as a sentinel. On first access by the real player, the sentinel entry is upgraded in-place to the full 128-bit UUID. Format detection is by file size (2080, 2112, or 4160 bytes). Player .dat filenames inside saveData.ms change from decimal XUID to dashed UUID — old saves need manual entry renaming in the archive. UI: NativeUIRenderer: immediate-mode drawing system (quads, text, 9-slice panels, scrollbars, focus lists) for rendering auth screens without Flash/Scaleform. UIScene_MSAuth handles device code display, Ely.by credential input with 2FA, per-account skin head preview, and multi-account add/remove/switch. Server: online-mode and auth-provider (mojang/elyby) in server.properties. Whitelist and ban checks validate against the server-verified UUID. Incompatible auth scheme logs which provider the server expects vs what the client is using. Also fixes a pre-existing exploit where any client could send a DebugOptionsPacket to grant themselves CraftAnything and other debug privileges on any server — now requires OP status server-side.
146 lines
4.6 KiB
C++
146 lines
4.6 KiB
C++
#pragma once
|
|
using namespace std;
|
|
|
|
#ifdef _LARGE_WORLDS
|
|
// 51 maps per player (7x7 overworld, 1 nether, 1 end) * 100 players rounded up to power of 2
|
|
#define MAXIMUM_MAP_SAVE_DATA 8192//65536
|
|
|
|
// 4J Stu - These are special map slots that are used on local machines. They will never be an actual map,
|
|
// but are placeholders for when we get updated with the correct id
|
|
#define MAP_OVERWORLD_DEFAULT_INDEX 65535
|
|
#define MAP_NETHER_DEFAULT_INDEX 65534
|
|
#define MAP_END_DEFAULT_INDEX 65533
|
|
#else
|
|
#define MAXIMUM_MAP_SAVE_DATA 256
|
|
|
|
// 4J Stu - These are special map slots that are used on local machines. They will never be an actual map,
|
|
// but are placeholders for when we get updated with the correct id
|
|
#define MAP_OVERWORLD_DEFAULT_INDEX 255
|
|
#define MAP_NETHER_DEFAULT_INDEX 254
|
|
#define MAP_END_DEFAULT_INDEX 253
|
|
#endif
|
|
|
|
// The save file version in which we added the End dimension map mappings
|
|
#define END_DIMENSION_MAP_MAPPINGS_SAVE_VERSION 5
|
|
|
|
#include "File.h"
|
|
#include "LevelStorage.h"
|
|
#include "PlayerIO.h"
|
|
|
|
#include "ConsoleSavePath.h"
|
|
class ConsoleSaveFile;
|
|
|
|
// Map data mappings — current format uses 128-bit GameUUID
|
|
typedef struct _MapDataMappings
|
|
{
|
|
PlayerUID xuids[MAXIMUM_MAP_SAVE_DATA];
|
|
byte dimensions[MAXIMUM_MAP_SAVE_DATA/4];
|
|
|
|
_MapDataMappings();
|
|
int getDimension(int id);
|
|
void setMapping(int id, PlayerUID xuid, int dimension);
|
|
} MapDataMappings;
|
|
|
|
// Legacy binary format with 64-bit XUIDs — used ONLY for reading old save files
|
|
typedef struct _MapDataMappings_legacy64
|
|
{
|
|
uint64_t xuids[MAXIMUM_MAP_SAVE_DATA];
|
|
byte dimensions[MAXIMUM_MAP_SAVE_DATA/4];
|
|
} MapDataMappings_legacy64;
|
|
|
|
// Even older format with 1-bit dimension indexing and 64-bit XUIDs
|
|
typedef struct _MapDataMappings_old
|
|
{
|
|
uint64_t xuids[MAXIMUM_MAP_SAVE_DATA];
|
|
byte dimensions[MAXIMUM_MAP_SAVE_DATA/8];
|
|
|
|
_MapDataMappings_old();
|
|
int getDimension(int id);
|
|
void setMapping(int id, uint64_t xuid, int dimension);
|
|
} MapDataMappings_old;
|
|
|
|
class DirectoryLevelStorage : public LevelStorage, public PlayerIO
|
|
{
|
|
private:
|
|
/* 4J Jev, Probably no need for this as theres no exceptions being thrown.
|
|
static const Logger *logger = Logger::getLogger("Minecraft"); */
|
|
|
|
const File dir;
|
|
//const File playerDir;
|
|
const ConsoleSavePath playerDir;
|
|
//const File dataDir;
|
|
const ConsoleSavePath dataDir;
|
|
const int64_t sessionId;
|
|
const wstring levelId;
|
|
|
|
static const wstring sc_szPlayerDir;
|
|
// 4J Added
|
|
#ifdef _LARGE_WORLDS
|
|
class PlayerMappings
|
|
{
|
|
friend class DirectoryLevelStorage;
|
|
private:
|
|
unordered_map<int64_t, short> m_mappings;
|
|
|
|
public:
|
|
void addMapping(int id, int centreX, int centreZ, int dimension, int scale);
|
|
bool getMapping(int &id, int centreX, int centreZ, int dimension, int scale);
|
|
void writeMappings(DataOutputStream *dos);
|
|
void readMappings(DataInputStream *dis);
|
|
};
|
|
unordered_map<PlayerUID, PlayerMappings, PlayerUID::Hash> m_playerMappings;
|
|
byteArray m_usedMappings;
|
|
#else
|
|
MapDataMappings m_mapDataMappings;
|
|
MapDataMappings m_saveableMapDataMappings;
|
|
#endif
|
|
bool m_bHasLoadedMapDataMappings;
|
|
|
|
unordered_map<wstring, ByteArrayOutputStream *> m_cachedSaveData;
|
|
vector<short> m_mapFilesToDelete; // Temp list of files that couldn't be deleted immediately due to saving being disabled
|
|
|
|
protected:
|
|
ConsoleSaveFile *m_saveFile;
|
|
|
|
public:
|
|
virtual ConsoleSaveFile *getSaveFile() { return m_saveFile; }
|
|
virtual void flushSaveFile(bool autosave);
|
|
|
|
public:
|
|
DirectoryLevelStorage(ConsoleSaveFile *saveFile, const File dir, const wstring& levelId, bool createPlayerDir);
|
|
~DirectoryLevelStorage();
|
|
|
|
private:
|
|
void initiateSession();
|
|
|
|
protected:
|
|
File getFolder();
|
|
|
|
public:
|
|
void checkSession();
|
|
virtual ChunkStorage *createChunkStorage(Dimension *dimension);
|
|
LevelData *prepareLevel();
|
|
virtual void saveLevelData(LevelData *levelData, vector<shared_ptr<Player> > *players);
|
|
virtual void saveLevelData(LevelData *levelData);
|
|
virtual void save(shared_ptr<Player> player);
|
|
virtual CompoundTag *load(shared_ptr<Player> player); // 4J Changed return val to bool to check if new player or loaded player
|
|
virtual CompoundTag *loadPlayerDataTag(PlayerUID xuid);
|
|
virtual void clearOldPlayerFiles(); // 4J Added
|
|
PlayerIO *getPlayerIO();
|
|
virtual void closeAll();
|
|
ConsoleSavePath getDataFile(const wstring& id);
|
|
wstring getLevelId();
|
|
|
|
// 4J Added
|
|
virtual int getAuxValueForMap(PlayerUID xuid, int dimension, int centreXC, int centreZC, int scale);
|
|
virtual void saveMapIdLookup();
|
|
virtual void deleteMapFilesForPlayer(shared_ptr<Player> player);
|
|
virtual void saveAllCachedData();
|
|
void resetNetherPlayerPositions(); // 4J Added
|
|
static wstring getPlayerDir() { return sc_szPlayerDir; }
|
|
|
|
private:
|
|
void dontSaveMapMappingForPlayer(PlayerUID xuid);
|
|
void deleteMapFilesForPlayer(PlayerUID xuid);
|
|
};
|