Berniemack Posted August 2 Posted August 2 (edited) Hey everyone, I may be sharing this project prematurely out of excitement lol. There is not much here yet, and what is here is nothing new or special really. Sharing for feedback and for anyone interested in following my journey down this little adventure. Preface (feel free to skip): About a month or so ago I got an itch to mess around with conquer online this old game I used to love. Just wanted to hop in and look around (not the retail version of course haha) one rabbit hole lead to another and now here I am. I have never worked on a game server before this project. My development velocity has been... slow to say the least but thats because im really trying to take my time and learn as much as I can in this process, and further more try to avoid the dreaded scrapping of the project because of an eventual roadblock caused by a design oversight. As much as I can with my limited knowledge on this topic. Credits: All credits go to whoever's code you recognize, if you see any. A lot of the ideas and implementation here was taken either directly or with a grain of salt from either Comet or Albetros. I claim nothing here, as nothing Ive done so far would be possible for me without the leg work the community has done. Some details on what the project does now this thread will be updated as the project gets updated, I will try my best to have daily commits for anyone interested in following. - Right now the server is implemented up to the point where we respond to the client to the create player packet https://github.com/berniemackie97/OpenConquer 8/23/2025 first update. dont remember the current state just pushed up what I had when I was last working on this a few weeks ago. Will be coming back to this soon, what I'm working on now should make working on the server easier Edited August 23 by Berniemack update Quote
BLACK Posted August 22 Posted August 22 fix erorr using Microsoft.EntityFrameworkCore; using OpenConquer.Domain.Contracts; using OpenConquer.GameServer; using OpenConquer.GameServer.Calculations.Implementation; using OpenConquer.GameServer.Calculations.Interface; using OpenConquer.GameServer.Dispatchers; using OpenConquer.GameServer.Handlers; using OpenConquer.GameServer.Queues; using OpenConquer.GameServer.Session.Managers; using OpenConquer.GameServer.Workers; using OpenConquer.Infrastructure.Mapping; using OpenConquer.Infrastructure.Persistence.Context; using OpenConquer.Infrastructure.POCO; using OpenConquer.Infrastructure.Services; using OpenConquer.Protocol.Packets.Parsers; HostApplicationBuilder builder = Host.CreateApplicationBuilder(args); builder.Configuration.SetBasePath(AppContext.BaseDirectory).AddJsonFile("appsettings.shared.json", optional: false, reloadOnChange: true).AddJsonFile("appsettings.json", optional: true, reloadOnChange: true).AddEnvironmentVariables(); builder.Services.Configure<NetworkSettings>(builder.Configuration.GetSection("Network")); MapsterConfig.RegisterMappings(); builder.Services.AddDbContext<AccountDataContext>(opts => opts.UseNpgsql(builder.Configuration.GetConnectionString("Default"))); builder.Services.AddDbContext<GameDataContext>(opts => opts.UseNpgsql(builder.Configuration.GetConnectionString("Default"))); builder.Services.AddScoped<ExperienceService>(); builder.Services.AddScoped<IExperienceService>(sp => sp.GetRequiredService<ExperienceService>()); builder.Services.AddScoped<UserManager>(); builder.Services.AddScoped<ILevelStatService, LevelStatService>(); builder.Services.AddScoped<IAccountService, AccountService>(); builder.Services.AddScoped<ICharacterService, CharacterService>(); builder.Services.Scan(scan => scan.FromAssemblyOf<IPacketParser>().AddClasses(classes => classes.AssignableTo<IPacketParser>()).AsImplementedInterfaces().WithSingletonLifetime()); builder.Services.Scan(scan => scan.FromAssemblyOf<PacketDispatcher>().AddClasses(classes => classes.AssignableTo(typeof(IPacketHandler<>))).AsImplementedInterfaces().WithTransientLifetime()); builder.Services.AddSingleton<PacketDispatcher>(); builder.Services.AddSingleton<WorldManager>(); builder.Services.AddSingleton<ExperienceService>(); builder.Services.AddSingleton<ConnectionQueue>(); builder.Services.AddSingleton<IExperienceService>(sp => sp.GetRequiredService<ExperienceService>()); builder.Services.AddHostedService(sp => sp.GetRequiredService<ExperienceService>()); builder.Services.AddHostedService<GameHandshakeService>(); builder.Services.AddHostedService<ConnectionWorker>(); IHost host = builder.Build(); host.Run(); Quote
Berniemack Posted August 23 Author Posted August 23 (edited) Its not currently playable, I'd guess the error youre facing is the missing appsettings.shared.json, since you didnt give me the error you got just the program.cs file. Either way, I wouldnt expect much progress on this for a few more months. Life things, plus I've shifted partial focus to trying to deob the client to release along with this if I can, if not hopefully some useful tools or info comes out of it at least. Feel free to dm me if you have specific issues with at least building the project I'll try to help you get set up. Although I do remember there were other errors at some point in time with my with my AddScoped's, I'll update the repo this weekend, here's what I currently have using Microsoft.EntityFrameworkCore; using OpenConquer.Domain.Contracts; using OpenConquer.GameServer; using OpenConquer.GameServer.Calculations.Implementation; using OpenConquer.GameServer.Calculations.Interface; using OpenConquer.GameServer.Dispatchers; using OpenConquer.GameServer.Handlers; using OpenConquer.GameServer.Queues; using OpenConquer.GameServer.Session.Managers; using OpenConquer.GameServer.Workers; using OpenConquer.Infrastructure.Mapping; using OpenConquer.Infrastructure.Persistence.Context; using OpenConquer.Infrastructure.POCO; using OpenConquer.Infrastructure.Services; using OpenConquer.Protocol.Crypto; using OpenConquer.Protocol.Packets.Parsers; using OpenConquer.Protocol.Utilities; HostApplicationBuilder builder = Host.CreateApplicationBuilder(args); builder.Configuration.SetBasePath(AppContext.BaseDirectory).AddJsonFile("appsettings.shared.json", optional: false, reloadOnChange: true).AddJsonFile("appsettings.json", optional: true, reloadOnChange: true).AddEnvironmentVariables(); builder.Services.Configure<NetworkSettings>(builder.Configuration.GetSection("Network")); builder.Services.AddDbContextFactory<DataContext>(opts => opts.UseMySql(builder.Configuration.GetConnectionString("Default"), new MySqlServerVersion(new Version(8, 0, 36)))); MapsterConfig.RegisterMappings(); builder.Services.Scan(scan => scan.FromAssemblyOf<IPacketParser>().AddClasses(c => c.AssignableTo<IPacketParser>()).AsImplementedInterfaces().WithSingletonLifetime()); builder.Services.AddSingleton<PacketParserRegistry>(); builder.Services.Scan(scan => scan.FromAssemblyOf<PacketDispatcher>().AddClasses(c => c.AssignableTo(typeof(IPacketHandler<>))).AsImplementedInterfaces().WithTransientLifetime()); builder.Services.AddScoped<IAccountService, AccountService>(); builder.Services.AddScoped<ICharacterService, CharacterService>(); builder.Services.AddSingleton<ILevelStatService, LevelStatService>(); builder.Services.AddSingleton<UserManager>(); builder.Services.AddSingleton<WorldManager>(); builder.Services.AddSingleton<PacketDispatcher>(); builder.Services.AddSingleton<ExperienceService>(); builder.Services.AddSingleton<IExperienceService>(sp => sp.GetRequiredService<ExperienceService>()); builder.Services.AddHostedService(sp => sp.GetRequiredService<ExperienceService>()); builder.Services.AddSingleton<ConnectionQueue>(); builder.Services.AddHostedService<ConnectionWorker>(); builder.Services.AddHostedService<GameHandshakeService>(); IHost host = builder.Build(); host.Run(); for the appsettings file just make it and put it in your debug folder { "Network": { "LoginPort": 9959, "GamePort": 5816, "ExternalIp": "" }, "ConnectionStrings": { "Default": "Server=localhost;Port=3306;Database=openco;User=root;Password=;" } } Edited August 23 by Berniemack Quote
Omicron Posted August 23 Posted August 23 (edited) Took a quick look and it looks pretty clean, nice work. I do have 2 small feedback points based on the comments here and something I didn’t see. 1. You don’t need a appsettings.shared.json, you can just put them in appsettings.json. If you need to override them, you can do so in another appsettings file. 2. I didn’t see a globals file. If add a globals file in a project, you can add the most commonly used using statements in there. This will help clean up the using statements in all files in that project. Edited August 23 by Omicron Quote
Omicron Posted August 23 Posted August 23 Can’t seem to update my previous post… Got some questions too, I noticed that you used PostgresSql and MySQL. Do you mind elaborating? Another tip to help improve performance: disable data tracking by EF where you don’t need it. https://dotnetbenchmarks.com/benchmark/1079 Quote
Tkblackbelt Posted August 23 Posted August 23 On 8/22/2025 at 6:49 AM, BLACK said: fix erorr using Microsoft.EntityFrameworkCore; using OpenConquer.Domain.Contracts; using OpenConquer.GameServer; using OpenConquer.GameServer.Calculations.Implementation; using OpenConquer.GameServer.Calculations.Interface; using OpenConquer.GameServer.Dispatchers; using OpenConquer.GameServer.Handlers; using OpenConquer.GameServer.Queues; using OpenConquer.GameServer.Session.Managers; using OpenConquer.GameServer.Workers; using OpenConquer.Infrastructure.Mapping; using OpenConquer.Infrastructure.Persistence.Context; using OpenConquer.Infrastructure.POCO; using OpenConquer.Infrastructure.Services; using OpenConquer.Protocol.Packets.Parsers; HostApplicationBuilder builder = Host.CreateApplicationBuilder(args); builder.Configuration.SetBasePath(AppContext.BaseDirectory).AddJsonFile("appsettings.shared.json", optional: false, reloadOnChange: true).AddJsonFile("appsettings.json", optional: true, reloadOnChange: true).AddEnvironmentVariables(); builder.Services.Configure<NetworkSettings>(builder.Configuration.GetSection("Network")); MapsterConfig.RegisterMappings(); builder.Services.AddDbContext<AccountDataContext>(opts => opts.UseNpgsql(builder.Configuration.GetConnectionString("Default"))); builder.Services.AddDbContext<GameDataContext>(opts => opts.UseNpgsql(builder.Configuration.GetConnectionString("Default"))); builder.Services.AddScoped<ExperienceService>(); builder.Services.AddScoped<IExperienceService>(sp => sp.GetRequiredService<ExperienceService>()); builder.Services.AddScoped<UserManager>(); builder.Services.AddScoped<ILevelStatService, LevelStatService>(); builder.Services.AddScoped<IAccountService, AccountService>(); builder.Services.AddScoped<ICharacterService, CharacterService>(); builder.Services.Scan(scan => scan.FromAssemblyOf<IPacketParser>().AddClasses(classes => classes.AssignableTo<IPacketParser>()).AsImplementedInterfaces().WithSingletonLifetime()); builder.Services.Scan(scan => scan.FromAssemblyOf<PacketDispatcher>().AddClasses(classes => classes.AssignableTo(typeof(IPacketHandler<>))).AsImplementedInterfaces().WithTransientLifetime()); builder.Services.AddSingleton<PacketDispatcher>(); builder.Services.AddSingleton<WorldManager>(); builder.Services.AddSingleton<ExperienceService>(); builder.Services.AddSingleton<ConnectionQueue>(); builder.Services.AddSingleton<IExperienceService>(sp => sp.GetRequiredService<ExperienceService>()); builder.Services.AddHostedService(sp => sp.GetRequiredService<ExperienceService>()); builder.Services.AddHostedService<GameHandshakeService>(); builder.Services.AddHostedService<ConnectionWorker>(); IHost host = builder.Build(); host.Run(); Very rude... Just dumping code here and saying to fix the error without even adding the error message /facepalm. ------ On another note, very cool project OP! Love these kinds of projects Quote
Berniemack Posted August 23 Author Posted August 23 (edited) 3 hours ago, Omicron said: Can’t seem to update my previous post… Got some questions too, I noticed that you used PostgresSql and MySQL. Do you mind elaborating? Another tip to help improve performance: disable data tracking by EF where you don’t need it. https://dotnetbenchmarks.com/benchmark/1079 Thanks for the suggestions! Just using MySQL, any PostgresSQL stuff is just uncleaned up code from playing around with ideas. The reason for the appsettings.shared.json is I was toying around with separating some things that I plan on putting in a regular appsettings.json. May not end up doing that at all though so, It may end up just being an appsettings.json in the end. Will definitely look into disabling tracking, and possibly using a globals file, I'll see if I like it for this. Again thank you for taking the time to look at my project and give me some kind feedback! I will be updating the repo at some point today Edited August 23 by Berniemack Quote
Berniemack Posted August 23 Author Posted August 23 6 minutes ago, Tkblackbelt said: Very rude... Just dumping code here and saying to fix the error without even adding the error message /facepalm. ------ On another note, very cool project OP! Love these kinds of projects Thank you! Haven't updated in a bit but I'm still hard at work at this whenever I can get the time to work on it. Will update the thread when I get some time today to update the repo. (Mostly refactoring changes still "stuck" on the dhkey exchange, really I've mostly just so happened to have shifted focus on working on another part of this project). Quote
Spirited Posted August 25 Posted August 25 Good job! I haven't looked through the project too much, but it looks like you're following the hosted services factory pattern? Would be interested to know your thoughts around using it, and if you'd recommend it for C# game server development. I experimented a little with it for Comet's randomization service (BackgroundService using the host service pattern), but never implemented any game systems with it. Best of luck with your development! Quote
Berniemack Posted August 25 Author Posted August 25 2 hours ago, Spirited said: Good job! I haven't looked through the project too much, but it looks like you're following the hosted services factory pattern? Would be interested to know your thoughts around using it, and if you'd recommend it for C# game server development. I experimented a little with it for Comet's randomization service (BackgroundService using the host service pattern), but never implemented any game systems with it. Best of luck with your development! I am indeed leaning into the generic host + BackgroundService pattern but only for LoginHandshakeService, GameHandshakeService, ConnectionWorker and im currently experimenting with an ExperienceService but im not really liking how I have that set up (no real reason other than I feel like there probably is a better way to do what im currently doing with it). Everything else is regular old DI, Parsers and handlers are discovered through assembly scanning. So far I dont have any complaints, I do have to say this is my introduction to game server development as a whole, so I dont know if i can really recommend anything to anyone, other than say so far for me it fits my needs. I really probably should read more into the topic and see more about why things are done a certain way in other game servers. Thank you! Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.