Initial commit: wowee native WoW 3.3.5a client

This commit is contained in:
Kelsi 2026-02-02 12:24:50 -08:00
commit ce6cb8f38e
147 changed files with 32347 additions and 0 deletions

View file

@ -0,0 +1,106 @@
#pragma once
#include "core/window.hpp"
#include "core/input.hpp"
#include <memory>
#include <string>
#include <vector>
namespace wowee {
// Forward declarations
namespace rendering { class Renderer; }
namespace ui { class UIManager; }
namespace auth { class AuthHandler; }
namespace game { class GameHandler; class World; class NpcManager; }
namespace pipeline { class AssetManager; }
namespace core {
enum class AppState {
AUTHENTICATION,
REALM_SELECTION,
CHARACTER_SELECTION,
IN_GAME,
DISCONNECTED
};
class Application {
public:
Application();
~Application();
Application(const Application&) = delete;
Application& operator=(const Application&) = delete;
bool initialize();
void run();
void shutdown();
// State management
AppState getState() const { return state; }
void setState(AppState newState);
// Accessors
Window* getWindow() { return window.get(); }
rendering::Renderer* getRenderer() { return renderer.get(); }
ui::UIManager* getUIManager() { return uiManager.get(); }
auth::AuthHandler* getAuthHandler() { return authHandler.get(); }
game::GameHandler* getGameHandler() { return gameHandler.get(); }
game::World* getWorld() { return world.get(); }
pipeline::AssetManager* getAssetManager() { return assetManager.get(); }
// Singleton access
static Application& getInstance() { return *instance; }
// Single-player mode
void startSinglePlayer();
bool isSinglePlayer() const { return singlePlayerMode; }
// Weapon loading (called at spawn and on equipment change)
void loadEquippedWeapons();
// Character skin composite state (saved at spawn for re-compositing on equipment change)
const std::string& getBodySkinPath() const { return bodySkinPath_; }
const std::vector<std::string>& getUnderwearPaths() const { return underwearPaths_; }
uint32_t getSkinTextureSlotIndex() const { return skinTextureSlotIndex_; }
uint32_t getCloakTextureSlotIndex() const { return cloakTextureSlotIndex_; }
private:
void update(float deltaTime);
void render();
void setupUICallbacks();
void spawnPlayerCharacter();
void spawnNpcs();
static Application* instance;
std::unique_ptr<Window> window;
std::unique_ptr<rendering::Renderer> renderer;
std::unique_ptr<ui::UIManager> uiManager;
std::unique_ptr<auth::AuthHandler> authHandler;
std::unique_ptr<game::GameHandler> gameHandler;
std::unique_ptr<game::World> world;
std::unique_ptr<game::NpcManager> npcManager;
std::unique_ptr<pipeline::AssetManager> assetManager;
AppState state = AppState::AUTHENTICATION;
bool running = false;
bool singlePlayerMode = false;
bool playerCharacterSpawned = false;
bool npcsSpawned = false;
float lastFrameTime = 0.0f;
float movementHeartbeatTimer = 0.0f;
// Weapon model ID counter (starting high to avoid collision with character model IDs)
uint32_t nextWeaponModelId_ = 1000;
// Saved at spawn for skin re-compositing
std::string bodySkinPath_;
std::vector<std::string> underwearPaths_;
uint32_t skinTextureSlotIndex_ = 0;
uint32_t cloakTextureSlotIndex_ = 0;
};
} // namespace core
} // namespace wowee

57
include/core/input.hpp Normal file
View file

@ -0,0 +1,57 @@
#pragma once
#include <SDL2/SDL.h>
#include <array>
#include <glm/glm.hpp>
namespace wowee {
namespace core {
class Input {
public:
static Input& getInstance();
void update();
void handleEvent(const SDL_Event& event);
// Keyboard
bool isKeyPressed(SDL_Scancode key) const;
bool isKeyJustPressed(SDL_Scancode key) const;
bool isKeyJustReleased(SDL_Scancode key) const;
// Mouse
bool isMouseButtonPressed(int button) const;
bool isMouseButtonJustPressed(int button) const;
bool isMouseButtonJustReleased(int button) const;
glm::vec2 getMousePosition() const { return mousePosition; }
glm::vec2 getMouseDelta() const { return mouseDelta; }
float getMouseWheelDelta() const { return mouseWheelDelta; }
bool isMouseLocked() const { return mouseLocked; }
void setMouseLocked(bool locked);
private:
Input() = default;
~Input() = default;
Input(const Input&) = delete;
Input& operator=(const Input&) = delete;
static constexpr int NUM_KEYS = SDL_NUM_SCANCODES;
static constexpr int NUM_MOUSE_BUTTONS = 8;
std::array<bool, NUM_KEYS> currentKeyState = {};
std::array<bool, NUM_KEYS> previousKeyState = {};
std::array<bool, NUM_MOUSE_BUTTONS> currentMouseState = {};
std::array<bool, NUM_MOUSE_BUTTONS> previousMouseState = {};
glm::vec2 mousePosition = glm::vec2(0.0f);
glm::vec2 previousMousePosition = glm::vec2(0.0f);
glm::vec2 mouseDelta = glm::vec2(0.0f);
float mouseWheelDelta = 0.0f;
bool mouseLocked = false;
};
} // namespace core
} // namespace wowee

76
include/core/logger.hpp Normal file
View file

@ -0,0 +1,76 @@
#pragma once
#include <string>
#include <iostream>
#include <sstream>
#include <mutex>
namespace wowee {
namespace core {
enum class LogLevel {
DEBUG,
INFO,
WARNING,
ERROR,
FATAL
};
class Logger {
public:
static Logger& getInstance();
void log(LogLevel level, const std::string& message);
void setLogLevel(LogLevel level);
template<typename... Args>
void debug(Args&&... args) {
log(LogLevel::DEBUG, format(std::forward<Args>(args)...));
}
template<typename... Args>
void info(Args&&... args) {
log(LogLevel::INFO, format(std::forward<Args>(args)...));
}
template<typename... Args>
void warning(Args&&... args) {
log(LogLevel::WARNING, format(std::forward<Args>(args)...));
}
template<typename... Args>
void error(Args&&... args) {
log(LogLevel::ERROR, format(std::forward<Args>(args)...));
}
template<typename... Args>
void fatal(Args&&... args) {
log(LogLevel::FATAL, format(std::forward<Args>(args)...));
}
private:
Logger() = default;
~Logger() = default;
Logger(const Logger&) = delete;
Logger& operator=(const Logger&) = delete;
template<typename... Args>
std::string format(Args&&... args) {
std::ostringstream oss;
(oss << ... << args);
return oss.str();
}
LogLevel minLevel = LogLevel::DEBUG;
std::mutex mutex;
};
// Convenience macros
#define LOG_DEBUG(...) wowee::core::Logger::getInstance().debug(__VA_ARGS__)
#define LOG_INFO(...) wowee::core::Logger::getInstance().info(__VA_ARGS__)
#define LOG_WARNING(...) wowee::core::Logger::getInstance().warning(__VA_ARGS__)
#define LOG_ERROR(...) wowee::core::Logger::getInstance().error(__VA_ARGS__)
#define LOG_FATAL(...) wowee::core::Logger::getInstance().fatal(__VA_ARGS__)
} // namespace core
} // namespace wowee

54
include/core/window.hpp Normal file
View file

@ -0,0 +1,54 @@
#pragma once
#include <string>
#include <memory>
#include <SDL2/SDL.h>
namespace wowee {
namespace core {
struct WindowConfig {
std::string title = "Wowser Native";
int width = 1920;
int height = 1080;
bool fullscreen = false;
bool vsync = true;
bool resizable = true;
};
class Window {
public:
explicit Window(const WindowConfig& config);
~Window();
Window(const Window&) = delete;
Window& operator=(const Window&) = delete;
bool initialize();
void shutdown();
void swapBuffers();
void pollEvents();
bool shouldClose() const { return shouldCloseFlag; }
void setShouldClose(bool value) { shouldCloseFlag = value; }
int getWidth() const { return width; }
int getHeight() const { return height; }
float getAspectRatio() const { return static_cast<float>(width) / height; }
SDL_Window* getSDLWindow() const { return window; }
SDL_GLContext getGLContext() const { return glContext; }
private:
WindowConfig config;
SDL_Window* window = nullptr;
SDL_GLContext glContext = nullptr;
int width;
int height;
bool shouldCloseFlag = false;
};
} // namespace core
} // namespace wowee