Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Normalize EOL for all files that Git considers text files.
* text=auto eol=lf
33 changes: 33 additions & 0 deletions .github/workflows/ci_cd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# This workflow will build a .NET project
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-net

name: .NET

on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]

jobs:
build:

runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 8.0.x

- name: Restore dependencies
run: dotnet restore

- name: Build
run: dotnet build --no-restore

- name: Test
run: dotnet test --no-build --verbosity normal
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,18 @@ export_presets.cfg

# Imported translations (automatically generated from CSV files)
*.translation
**/*.translate

# Mono-specific ignores
.mono/
data_*/
mono_crash.*.json

# Editor ignores
.idea/
.vs/
EQGodot.sln.DotSettings.user

# Other files
orig_files/
open_lore.yaml
9 changes: 9 additions & 0 deletions DESIGN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Asset Loading
Godot generally likes files to be imported into the editor so they can be used. But that means that imported files are
then packaged into the files that are distributed, which is against the EULA.

An equivalent to Lantern Extractor is possible, but the user will need to run it on their copy of EQ, and it seems like
an extra hurdle.

There is a ResourceManager class that orchestrates all the loading, loaded assets go into 2 categories, global assets
and zone assets. Zone assets get wiped on switching zone. Ondemand assets will be considered zone assets.
25 changes: 25 additions & 0 deletions EQGodot.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.9.34728.123
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EQGodot", "EQGodot.csproj", "{DDFE35FB-AC86-49A7-A617-7407C3341077}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
ExportDebug|Any CPU = ExportDebug|Any CPU
ExportRelease|Any CPU = ExportRelease|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{DDFE35FB-AC86-49A7-A617-7407C3341077}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DDFE35FB-AC86-49A7-A617-7407C3341077}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DDFE35FB-AC86-49A7-A617-7407C3341077}.ExportDebug|Any CPU.ActiveCfg = ExportDebug|Any CPU
{DDFE35FB-AC86-49A7-A617-7407C3341077}.ExportDebug|Any CPU.Build.0 = ExportDebug|Any CPU
{DDFE35FB-AC86-49A7-A617-7407C3341077}.ExportRelease|Any CPU.ActiveCfg = ExportRelease|Any CPU
{DDFE35FB-AC86-49A7-A617-7407C3341077}.ExportRelease|Any CPU.Build.0 = ExportRelease|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
26 changes: 26 additions & 0 deletions GameController/GameConfig.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System.Collections.Generic;
using System.IO;
using System.Net;

namespace EQGodot.GameController;

public sealed class GameConfig
{
private static GameConfig _instance;

public string AssetPath { get; private set; }
public string LoginServerHostname { get; private set; }
public int LoginServerPort { get; private set; }


private GameConfig()
{
var deserializer = new YamlDotNet.Serialization.Deserializer();
var dict = deserializer.Deserialize<Dictionary<string, string>>(File.ReadAllText("open_lore.yaml"));
AssetPath = dict["asset_path"];
LoginServerHostname = dict["login_server_host"];
LoginServerPort = int.Parse(dict["login_server_port"]);
}

public static GameConfig Instance => _instance ??= new GameConfig();
}
112 changes: 112 additions & 0 deletions GameController/GameController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
using EQGodot.login_server;
using EQGodot.network_manager.login_server;
using EQGodot.network_manager.world_server;
using EQGodot.resource_manager;
using Godot;
using System;

namespace EQGodot.GameController;

public partial class GameController : Node
{
private Node ActiveScene;
private EQServerDescription ActiveServer;
private LoginSession NetworkLoginSession;
private WorldSession NetworkWorldSession;
private byte[] PlayerKey;
private uint PlayerLSID;

private ResourceManager _resources;

private enum State
{
NONE,
LOGIN,
SERVER_SELECTION,
RENDERING,
}

private State _state = State.NONE;

public override void _Ready()
{
_resources = GetNode<ResourceManager>("ResourceManager");
SwitchState(State.RENDERING);
}

public override void _Process(double delta)
{
}

private void SwitchState(State newState)
{
if (_state != State.NONE)
{
ActiveScene.QueueFree();
}

switch (newState)
{
case State.LOGIN:
var loginScene = ResourceLoader.Load<PackedScene>("res://login_server/login_screen.tscn");
ActiveScene = loginScene.Instantiate<login_screen>();
((login_screen)ActiveScene).DoLogin += OnLoginScreenDoLogin;
AddChild(ActiveScene);
break;
case State.SERVER_SELECTION:
var serverSelectionScene = ResourceLoader.Load<PackedScene>("res://login_server/server_selection.tscn");
ActiveScene = serverSelectionScene.Instantiate<server_selection>();
((server_selection)ActiveScene).ServerJoinStart += OnServerJoinStart;
AddChild(ActiveScene);
break;
case State.RENDERING:
var baseRenderingScene = ResourceLoader.Load<PackedScene>("res://base_scene.tscn");
ActiveScene = baseRenderingScene.Instantiate<Node3D>();
AddChild(ActiveScene);
break;
case State.NONE:
break;
default:
throw new ArgumentOutOfRangeException(nameof(newState), newState, null);
}
}


private void OnLoginScreenDoLogin(string username, string password)
{
NetworkLoginSession = new LoginSession(username, password);
NetworkLoginSession.MessageUpdate += ((login_screen)ActiveScene).OnMessageUpdate;
NetworkLoginSession.ServerListReceived += OnServerListReceived;
NetworkLoginSession.LoggedIn += OnLoggedIn;
AddChild(NetworkLoginSession);
}

private void OnLoggedIn(uint lsid, byte[] key)
{
PlayerLSID = lsid;
PlayerKey = key;
}

private void OnServerListReceived(EQServerDescription[] servers)
{
SwitchState(State.SERVER_SELECTION);
((server_selection)ActiveScene).LoadServers(servers);
}

private void OnServerJoinStart(EQServerDescription server)
{
ActiveServer = server;
NetworkLoginSession.ServerJoinAccepted += OnServerJoinAccepted;
NetworkLoginSession.JoinServer(ActiveServer);
}

private void OnServerJoinAccepted()
{
SwitchState(State.RENDERING);

GD.Print($"Accepted on server {ActiveServer.LongName}, proceeding to join world server");

NetworkWorldSession = new WorldSession(PlayerLSID, PlayerKey, ActiveServer);
AddChild(NetworkWorldSession);
}
}
30 changes: 30 additions & 0 deletions GameController/GameController.tscn
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
[gd_scene load_steps=5 format=3 uid="uid://d3dhtpjlmacg7"]

[ext_resource type="Script" path="res://GameController/GameController.cs" id="1_yhlwj"]
[ext_resource type="Script" path="res://resource_manager/ResourceManager.cs" id="2_57lqd"]
[ext_resource type="Script" path="res://resource_manager/EqGlobalResources.cs" id="3_74vw4"]
[ext_resource type="Script" path="res://resource_manager/EqZoneResources.cs" id="4_nswmo"]

[node name="GameController" type="Node"]
script = ExtResource("1_yhlwj")

[node name="ResourceManager" type="Node" parent="."]
process_thread_group = 2
process_thread_group_order = 0
process_thread_messages = 1
script = ExtResource("2_57lqd")

[node name="SceneRoot" type="Node3D" parent="ResourceManager"]
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0, 0, 0)

[node name="GlobalResources" type="Node" parent="ResourceManager"]
process_thread_group = 2
process_thread_group_order = 0
process_thread_messages = 1
script = ExtResource("3_74vw4")

[node name="ZoneResources" type="Node" parent="ResourceManager"]
process_thread_group = 2
process_thread_group_order = 0
process_thread_messages = 0
script = ExtResource("4_nswmo")
15 changes: 15 additions & 0 deletions GlobalSuppressions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// This file is used by Code Analysis to maintain SuppressMessage
// attributes that are applied to this project.
// Project-level suppressions either have no target or are given
// a specific target and scoped to a namespace, type, member, etc.

using System.Diagnostics.CodeAnalysis;

[assembly: SuppressMessage(
"Interoperability",
"CA1416:Validate platform compatibility",
Justification = "",
Scope = "member",
Target =
"~M:EQGodot2.resource_manager.pack_file.PfsArchive.ProcessBMPImage(EQGodot2.resource_manager.pack_file.PFSFile)~Godot.ImageTexture"
)]
8 changes: 8 additions & 0 deletions GlobalVariables.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using System;

namespace EQGodot;

public static class GlobalVariables
{
public static Random Rand = new();
}
18 changes: 17 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,17 @@
# openlore
# OpenLore

Build a client compatible with EQEmu

## Godot version

We will be using 4.3 that you can download here
https://godotengine.org/download/archive/4.3-stable/

## Lantern Extractor

A good chunk of code is taken from Lantern and adapted. I annotated all the classes that mostly come from Lantern, for
more information please visit their github: https://github.com/LanternEQ/LanternExtractor

## Running

The folder `orig_files` should contain all the original files, you can copy your original folder there.
7 changes: 7 additions & 0 deletions addons/debug_camera/plugin.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[plugin]

name="Debug Camera"
description="A debug camera for Godot 4"
author="Kcfresh53"
version="0.1"
script="scripts/plugin.gd"
23 changes: 23 additions & 0 deletions addons/debug_camera/scripts/DebugCamAutoload.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
extends Node

var debug_cam_2d = preload("res://addons/debug_camera/scripts/DebugCamera2D.gd")
var debug_cam_3d = preload("res://addons/debug_camera/scripts/DebugCamera3D.gd")


func _ready() -> void:
var cam_2d := debug_cam_2d.new()
var cam_3d := debug_cam_3d.new()

get_tree().current_scene.tree_exited.connect(_new_scene)

if get_viewport().get_camera_2d() != null:
get_tree().current_scene.add_child(cam_2d)
elif get_viewport().get_camera_3d() != null:
get_tree().current_scene.add_child(cam_3d)


func _new_scene():
if get_tree() != null:
await get_tree().node_added
await get_tree().get_current_scene().ready
_ready()
Loading