From 578c53dc78fd46cdd32d0881d9ade76906647088 Mon Sep 17 00:00:00 2001 From: Pablo Alcubilla Date: Sun, 15 Dec 2024 20:14:26 +0000 Subject: [PATCH] Initial commit with a copy of previous project. --- .gitattributes | 2 + .github/workflows/ci_cd.yml | 33 ++ .gitignore | 10 + DESIGN.md | 9 + EQGodot.sln | 25 + GameController/GameConfig.cs | 26 + GameController/GameController.cs | 112 ++++ GameController/GameController.tscn | 30 + GlobalSuppressions.cs | 15 + GlobalVariables.cs | 8 + README.md | 18 +- addons/debug_camera/plugin.cfg | 7 + .../debug_camera/scripts/DebugCamAutoload.gd | 23 + addons/debug_camera/scripts/DebugCamera2D.gd | 61 ++ addons/debug_camera/scripts/DebugCamera3D.gd | 60 ++ addons/debug_camera/scripts/plugin.gd | 10 + .../Importers/EqEditorSceneImporter.cs | 73 +++ .../Importers/EqPackFileImporter.cs | 79 +++ .../Importers/EqPackFileResourceLoader.cs | 51 ++ addons/pfs_loader/pfs_loader.gd | 29 + addons/pfs_loader/plugin.cfg | 7 + base_scene.gd | 1 + base_scene.tscn | 58 ++ button.gd | 10 + class_selection.gd | 43 ++ icon.svg | 1 + login_server/login_screen.cs | 22 + login_server/login_screen.tscn | 117 ++++ login_server/server_selection.cs | 39 ++ login_server/server_selection.tscn | 84 +++ .../login_server/CSGetServerList.cs | 17 + network_manager/login_server/CSHandshake.cs | 20 + network_manager/login_server/CSJoinServer.cs | 24 + network_manager/login_server/CSPlayerLogin.cs | 44 ++ .../login_server/EQServerDescription.cs | 15 + network_manager/login_server/LoginSession.cs | 121 ++++ .../login_server/SCGetServerListReply.cs | 40 ++ .../login_server/SCHandshakeReply.cs | 26 + .../login_server/SCJoinServerReply.cs | 30 + .../login_server/SCPlayerLoginReply.cs | 37 ++ .../login_server/SCSetGameFeatures.cs | 18 + network_manager/network_session/AppPacket.cs | 34 ++ .../network_session/NetworkSession.cs | 261 +++++++++ .../network_session/OpcodeManager.cs | 41 ++ network_manager/packets/CRC.cs | 52 ++ network_manager/packets/DESCrypto.cs | 521 ++++++++++++++++++ network_manager/packets/PacketReader.cs | 73 +++ network_manager/packets/PacketWriter.cs | 84 +++ network_manager/world_server/CSWorldAuth.cs | 30 + .../world_server/SCApproveWorld.cs | 19 + network_manager/world_server/SCEnterWorld.cs | 19 + .../world_server/SCExpansionInfo.cs | 19 + network_manager/world_server/SCGuildList.cs | 23 + network_manager/world_server/SCLogServer.cs | 19 + .../world_server/SCPostEnterWorld.cs | 19 + .../world_server/SCSetMaxCharacters.cs | 19 + .../world_server/SCSetMembership.cs | 19 + network_manager/world_server/WorldSession.cs | 114 ++++ open_lore.yaml.sample | 3 + orig_files/.gdignore | 0 orig_files/ASSETS.md | 1 + project.godot | 39 ++ resource_manager/EqGlobalResources.cs | 26 + resource_manager/EqResourceLoader.cs | 127 +++++ resource_manager/EqResources.cs | 102 ++++ resource_manager/EqZoneResources.cs | 76 +++ resource_manager/ResourceManager.cs | 108 ++++ .../godot_resources/ActorDefinition.cs | 8 + .../godot_resources/ActorSkeletonBone.cs | 20 + .../godot_resources/ActorSkeletonPath.cs | 94 ++++ .../godot_resources/BlitActorDefinition.cs | 19 + .../HierarchicalActorDefinition.cs | 82 +++ .../HierarchicalActorInstance.cs | 28 + .../converters/HierarchicalActorBuilder.cs | 69 +++ .../interfaces/IIntoGodotLight.cs | 8 + .../interfaces/IIntoGodotMaterial.cs | 8 + resource_manager/interfaces/IIntoGodotMesh.cs | 8 + resource_manager/interfaces/IIntoGodotZone.cs | 8 + resource_manager/pack_file/PFSFile.cs | 22 + resource_manager/pack_file/PackFileParser.cs | 128 +++++ resource_manager/pack_file/PfsArchive.cs | 185 +++++++ resource_manager/pack_file/PfsArchiveType.cs | 8 + resource_manager/wld_file/WldFile.cs | 309 +++++++++++ resource_manager/wld_file/WldFragment.cs | 28 + .../wld_file/WldFragmentBuilder.cs | 56 ++ .../wld_file/fragments/Frag00Default.cs | 7 + .../fragments/Frag01DefaultPaletteFile.cs | 7 + .../wld_file/fragments/Frag02UserData.cs | 7 + .../wld_file/fragments/Frag03BMInfo.cs | 29 + .../fragments/Frag04SimpleSpriteDef.cs | 42 ++ .../wld_file/fragments/Frag05SimpleSprite.cs | 28 + .../wld_file/fragments/Frag06Sprite2DDef.cs | 7 + .../wld_file/fragments/Frag07Sprite2D.cs | 7 + .../wld_file/fragments/Frag08Sprite3DDef.cs | 7 + .../wld_file/fragments/Frag09Sprite3D.cs | 7 + .../fragments/Frag10HierarchicalSpriteDef.cs | 222 ++++++++ .../fragments/Frag11HierarchicalSprite.cs | 39 ++ .../wld_file/fragments/Frag12TrackDef.cs | 92 ++++ .../wld_file/fragments/Frag13Track.cs | 124 +++++ .../wld_file/fragments/Frag14ActorDef.cs | 162 ++++++ .../wld_file/fragments/Frag15ActorInstance.cs | 56 ++ .../wld_file/fragments/Frag16Sphere.cs | 7 + .../wld_file/fragments/Frag17PolyhedronDef.cs | 7 + .../wld_file/fragments/Frag18Polyhedron.cs | 7 + .../wld_file/fragments/Frag1BLightDef.cs | 51 ++ .../wld_file/fragments/Frag1CLight.cs | 17 + .../wld_file/fragments/Frag21WorldTree.cs | 79 +++ .../wld_file/fragments/Frag22Region.cs | 79 +++ .../wld_file/fragments/Frag26BlitSpriteDef.cs | 20 + .../wld_file/fragments/Frag27BlitSprite.cs | 19 + .../wld_file/fragments/Frag28PointLight.cs | 38 ++ .../wld_file/fragments/Frag29Zone.cs | 136 +++++ .../wld_file/fragments/Frag2AAmbientLight.cs | 29 + .../wld_file/fragments/Frag2CDmSpriteDef.cs | 242 ++++++++ .../wld_file/fragments/Frag2DDmSprite.cs | 28 + .../wld_file/fragments/Frag30MaterialDef.cs | 281 ++++++++++ .../fragments/Frag31MaterialPalette.cs | 163 ++++++ .../wld_file/fragments/Frag32DmRGBTrackDef.cs | 7 + .../wld_file/fragments/Frag33DmRGBTrack.cs | 17 + .../fragments/Frag34ParticleCloudDef.cs | 43 ++ .../fragments/Frag35GlobalAmbientLightDef.cs | 25 + .../wld_file/fragments/Frag36DmSpriteDef2.cs | 275 +++++++++ .../wld_file/fragments/FragXXFallback.cs | 7 + .../wld_file/helpers/BitAnalyzer.cs | 31 ++ .../wld_file/helpers/FragmentNameCleaner.cs | 35 ++ .../wld_file/helpers/WldStringDecoder.cs | 15 + resources.md | 1 + 127 files changed, 6892 insertions(+), 1 deletion(-) create mode 100644 .gitattributes create mode 100644 .github/workflows/ci_cd.yml create mode 100644 DESIGN.md create mode 100644 EQGodot.sln create mode 100644 GameController/GameConfig.cs create mode 100644 GameController/GameController.cs create mode 100644 GameController/GameController.tscn create mode 100644 GlobalSuppressions.cs create mode 100644 GlobalVariables.cs create mode 100644 addons/debug_camera/plugin.cfg create mode 100644 addons/debug_camera/scripts/DebugCamAutoload.gd create mode 100644 addons/debug_camera/scripts/DebugCamera2D.gd create mode 100644 addons/debug_camera/scripts/DebugCamera3D.gd create mode 100644 addons/debug_camera/scripts/plugin.gd create mode 100644 addons/pfs_loader/Importers/EqEditorSceneImporter.cs create mode 100644 addons/pfs_loader/Importers/EqPackFileImporter.cs create mode 100644 addons/pfs_loader/Importers/EqPackFileResourceLoader.cs create mode 100644 addons/pfs_loader/pfs_loader.gd create mode 100644 addons/pfs_loader/plugin.cfg create mode 100644 base_scene.gd create mode 100644 base_scene.tscn create mode 100644 button.gd create mode 100644 class_selection.gd create mode 100644 icon.svg create mode 100644 login_server/login_screen.cs create mode 100644 login_server/login_screen.tscn create mode 100644 login_server/server_selection.cs create mode 100644 login_server/server_selection.tscn create mode 100644 network_manager/login_server/CSGetServerList.cs create mode 100644 network_manager/login_server/CSHandshake.cs create mode 100644 network_manager/login_server/CSJoinServer.cs create mode 100644 network_manager/login_server/CSPlayerLogin.cs create mode 100644 network_manager/login_server/EQServerDescription.cs create mode 100644 network_manager/login_server/LoginSession.cs create mode 100644 network_manager/login_server/SCGetServerListReply.cs create mode 100644 network_manager/login_server/SCHandshakeReply.cs create mode 100644 network_manager/login_server/SCJoinServerReply.cs create mode 100644 network_manager/login_server/SCPlayerLoginReply.cs create mode 100644 network_manager/login_server/SCSetGameFeatures.cs create mode 100644 network_manager/network_session/AppPacket.cs create mode 100644 network_manager/network_session/NetworkSession.cs create mode 100644 network_manager/network_session/OpcodeManager.cs create mode 100644 network_manager/packets/CRC.cs create mode 100644 network_manager/packets/DESCrypto.cs create mode 100644 network_manager/packets/PacketReader.cs create mode 100644 network_manager/packets/PacketWriter.cs create mode 100644 network_manager/world_server/CSWorldAuth.cs create mode 100644 network_manager/world_server/SCApproveWorld.cs create mode 100644 network_manager/world_server/SCEnterWorld.cs create mode 100644 network_manager/world_server/SCExpansionInfo.cs create mode 100644 network_manager/world_server/SCGuildList.cs create mode 100644 network_manager/world_server/SCLogServer.cs create mode 100644 network_manager/world_server/SCPostEnterWorld.cs create mode 100644 network_manager/world_server/SCSetMaxCharacters.cs create mode 100644 network_manager/world_server/SCSetMembership.cs create mode 100644 network_manager/world_server/WorldSession.cs create mode 100644 open_lore.yaml.sample create mode 100644 orig_files/.gdignore create mode 100644 orig_files/ASSETS.md create mode 100644 project.godot create mode 100644 resource_manager/EqGlobalResources.cs create mode 100644 resource_manager/EqResourceLoader.cs create mode 100644 resource_manager/EqResources.cs create mode 100644 resource_manager/EqZoneResources.cs create mode 100644 resource_manager/ResourceManager.cs create mode 100644 resource_manager/godot_resources/ActorDefinition.cs create mode 100644 resource_manager/godot_resources/ActorSkeletonBone.cs create mode 100644 resource_manager/godot_resources/ActorSkeletonPath.cs create mode 100644 resource_manager/godot_resources/BlitActorDefinition.cs create mode 100644 resource_manager/godot_resources/HierarchicalActorDefinition.cs create mode 100644 resource_manager/godot_resources/HierarchicalActorInstance.cs create mode 100644 resource_manager/godot_resources/converters/HierarchicalActorBuilder.cs create mode 100644 resource_manager/interfaces/IIntoGodotLight.cs create mode 100644 resource_manager/interfaces/IIntoGodotMaterial.cs create mode 100644 resource_manager/interfaces/IIntoGodotMesh.cs create mode 100644 resource_manager/interfaces/IIntoGodotZone.cs create mode 100644 resource_manager/pack_file/PFSFile.cs create mode 100644 resource_manager/pack_file/PackFileParser.cs create mode 100644 resource_manager/pack_file/PfsArchive.cs create mode 100644 resource_manager/pack_file/PfsArchiveType.cs create mode 100644 resource_manager/wld_file/WldFile.cs create mode 100644 resource_manager/wld_file/WldFragment.cs create mode 100644 resource_manager/wld_file/WldFragmentBuilder.cs create mode 100644 resource_manager/wld_file/fragments/Frag00Default.cs create mode 100644 resource_manager/wld_file/fragments/Frag01DefaultPaletteFile.cs create mode 100644 resource_manager/wld_file/fragments/Frag02UserData.cs create mode 100644 resource_manager/wld_file/fragments/Frag03BMInfo.cs create mode 100644 resource_manager/wld_file/fragments/Frag04SimpleSpriteDef.cs create mode 100644 resource_manager/wld_file/fragments/Frag05SimpleSprite.cs create mode 100644 resource_manager/wld_file/fragments/Frag06Sprite2DDef.cs create mode 100644 resource_manager/wld_file/fragments/Frag07Sprite2D.cs create mode 100644 resource_manager/wld_file/fragments/Frag08Sprite3DDef.cs create mode 100644 resource_manager/wld_file/fragments/Frag09Sprite3D.cs create mode 100644 resource_manager/wld_file/fragments/Frag10HierarchicalSpriteDef.cs create mode 100644 resource_manager/wld_file/fragments/Frag11HierarchicalSprite.cs create mode 100644 resource_manager/wld_file/fragments/Frag12TrackDef.cs create mode 100644 resource_manager/wld_file/fragments/Frag13Track.cs create mode 100644 resource_manager/wld_file/fragments/Frag14ActorDef.cs create mode 100644 resource_manager/wld_file/fragments/Frag15ActorInstance.cs create mode 100644 resource_manager/wld_file/fragments/Frag16Sphere.cs create mode 100644 resource_manager/wld_file/fragments/Frag17PolyhedronDef.cs create mode 100644 resource_manager/wld_file/fragments/Frag18Polyhedron.cs create mode 100644 resource_manager/wld_file/fragments/Frag1BLightDef.cs create mode 100644 resource_manager/wld_file/fragments/Frag1CLight.cs create mode 100644 resource_manager/wld_file/fragments/Frag21WorldTree.cs create mode 100644 resource_manager/wld_file/fragments/Frag22Region.cs create mode 100644 resource_manager/wld_file/fragments/Frag26BlitSpriteDef.cs create mode 100644 resource_manager/wld_file/fragments/Frag27BlitSprite.cs create mode 100644 resource_manager/wld_file/fragments/Frag28PointLight.cs create mode 100644 resource_manager/wld_file/fragments/Frag29Zone.cs create mode 100644 resource_manager/wld_file/fragments/Frag2AAmbientLight.cs create mode 100644 resource_manager/wld_file/fragments/Frag2CDmSpriteDef.cs create mode 100644 resource_manager/wld_file/fragments/Frag2DDmSprite.cs create mode 100644 resource_manager/wld_file/fragments/Frag30MaterialDef.cs create mode 100644 resource_manager/wld_file/fragments/Frag31MaterialPalette.cs create mode 100644 resource_manager/wld_file/fragments/Frag32DmRGBTrackDef.cs create mode 100644 resource_manager/wld_file/fragments/Frag33DmRGBTrack.cs create mode 100644 resource_manager/wld_file/fragments/Frag34ParticleCloudDef.cs create mode 100644 resource_manager/wld_file/fragments/Frag35GlobalAmbientLightDef.cs create mode 100644 resource_manager/wld_file/fragments/Frag36DmSpriteDef2.cs create mode 100644 resource_manager/wld_file/fragments/FragXXFallback.cs create mode 100644 resource_manager/wld_file/helpers/BitAnalyzer.cs create mode 100644 resource_manager/wld_file/helpers/FragmentNameCleaner.cs create mode 100644 resource_manager/wld_file/helpers/WldStringDecoder.cs create mode 100644 resources.md diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..8ad74f7 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Normalize EOL for all files that Git considers text files. +* text=auto eol=lf diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml new file mode 100644 index 0000000..486c04e --- /dev/null +++ b/.github/workflows/ci_cd.yml @@ -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 diff --git a/.gitignore b/.gitignore index d9aac21..f4fd849 100644 --- a/.gitignore +++ b/.gitignore @@ -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 \ No newline at end of file diff --git a/DESIGN.md b/DESIGN.md new file mode 100644 index 0000000..28c54dc --- /dev/null +++ b/DESIGN.md @@ -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. diff --git a/EQGodot.sln b/EQGodot.sln new file mode 100644 index 0000000..7057926 --- /dev/null +++ b/EQGodot.sln @@ -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 diff --git a/GameController/GameConfig.cs b/GameController/GameConfig.cs new file mode 100644 index 0000000..4c62ef6 --- /dev/null +++ b/GameController/GameConfig.cs @@ -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>(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(); +} \ No newline at end of file diff --git a/GameController/GameController.cs b/GameController/GameController.cs new file mode 100644 index 0000000..e775874 --- /dev/null +++ b/GameController/GameController.cs @@ -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"); + 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("res://login_server/login_screen.tscn"); + ActiveScene = loginScene.Instantiate(); + ((login_screen)ActiveScene).DoLogin += OnLoginScreenDoLogin; + AddChild(ActiveScene); + break; + case State.SERVER_SELECTION: + var serverSelectionScene = ResourceLoader.Load("res://login_server/server_selection.tscn"); + ActiveScene = serverSelectionScene.Instantiate(); + ((server_selection)ActiveScene).ServerJoinStart += OnServerJoinStart; + AddChild(ActiveScene); + break; + case State.RENDERING: + var baseRenderingScene = ResourceLoader.Load("res://base_scene.tscn"); + ActiveScene = baseRenderingScene.Instantiate(); + 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); + } +} \ No newline at end of file diff --git a/GameController/GameController.tscn b/GameController/GameController.tscn new file mode 100644 index 0000000..3be06c3 --- /dev/null +++ b/GameController/GameController.tscn @@ -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") diff --git a/GlobalSuppressions.cs b/GlobalSuppressions.cs new file mode 100644 index 0000000..3ee7231 --- /dev/null +++ b/GlobalSuppressions.cs @@ -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" +)] \ No newline at end of file diff --git a/GlobalVariables.cs b/GlobalVariables.cs new file mode 100644 index 0000000..1587cc8 --- /dev/null +++ b/GlobalVariables.cs @@ -0,0 +1,8 @@ +using System; + +namespace EQGodot; + +public static class GlobalVariables +{ + public static Random Rand = new(); +} \ No newline at end of file diff --git a/README.md b/README.md index 4f5e036..bc619a6 100644 --- a/README.md +++ b/README.md @@ -1 +1,17 @@ -# openlore \ No newline at end of file +# 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. \ No newline at end of file diff --git a/addons/debug_camera/plugin.cfg b/addons/debug_camera/plugin.cfg new file mode 100644 index 0000000..78280aa --- /dev/null +++ b/addons/debug_camera/plugin.cfg @@ -0,0 +1,7 @@ +[plugin] + +name="Debug Camera" +description="A debug camera for Godot 4" +author="Kcfresh53" +version="0.1" +script="scripts/plugin.gd" diff --git a/addons/debug_camera/scripts/DebugCamAutoload.gd b/addons/debug_camera/scripts/DebugCamAutoload.gd new file mode 100644 index 0000000..b3ea3ba --- /dev/null +++ b/addons/debug_camera/scripts/DebugCamAutoload.gd @@ -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() diff --git a/addons/debug_camera/scripts/DebugCamera2D.gd b/addons/debug_camera/scripts/DebugCamera2D.gd new file mode 100644 index 0000000..0398b72 --- /dev/null +++ b/addons/debug_camera/scripts/DebugCamera2D.gd @@ -0,0 +1,61 @@ +extends Camera2D +class_name DebugCamera2D + +# Lower cap for the `_zoom_level`. +@export var min_zoom := 0.5 +# Upper cap for the `_zoom_level`. +@export var max_zoom := 2.0 +# Controls how much we increase or decrease the `_zoom_level` on every turn of the scroll wheel. +@export var zoom_factor := 0.1 +# Duration of the zoom's tween animation. +@export var zoom_duration := 0.2 + +# The camera's target zoom level. +var _zoom_level : float = 1.0 : + set(value): + var tween = get_tree().create_tween() + # We limit the value between `min_zoom` and `max_zoom` + _zoom_level = clamp(value, min_zoom, max_zoom) + tween.tween_property(self, "zoom", Vector2(_zoom_level, _zoom_level), zoom_duration).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_OUT) + +var _previousPosition: Vector2 = Vector2(0, 0) +var _moveCamera: bool = false + +var main_cam : Camera2D + + +func _ready() -> void: + main_cam = get_viewport().get_camera_2d() + + +func _process(_delta: float) -> void: + if !enabled: + position = main_cam.global_position + + +func _unhandled_input(event: InputEvent) -> void: + if event is InputEventMouseButton: + # zoom out + if event.pressed && event.button_index == MOUSE_BUTTON_WHEEL_DOWN: + _zoom_level = _zoom_level - zoom_factor + # zoom in + if event.pressed && event.button_index == MOUSE_BUTTON_WHEEL_UP: + _zoom_level = _zoom_level + zoom_factor + + if event is InputEventMouseButton && event.button_index == MOUSE_BUTTON_RIGHT: + if event.is_pressed(): + _previousPosition = event.position + _moveCamera = true + else: + _moveCamera = false + elif event is InputEventMouseMotion && _moveCamera: + position += (_previousPosition - event.position) + _previousPosition = event.position + + # Toggle cameras + if event is InputEventKey && event.is_pressed(): + if event.keycode == KEY_MINUS: + var cam := main_cam + cam.enabled = !cam.enabled + enabled = !cam.enabled + diff --git a/addons/debug_camera/scripts/DebugCamera3D.gd b/addons/debug_camera/scripts/DebugCamera3D.gd new file mode 100644 index 0000000..17881a1 --- /dev/null +++ b/addons/debug_camera/scripts/DebugCamera3D.gd @@ -0,0 +1,60 @@ +extends Camera3D +class_name DebugCamera3D + + +@export_range(0, 10, 0.01) var sensitivity : float = 3 +@export_range(0, 1000, 0.1) var default_velocity : float = 5 +@export_range(0, 10, 0.01) var speed_scale : float = 1.17 +@export_range(1, 100, 0.1) var boost_speed_multiplier : float = 3.0 +@export var max_speed : float = 1000 +@export var min_speed : float = 0.2 + +@onready var _velocity = default_velocity + +var main_cam : Camera3D + + +func _ready() -> void: + main_cam = get_viewport().get_camera_3d() + + +func _process(delta: float) -> void: + if !current: + position = main_cam.global_position + rotation = main_cam.global_rotation + return + + var direction = Vector3( + float(Input.is_physical_key_pressed(KEY_D)) - float(Input.is_physical_key_pressed(KEY_A)), + float(Input.is_physical_key_pressed(KEY_E)) - float(Input.is_physical_key_pressed(KEY_Q)), + float(Input.is_physical_key_pressed(KEY_S)) - float(Input.is_physical_key_pressed(KEY_W)) + ).normalized() + + if Input.is_physical_key_pressed(KEY_SHIFT): # boost + translate(direction * _velocity * delta * boost_speed_multiplier) + else: + translate(direction * _velocity * delta) + + +func _unhandled_input(event: InputEvent) -> void: + if Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED: + if event is InputEventMouseMotion: + rotation.y -= event.relative.x / 1000 * sensitivity + rotation.x -= event.relative.y / 1000 * sensitivity + rotation.x = clamp(rotation.x, PI/-2, PI/2) + + if event is InputEventMouseButton: + match event.button_index: + MOUSE_BUTTON_RIGHT: + Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED if event.pressed else Input.MOUSE_MODE_VISIBLE) + MOUSE_BUTTON_WHEEL_UP: # increase fly velocity + _velocity = clamp(_velocity * speed_scale, min_speed, max_speed) + MOUSE_BUTTON_WHEEL_DOWN: # decrease fly velocity + _velocity = clamp(_velocity / speed_scale, min_speed, max_speed) + + # Toggle cameras + if event is InputEventKey && event.is_pressed(): + if event.keycode == KEY_MINUS: + var cam := main_cam + cam.current = !cam.current + current = !cam.current diff --git a/addons/debug_camera/scripts/plugin.gd b/addons/debug_camera/scripts/plugin.gd new file mode 100644 index 0000000..c787715 --- /dev/null +++ b/addons/debug_camera/scripts/plugin.gd @@ -0,0 +1,10 @@ +@tool +extends EditorPlugin + + +func _enter_tree(): + add_autoload_singleton("DebugCam", "res://addons/debug_camera/scripts/DebugCamAutoload.gd") + + +func _exit_tree(): + remove_autoload_singleton("DebugCam") diff --git a/addons/pfs_loader/Importers/EqEditorSceneImporter.cs b/addons/pfs_loader/Importers/EqEditorSceneImporter.cs new file mode 100644 index 0000000..8926f9f --- /dev/null +++ b/addons/pfs_loader/Importers/EqEditorSceneImporter.cs @@ -0,0 +1,73 @@ +using Godot; + +namespace EQGodot.addons.pfs_loader.Importers; + +[Tool] +[GlobalClass] +public partial class EqEditorSceneImporter : EditorSceneFormatImporter +{ + public override string[] _GetExtensions() + { + // GD.Print("EQEditorSceneImporter::_GetExtensions()"); + return ["s3d"]; + } + + public override Variant _GetOptionVisibility(string path, bool forAnimation, string option) + { + // GD.Print("EQEditorSceneImporter::_GetOptionVisibility()"); + return base._GetOptionVisibility(path, forAnimation, option); + } + + public override uint _GetImportFlags() + { + // GD.Print("EQEditorSceneImporter::_GetImportFlags()"); + return (uint)ImportScene | (uint)ImportAnimation; + } + + public override GodotObject _ImportScene(string path, uint flags, Godot.Collections.Dictionary options) + { + // GD.Print("EQEditorSceneImporter::_ImportScene()"); + // var resource = PackFileParser.Load(path); + var root = new Node3D(); + root.Name = path; + // var extraAnimations = new Dictionary(); + // var actordefs = new Dictionary(); + // // GD.Print(resource); + // foreach (var wld in resource.WldFiles.Values) + // { + // foreach (var actorDef in wld.ActorDefs.Values) + // { + // if (actorDef is not HierarchicalActorDefinition act) continue; + // var name = act.ResourceName; + // actordefs[name] = act; + // GD.Print($"Loaded {name}"); + // } + // + // foreach (var animation in wld.ExtraAnimations.Values) + // { + // if (extraAnimations.TryAdd(animation.Name, animation)) continue; + // GD.Print($"{animation.Name} already exists"); + // } + // } + // + // foreach (var animation in extraAnimations.Values) + // { + // var animationName = animation.Name.Substr(0, 3); + // var actorName = animation.Name.Substr(3, 3); + // var boneName = animation.Name[6..].Replace("_track", ""); + // if (boneName == "") boneName = "root"; + // + // if (!actordefs.TryGetValue(actorName, out var actor)) continue; + // if (actor.BonesByName.TryGetValue(boneName, out var bone)) bone.AnimationTracks[animationName] = animation; + // } + // + // foreach (var actor in actordefs.Values.OfType()) + // { + // // var instance = actor.InstantiateCharacter(); + // // instance.Owner = root; + // // root.AddChild(instance); + // } + + return root; + } +} \ No newline at end of file diff --git a/addons/pfs_loader/Importers/EqPackFileImporter.cs b/addons/pfs_loader/Importers/EqPackFileImporter.cs new file mode 100644 index 0000000..e49d3af --- /dev/null +++ b/addons/pfs_loader/Importers/EqPackFileImporter.cs @@ -0,0 +1,79 @@ +using System; +using Godot; +using Godot.Collections; + +namespace EQGodot.addons.pfs_loader.Importers; + +[Tool] +[GlobalClass] +public partial class EqPackFileImporter : EditorImportPlugin +{ + public override string _GetImporterName() + { + return "pfs.import.plugin"; + } + + public override string _GetVisibleName() + { + return "PFS Archive Import"; + } + + public override string[] _GetRecognizedExtensions() + { + return ["s3d", "eqg"]; + } + + public override string _GetSaveExtension() + { + return "tres"; + } + + public override string _GetResourceType() + { + return "PfsArchive"; + } + + public override int _GetPresetCount() + { + return 1; + } + + public override string _GetPresetName(int presetIndex) + { + return "Default"; + } + + public override float _GetPriority() + { + return 1.0F; + } + + public override int _GetImportOrder() + { + return 1; + } + + public override Array _GetImportOptions(string path, int presetIndex) + { + return []; + } + + public override Error _Import(string sourceFile, string savePath, Dictionary options, + Array platformVariants, Array genFiles) + { + try + { + GD.Print($"PfsArchive: Finished post-processing archive: {sourceFile}"); + var destFile = $"{savePath}.{_GetSaveExtension()}"; + // var archive = PackFileParser.Load(sourceFile); + // var result = ResourceSaver.Save(archive, destFile); + GD.Print($"PfsArchive: Finished writing archive: {sourceFile} to {destFile}"); + // return result; + } + catch (Exception e) + { + GD.PrintErr(e); + } + return Error.Failed; + } +} \ No newline at end of file diff --git a/addons/pfs_loader/Importers/EqPackFileResourceLoader.cs b/addons/pfs_loader/Importers/EqPackFileResourceLoader.cs new file mode 100644 index 0000000..9ee3aaf --- /dev/null +++ b/addons/pfs_loader/Importers/EqPackFileResourceLoader.cs @@ -0,0 +1,51 @@ +using System; +using Godot; + +namespace EQGodot.addons.pfs_loader.Importers; + +[GlobalClass] +[Tool] +public partial class EqPackFileResourceLoader : ResourceFormatLoader +{ + public override string[] _GetRecognizedExtensions() + { + // GD.Print("_GetRecognizedExtensions"); + return ["s3d", "eqg"]; + } + + public override string _GetResourceScriptClass(string path) + { + // GD.Print($"_GetResourceScriptClass({path})"); + return "PfsArchive.cs"; + } + + public override string _GetResourceType(string path) + { + // GD.Print($"_GetResourceType({path})"); + using var file = FileAccess.Open(path, FileAccess.ModeFlags.Read); + if (file.GetError() != Error.Ok) + { + GD.PrintErr("Failed to open: ", path); + throw new Exception($"Failed to open {path}"); + } + + file.BigEndian = false; + + var directoryOffset = file.Get32(); + var magicNumber = file.Get32(); + return magicNumber is 0x20534650 or 0x50465320 ? "PfsArchive" : ""; + } + + public override bool _HandlesType(StringName type) + { + // GD.Print($"_HandlesType({type})"); + return type == "PfsArchive"; + } + + public override Variant _Load(string path, string originalPath, bool useSubThreads, int cacheMode) + { + // GD.Print($"_Load({path}, {originalPath}, {useSubThreads}, {cacheMode})"); + // return PackFileParser.Load(path); + return false; + } +} \ No newline at end of file diff --git a/addons/pfs_loader/pfs_loader.gd b/addons/pfs_loader/pfs_loader.gd new file mode 100644 index 0000000..98bc057 --- /dev/null +++ b/addons/pfs_loader/pfs_loader.gd @@ -0,0 +1,29 @@ +@tool +extends EditorPlugin + +var loader +var importer +var scene_importer + +func _enter_tree() -> void: + # Initialization of the plugin goes here. + print("Initializing pfs_loader") +# loader = EqPackFileResourceLoader.new() +# ResourceLoader.add_resource_format_loader(loader) +# importer = EqPackFileImporter.new() +# add_import_plugin(importer) +# scene_importer = EqEditorSceneImporter.new() +# add_scene_format_importer_plugin(scene_importer) + +func _exit_tree() -> void: + # Clean-up of the plugin goes here. + print("Cleanup pfs_loader") + if loader != null: + ResourceLoader.remove_resource_format_loader(loader) + loader = null + if scene_importer != null: + remove_scene_format_importer_plugin(scene_importer) + scene_importer = null + if importer != null: + remove_import_plugin(importer) + importer = null diff --git a/addons/pfs_loader/plugin.cfg b/addons/pfs_loader/plugin.cfg new file mode 100644 index 0000000..7f6b8f5 --- /dev/null +++ b/addons/pfs_loader/plugin.cfg @@ -0,0 +1,7 @@ +[plugin] + +name="PFSLoader" +description="" +author="Anarelion" +version="" +script="pfs_loader.gd" diff --git a/base_scene.gd b/base_scene.gd new file mode 100644 index 0000000..67e954f --- /dev/null +++ b/base_scene.gd @@ -0,0 +1 @@ +extends Node3D diff --git a/base_scene.tscn b/base_scene.tscn new file mode 100644 index 0000000..5e90ea9 --- /dev/null +++ b/base_scene.tscn @@ -0,0 +1,58 @@ +[gd_scene load_steps=5 format=3 uid="uid://bav1ji3y2p1d4"] + +[ext_resource type="Script" path="res://base_scene.gd" id="1_p6kus"] +[ext_resource type="Script" path="res://addons/debug_camera/scripts/DebugCamera3D.gd" id="2_jnlh8"] +[ext_resource type="Script" path="res://button.gd" id="3_uaip4"] +[ext_resource type="Script" path="res://class_selection.gd" id="4_slpxg"] + +[node name="BaseScene" type="Node3D"] +transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0, 0, 0) +script = ExtResource("1_p6kus") + +[node name="Button" type="Button" parent="."] +offset_right = 41.0 +offset_bottom = 29.0 +text = "Do" +script = ExtResource("3_uaip4") + +[node name="ClassSelection" type="ItemList" parent="."] +visible = false +offset_top = 32.0 +offset_right = 61.0 +offset_bottom = 447.0 +item_count = 15 +item_0/text = "1" +item_1/text = "2" +item_2/text = "3" +item_3/text = "4" +item_4/text = "5" +item_5/text = "6" +item_6/text = "7" +item_7/text = "8" +item_8/text = "9" +item_9/text = "10" +item_10/text = "11" +item_11/text = "12" +item_12/text = "13" +item_13/text = "14" +item_14/text = "15" +script = ExtResource("4_slpxg") + +[node name="CameraPosition" type="Node3D" parent="."] + +[node name="CameraDefaultRotation" type="Node3D" parent="CameraPosition"] +transform = Transform3D(1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 0, 0) + +[node name="Camera3D" type="Camera3D" parent="CameraPosition/CameraDefaultRotation"] +script = ExtResource("2_jnlh8") + +[node name="OmniLight3D" type="OmniLight3D" parent="CameraPosition/CameraDefaultRotation/Camera3D"] +transform = Transform3D(1, 0, 0, 0, 1, 1.44355e-08, 0, -3.11993e-08, 1, 1.03417, 1.08536, 0.0851126) +light_energy = 2.057 +light_indirect_energy = 3.238 +light_size = 0.168 +omni_range = 200.0 +omni_attenuation = 0.210224 + +[connection signal="pressed" from="Button" to="Button" method="_on_button_pressed"] +[connection signal="item_selected" from="ClassSelection" to="ClassSelection" method="_on_item_selected"] diff --git a/button.gd b/button.gd new file mode 100644 index 0000000..e883c04 --- /dev/null +++ b/button.gd @@ -0,0 +1,10 @@ +extends Button + +func _on_button_pressed(): + var resources = get_tree().current_scene._resources + var character = resources.InstantiateCharacter("elm") + character.AttachItem("it149", "r_point", resources) + character.AttachItem("it227", "shield_point", resources) + + + # get_tree().current_scene.Resources.InstantiateZone() diff --git a/class_selection.gd b/class_selection.gd new file mode 100644 index 0000000..64d3d21 --- /dev/null +++ b/class_selection.gd @@ -0,0 +1,43 @@ +extends ItemList + +func _on_item_selected(index:int): + var cam = $"../CameraPosition" + if cam == null: + return + match get_item_text(index): + "1": + cam.set_position( Vector3(600.0, 1475.0, -180.0)) + "2": + cam.set_position( Vector3(603.5, -328.0, -85.0)) + "3": + cam.set_position( Vector3(-847.0, -250.0, -180.0)) + "4": + cam.set_position( Vector3(-45.0, 1415.0, 0.0)) + "5": + cam.set_position( Vector3(0.0, 680.0, 135.0)) + "6": + # sets some value to 2.2 + cam.set_position( Vector3(60.0, -950.0, 515.0)) + "7": + # sets some day period to 0x17 + cam.set_position( Vector3(0.0, -1120.0, 385.0)) + "8": + # sets some day period to 0x17 + cam.set_position( Vector3(60.0, -230.0, -870.0)) + "9": + # sets some day period to 0x17 + cam.set_position( Vector3(-790.0, 640.0, -20.0)) + "10": + cam.set_position( Vector3(2.0, 490.0, -981.0)) + "11": + # sets some day period to 0x17 + cam.set_position( Vector3(-850.0, -1275.0, -330.0)) + "12": + # sets some day period to 0x17 + cam.set_position( Vector3(600.0, 680.0, -25.0)) + "13": + cam.set_position( Vector3(-840.0, -1274.0, -205.0)) + "14": + cam.set_position( Vector3(-885.0, 685.0, 160.0)) + "15": + cam.set_position( Vector3(0.0, -260.0, -720.0)) diff --git a/icon.svg b/icon.svg new file mode 100644 index 0000000..b370ceb --- /dev/null +++ b/icon.svg @@ -0,0 +1 @@ + diff --git a/login_server/login_screen.cs b/login_server/login_screen.cs new file mode 100644 index 0000000..7d7e9c7 --- /dev/null +++ b/login_server/login_screen.cs @@ -0,0 +1,22 @@ +using Godot; + +namespace EQGodot.login_server; + +public partial class login_screen : Control +{ + [Signal] + public delegate void DoLoginEventHandler(string username, string password); + + private void OnLoginButtonPressed() + { + var username = GetNode("Background/Margins/VBox/UsernameLineEdit").Text; + var password = GetNode("Background/Margins/VBox/PasswordLineEdit").Text; + if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password)) return; + EmitSignal(SignalName.DoLogin, username, password); + } + + public void OnMessageUpdate(string message) + { + GetNode