├── _backup
├── README.MD
└── lobbyemu-master.zip
├── runRelease.sh
├── sonar-project.properties
├── FragmentNetslumServer
├── Services
│ ├── Interfaces
│ │ ├── IDatabaseAccessor.cs
│ │ ├── IRankingManagementService.cs
│ │ ├── INewsService.cs
│ │ ├── IBaseService.cs
│ │ ├── IOpCodeHandler.cs
│ │ ├── IBulletinBoardService.cs
│ │ ├── IOpCodeProviderService.cs
│ │ ├── IGuildManagementService.cs
│ │ ├── IMailService.cs
│ │ ├── IClientConnectionService.cs
│ │ ├── IClientProviderService.cs
│ │ └── ILobbyChatService.cs
│ ├── GameClientService.cs
│ └── LobbyChatService.cs
├── Models
│ ├── MessageOfTheDayModel.cs
│ ├── BbsCategoryModel.cs
│ ├── BbsPostBody.cs
│ ├── BbsThreadModel.cs
│ ├── NewsSectionLogModel.cs
│ ├── PlayerAccountIDModel.cs
│ ├── PlayerClass.cs
│ ├── MailBodyModel.cs
│ ├── Mapping
│ │ ├── MessageOfTheDayModel.hbm.xml
│ │ ├── PlayerAccountIDModel.hbm.xml
│ │ ├── BbsCategoryModel.hbm.xml
│ │ ├── NewsSectionLogModel.hbm.xml
│ │ ├── BbsThreadModel.hbm.xml
│ │ ├── BbsPostBody.hbm.xml
│ │ ├── MailBodyModel.hbm.xml
│ │ ├── NewsSectionModel.hbm.xml
│ │ ├── BbsPostMetaModel.hbm.xml
│ │ ├── MailMetaModel.hbm.xml
│ │ ├── RankingDataModel.hbm.xml
│ │ ├── GuildItemShopModel.hbm.xml
│ │ ├── GuildRepositoryModel.hbm.xml
│ │ └── CharacterRepositoryModel.hbm.xml
│ ├── MailMetaModel.cs
│ ├── BbsPostMetaModel.cs
│ ├── GuildItemShopModel.cs
│ ├── GuildRepositoryModel.cs
│ ├── RankingDataModel.cs
│ ├── NewsSectionModel.cs
│ └── CharacterRepositoryModel.cs
├── Entities
│ ├── OpCodeHandlers
│ │ ├── Data
│ │ │ ├── OPCODE_DATA_0X771E.cs
│ │ │ ├── BBS
│ │ │ │ ├── OPCODE_DATA_0x780F.cs
│ │ │ │ ├── OPCODE_DATA_BBS_GET_UPDATES.cs
│ │ │ │ ├── OPCODE_DATA_BBS_POST.cs
│ │ │ │ ├── OPCODE_DATA_BBS_THREAD_GET_CONTENT.cs
│ │ │ │ ├── OPCODE_DATA_BBS_THREAD_GETMENU.cs
│ │ │ │ └── OPCODE_DATA_BBS_GETMENU.cs
│ │ │ ├── OPCODE_DATA_0x787B.cs
│ │ │ ├── OPCODE_DATA_DISKID.cs
│ │ │ ├── OPCODE_DATA_LOGON_REPEAT.cs
│ │ │ ├── OPCODE_DATA_UNREGISTER_CHAR.cs
│ │ │ ├── AreaServer
│ │ │ │ ├── OPCODE_DATA_AS_PUBLISH.cs
│ │ │ │ ├── OPCODE_DATA_LOGON_AS2.cs
│ │ │ │ ├── OPCODE_DATA_AS_DISKID.cs
│ │ │ │ ├── OPCODE_DATA_AS_UPDATE_USERNUM.cs
│ │ │ │ ├── OPCODE_DATA_AS_UPDATE_STATUS.cs
│ │ │ │ ├── OPCODE_DATA_AS_PUBLISH_DETAILS.cs
│ │ │ │ └── OPCODE_DATA_AS_IPPORT.cs
│ │ │ ├── OPCODE_DATA_0x787E.cs
│ │ │ ├── OPCODE_DATA_COM.cs
│ │ │ ├── OPCODE_DATA_SELECT_CHAR.cs
│ │ │ ├── OPCODE_DATA_SELECT2_CHAR.cs
│ │ │ ├── Lobby
│ │ │ │ ├── OPCODE_DATA_LOBBY_GETSERVERS.cs
│ │ │ │ ├── OPCODE_DATA_LOBBY_GETSERVERS_EXIT.cs
│ │ │ │ ├── OPCODE_DATA_LOBBY_CHATROOM_GETLIST.cs
│ │ │ │ ├── OPCODE_DATA_LOBBY_EVENT.cs
│ │ │ │ ├── OPCODE_DATA_LOBBY_STATUS_UPDATE.cs
│ │ │ │ ├── OPCODE_DATA_LOBBY_EXITROOM.cs
│ │ │ │ ├── OPCODE_DATA_LOBBY_GETMENU.cs
│ │ │ │ ├── OPCODE_DATA_LOBBY_ENTERROOM.cs
│ │ │ │ └── OPCODE_DATA_LOBBY_GETSERVERS_GETLIST.cs
│ │ │ ├── OPCODE_DATA_RETURN_DESKTOP.cs
│ │ │ ├── Guild
│ │ │ │ ├── OPCODE_DATA_GUILD_DONATE_COINS.cs
│ │ │ │ ├── OPCODE_DATA_GUILD_DISSOLVED.cs
│ │ │ │ ├── OPCODE_DATA_GUILD_BUY_ITEM.cs
│ │ │ │ ├── OPCODE_DATA_GUILD_GET_DONATION_SETTINGS.cs
│ │ │ │ ├── OPCODE_DATA_GUILD_UPDATE_DETAILS.cs
│ │ │ │ ├── OPCODE_DATA_GUILD_LOGGEDIN_MEMBERS.cs
│ │ │ │ ├── OPCODE_DATA_GUILD_PLAYER_LEAVING.cs
│ │ │ │ ├── OPCODE_DATA_GUILD_CREATE.cs
│ │ │ │ ├── OPCODE_DATA_GUILD_UPDATEITEM_PRICING.cs
│ │ │ │ ├── OPCODE_DATA_GUILD_GET_INFO.cs
│ │ │ │ ├── OPCODE_DATA_GUILD_PLAYER_KICKED.cs
│ │ │ │ ├── OPCODE_DATA_GUILD_VIEW.cs
│ │ │ │ ├── OPCODE_DATA_GUILD_GM_LEAVING.cs
│ │ │ │ ├── OPCODE_DATA_ACCEPT_GUILD_INVITE.cs
│ │ │ │ ├── OPCODE_DATA_GUILD_DONATE_ITEM.cs
│ │ │ │ ├── OPCODE_DATA_GUILD_GETITEMS.cs
│ │ │ │ ├── OPCODE_DATA_GUILD_GETITEMS_TOBUY.cs
│ │ │ │ ├── OPCODE_DATA_GUILD_TAKE_GP.cs
│ │ │ │ ├── OPCODE_DATA_INVITE_TO_GUILD.cs
│ │ │ │ ├── OPCODE_DATA_GUILD_GET_LIST_OF_ITEMS.cs
│ │ │ │ ├── OPCODE_DATA_GUILD_TAKE_ITEM.cs
│ │ │ │ ├── OPCODE_DATA_GUILD_UPDATEITEM_PRICING_AVAILABILITY.cs
│ │ │ │ ├── OPCODE_DATA_GUILD_MEMBERLIST.cs
│ │ │ │ ├── OPCODE_DATA_GUILD_GET_ALL_GUILDS.cs
│ │ │ │ └── OPCODE_DATA_GUILD_GETMENU.cs
│ │ │ ├── Mail
│ │ │ │ ├── OPCODE_DATA_GUILD_MAIL_SEND.cs
│ │ │ │ ├── OPCODE_DATA_MAILCHECK.cs
│ │ │ │ ├── OPCODE_DATA_MAIL_SEND.cs
│ │ │ │ ├── OPCODE_DATA_MAIL_GET_MAIL_BODY.cs
│ │ │ │ └── OPCODE_DATA_MAIL_GET.cs
│ │ │ ├── Ranking
│ │ │ │ ├── OPCODE_RANKING_VIEW_PLAYER.cs
│ │ │ │ └── OPCODE_RANKING_VIEW_ALL.cs
│ │ │ ├── OPCODE_DATA_0x788C.cs
│ │ │ ├── News
│ │ │ │ ├── OPCODE_DATA_NEWCHECK.cs
│ │ │ │ ├── OPCODE_DATA_NEWS_GETPOST.cs
│ │ │ │ └── OPCODE_DATA_NEWS_GETMENU.cs
│ │ │ ├── OPCODE_DATA_LOGON.cs
│ │ │ ├── OPCODE_DATA_SAVEID.cs
│ │ │ ├── OPCODE_DATA_NORESPONSE.cs
│ │ │ └── OPCODE_DATA_REGISTER_CHAR.cs
│ │ ├── Regular
│ │ │ ├── OPCODE_UNKNOWN.cs
│ │ │ ├── OPCODE_KEY_EXCHANGE_ACKNOWLEDGMENT.cs
│ │ │ └── OPCODE_KEY_EXCHANGE_REQUEST.cs
│ │ ├── NoResponseOpCodeHandler.cs
│ │ └── SimpleResponseOpCodeHandler.cs
│ ├── Attributes
│ │ ├── OpCodeAttribute.cs
│ │ └── OpCodeDataAttribute.cs
│ └── RequestContent.cs
├── Enumerations
│ └── ServiceStatusEnum.cs
├── Exceptions
│ └── LobbyEmuCrashException.cs
├── Config.cs
├── Helpers
│ └── IPAddressHelpers.cs
└── FragmentNetslumServer.csproj
├── FragmentNetslumServerPubSub
├── FragmentNetslumServerPubSub.csproj
└── Ioc
│ ├── Interfaces
│ ├── IPubSubPipelineFactory.cs
│ ├── ISubscriber.cs
│ └── IPublisher.cs
│ └── Implementations
│ ├── Publisher.cs
│ ├── PubSubPipelineFactory.cs
│ └── Subscriber.cs
├── FragmentNetslumServerWebApi
├── appsettings.Development.json
├── appsettings.json
├── FragmentNetslumServerWebApi.csproj
├── Program.cs
├── Models
│ ├── ClientsModel.cs
│ ├── AreaServerModel.cs
│ └── PlayerModel.cs
├── Controllers
│ ├── RefreshNewsSection.cs
│ ├── RefreshMOD.cs
│ ├── DebugController.cs
│ └── StatusPageController.cs
├── Properties
│ └── launchSettings.json
└── Startup.cs
├── .travis.yml
├── FragmentNetslumServer.sln.DotSettings
├── .gitattributes
├── .gitignore
├── FragmentNetslumServerLauncher
└── FragmentNetslumServerLauncher.csproj
├── settings.ini.example
├── README.MD
└── FragmentNetslumServer.sln
/_backup/README.MD:
--------------------------------------------------------------------------------
1 | source: https://github.com/Lord-Ptolemy/lobbyemu
2 | date: 10.03.2017
--------------------------------------------------------------------------------
/_backup/lobbyemu-master.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zackmon/FragmentNetslumServer/HEAD/_backup/lobbyemu-master.zip
--------------------------------------------------------------------------------
/runRelease.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | ./FragmentNetslumServerLauncher/bin/Release/net6.0/FragmentNetslumServerLauncher
4 |
--------------------------------------------------------------------------------
/sonar-project.properties:
--------------------------------------------------------------------------------
1 | # must be unique in a given SonarQube instance
2 | sonar.projectKey=Zackmon_FragmentServer_netCore
3 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Services/Interfaces/IDatabaseAccessor.cs:
--------------------------------------------------------------------------------
1 | namespace FragmentNetslumServer.Services.Interfaces
2 | {
3 | class IDatabaseAccessor
4 | {
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/FragmentNetslumServerPubSub/FragmentNetslumServerPubSub.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net6.0
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/FragmentNetslumServerWebApi/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft": "Warning",
6 | "Microsoft.Hosting.Lifetime": "Information"
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Models/MessageOfTheDayModel.cs:
--------------------------------------------------------------------------------
1 | namespace FragmentNetslumServer.Models
2 | {
3 | public class MessageOfTheDayModel
4 | {
5 | public virtual int Id { get; set; }
6 | public virtual string Message { get; set; }
7 | }
8 | }
--------------------------------------------------------------------------------
/FragmentNetslumServer/Models/BbsCategoryModel.cs:
--------------------------------------------------------------------------------
1 | namespace FragmentNetslumServer.Models
2 | {
3 | public class BbsCategoryModel
4 | {
5 | public virtual int categoryID { get; set; }
6 | public virtual string categoryName { get; set; }
7 | }
8 | }
--------------------------------------------------------------------------------
/FragmentNetslumServerWebApi/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft": "Warning",
6 | "Microsoft.Hosting.Lifetime": "Information"
7 | }
8 | },
9 | "AllowedHosts": "*"
10 | }
11 |
--------------------------------------------------------------------------------
/FragmentNetslumServerPubSub/Ioc/Interfaces/IPubSubPipelineFactory.cs:
--------------------------------------------------------------------------------
1 | namespace FragmentNetslumServerPubSub.Ioc.Interfaces
2 | {
3 |
4 | public interface IPubSubPipelineFactory
5 | {
6 | IPublisher GetPublisher();
7 | ISubscriber GetSubscriber();
8 | }
9 |
10 | }
--------------------------------------------------------------------------------
/FragmentNetslumServer/Models/BbsPostBody.cs:
--------------------------------------------------------------------------------
1 | namespace FragmentNetslumServer.Models
2 | {
3 | public class BbsPostBody
4 | {
5 | public virtual int postBodyID {get; set; }
6 | public virtual byte[] postBody { get; set;}
7 | public virtual int postID { get; set;}
8 | }
9 | }
--------------------------------------------------------------------------------
/FragmentNetslumServer/Models/BbsThreadModel.cs:
--------------------------------------------------------------------------------
1 | namespace FragmentNetslumServer.Models
2 | {
3 | public class BbsThreadModel
4 | {
5 | public virtual int threadID { get; set; }
6 | public virtual byte[] threadTitle { get; set; }
7 | public virtual int categoryID { get; set; }
8 | }
9 | }
--------------------------------------------------------------------------------
/FragmentNetslumServer/Models/NewsSectionLogModel.cs:
--------------------------------------------------------------------------------
1 | namespace FragmentNetslumServer.Models
2 | {
3 | public class NewsSectionLogModel
4 | {
5 | public virtual int Id { get; set; }
6 | public virtual string SaveId { get; set; }
7 | public virtual ushort ArticleId { get; set; }
8 | }
9 | }
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: csharp
2 | solution: FragmentNetslumServer.sln
3 | mono: none
4 | dotnet: 6.0.100
5 | script:
6 | - dotnet restore
7 | - dotnet build -c Release
8 | - sonar-scanner
9 | addons:
10 | sonarcloud:
11 | organization: "zackmon" # the key of the org you chose at step #3
12 |
13 |
14 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Models/PlayerAccountIDModel.cs:
--------------------------------------------------------------------------------
1 | namespace FragmentNetslumServer.Models
2 | {
3 | public class PlayerAccountIDModel
4 | {
5 | public virtual int ID { get; set; }
6 | public virtual string saveID { get; set; }
7 |
8 | public PlayerAccountIDModel()
9 | {
10 | ID = -1;
11 | }
12 | }
13 | }
--------------------------------------------------------------------------------
/FragmentNetslumServerWebApi/FragmentNetslumServerWebApi.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net6.0
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Models/PlayerClass.cs:
--------------------------------------------------------------------------------
1 | namespace FragmentNetslumServer.Models
2 | {
3 | // 0 = Twin Blade, 1 = Blademaster, 2 = Heavy Blade, 3 = Heavy Axe, 4 = Long Arm, 5 = Wavemaster
4 | public enum PlayerClass
5 | {
6 | TwinBlade,
7 | BladeMaster,
8 | HeavyBlade,
9 | HeavyAxe,
10 | LongArm,
11 | WaveMaster
12 | }
13 | }
--------------------------------------------------------------------------------
/FragmentNetslumServer/Models/MailBodyModel.cs:
--------------------------------------------------------------------------------
1 | namespace FragmentNetslumServer.Models
2 | {
3 | public class MailBodyModel
4 | {
5 | public virtual int Mail_Body_ID { get; set; }
6 | public virtual int Mail_ID { get; set; }
7 | public virtual byte[] Mail_Body { get; set; }
8 | public virtual string Mail_Face_ID { get; set; }
9 |
10 | }
11 | }
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/OPCODE_DATA_0X771E.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 |
3 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data
4 | {
5 | [OpCodeData(0x771E)]
6 | public sealed class OPCODE_DATA_0X771E : SimpleResponseOpCodeHandler
7 | {
8 | public OPCODE_DATA_0X771E() : base(0x771F, new byte[] { 0x00, 0x00 }) { }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/FragmentNetslumServer.sln.DotSettings:
--------------------------------------------------------------------------------
1 |
2 | True
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/BBS/OPCODE_DATA_0x780F.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 |
3 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.BBS
4 | {
5 | [OpCodeData(0x780F)]
6 | public sealed class OPCODE_DATA_0x780F : SimpleResponseOpCodeHandler
7 | {
8 | public OPCODE_DATA_0x780F() : base(0x7810, new byte[] { 0x01, 0x92 }) { }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Regular/OPCODE_UNKNOWN.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using System.ComponentModel;
3 |
4 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Regular
5 | {
6 | [OpCode(0x0002), DisplayName("Unknown Handler"), Description("Handles an opcode that seemingly has no function")]
7 | public sealed class OPCODE_UNKNOWN : NoResponseOpCodeHandler { }
8 | }
9 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/OPCODE_DATA_0x787B.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 |
3 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data
4 | {
5 | [OpCodeData(0x787B)]
6 | public sealed class OPCODE_DATA_0x787B : SimpleResponseOpCodeHandler
7 | {
8 | public OPCODE_DATA_0x787B() : base(0x787C, new byte[] { 0x00, 0x00 })
9 | {
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Services/Interfaces/IRankingManagementService.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | namespace FragmentNetslumServer.Services.Interfaces
4 | {
5 | public interface IRankingManagementService : IBaseService
6 | {
7 | List GetPlayerRanking(ushort categoryID, ushort classID);
8 | List GetRankingCategory();
9 | byte[] GetRankingPlayerInfo(uint playerID);
10 | }
11 | }
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 |
7 | # Standard to msysgit
8 | *.doc diff=astextplain
9 | *.DOC diff=astextplain
10 | *.docx diff=astextplain
11 | *.DOCX diff=astextplain
12 | *.dot diff=astextplain
13 | *.DOT diff=astextplain
14 | *.pdf diff=astextplain
15 | *.PDF diff=astextplain
16 | *.rtf diff=astextplain
17 | *.RTF diff=astextplain
18 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/OPCODE_DATA_DISKID.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 |
3 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data
4 | {
5 | [OpCodeData(OpCodes.OPCODE_DATA_DISKID)]
6 | public sealed class OPCODE_DATA_DISKID : SimpleResponseOpCodeHandler
7 | {
8 | public OPCODE_DATA_DISKID() : base(OpCodes.OPCODE_DATA_DISKID_OK, new byte[] { 0x36, 0x36, 0x31, 0x36 }) { }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/BBS/OPCODE_DATA_BBS_GET_UPDATES.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 |
3 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.BBS
4 | {
5 | [OpCodeData(OpCodes.OPCODE_DATA_BBS_GET_UPDATES)]
6 | public sealed class OPCODE_DATA_BBS_GET_UPDATES : SimpleResponseOpCodeHandler
7 | {
8 | public OPCODE_DATA_BBS_GET_UPDATES() : base(0x786b, new byte[] { 0x00, 0x00 }) { }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/OPCODE_DATA_LOGON_REPEAT.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 |
3 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data
4 | {
5 | [OpCodeData(OpCodes.OPCODE_DATA_LOGON_REPEAT)]
6 | public sealed class OPCODE_DATA_LOGON_REPEAT : SimpleResponseOpCodeHandler
7 | {
8 | public OPCODE_DATA_LOGON_REPEAT() : base(OpCodes.OPCODE_DATA_LOGON_RESPONSE, new byte[] { 0x02, 0x10 }) { }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/OPCODE_DATA_UNREGISTER_CHAR.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 |
3 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data
4 | {
5 | [OpCodeData(OpCodes.OPCODE_DATA_UNREGISTER_CHAR)]
6 | public sealed class OPCODE_DATA_UNREGISTER_CHAR : SimpleResponseOpCodeHandler
7 | {
8 | public OPCODE_DATA_UNREGISTER_CHAR() : base(OpCodes.OPCODE_DATA_UNREGISTER_CHAROK, new byte[] { 0x00, 0x00 }) { }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/AreaServer/OPCODE_DATA_AS_PUBLISH.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 |
3 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.AreaServer
4 | {
5 | [OpCodeData(OpCodes.OPCODE_DATA_AS_PUBLISH)]
6 | public sealed class OPCODE_DATA_AS_PUBLISH : SimpleResponseOpCodeHandler
7 | {
8 | public OPCODE_DATA_AS_PUBLISH() : base(OpCodes.OPCODE_DATA_AS_PUBLISH_OK, new byte[] { 0x00, 0x00 })
9 | {
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/FragmentNetslumServerPubSub/Ioc/Implementations/Publisher.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServerPubSub.Core;
2 | using FragmentNetslumServerPubSub.Ioc.Interfaces;
3 |
4 | namespace FragmentNetslumServerPubSub.Ioc.Implementations
5 | {
6 |
7 | public class Publisher : IPublisher
8 | {
9 | private readonly Hub hub;
10 |
11 | public Publisher( Hub hub )
12 | {
13 | this.hub = hub;
14 | }
15 |
16 | public void Publish(T data) => hub.Publish(data);
17 | }
18 |
19 | }
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/AreaServer/OPCODE_DATA_LOGON_AS2.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using System.ComponentModel;
3 |
4 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.AreaServer
5 | {
6 | [OpCodeData(OpCodes.OPCODE_DATA_LOGON_AS2), Description("Handles an Area Server login request (I think)")]
7 | public sealed class OPCODE_DATA_LOGON_AS2 : SimpleResponseOpCodeHandler
8 | {
9 | public OPCODE_DATA_LOGON_AS2() : base(0x701C, new byte[] { 0x02, 0x11 }) { }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Models/Mapping/MessageOfTheDayModel.hbm.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Models/Mapping/PlayerAccountIDModel.hbm.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/FragmentNetslumServerPubSub/Ioc/Interfaces/ISubscriber.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace FragmentNetslumServerPubSub.Ioc.Interfaces
4 | {
5 |
6 | public interface ISubscriber
7 | {
8 | bool Exists( object subscriber );
9 | bool Exists( object subscriber, Action handler );
10 | void Subscribe( object subscriber, Action handler );
11 | void Unsubscribe( object subscriber );
12 | void Unsubscribe( object subscriber );
13 | void Unsubscribe( object subscriber, Action handler );
14 | }
15 |
16 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.swp
2 | *.*~
3 | project.lock.json
4 | .DS_Store
5 | *.pyc
6 | nupkg/
7 |
8 | # Visual Studio Code
9 | .vscode
10 |
11 | # Rider
12 | .idea
13 |
14 | # User-specific files
15 | *.suo
16 | *.user
17 | *.userosscache
18 | *.sln.docstates
19 |
20 | # Build results
21 | [Dd]ebug/
22 | [Dd]ebugPublic/
23 | [Rr]elease/
24 | [Rr]eleases/
25 | x64/
26 | x86/
27 | build/
28 | bld/
29 | [Bb]in/
30 | [Oo]bj/
31 | [Oo]ut/
32 | msbuild.log
33 | msbuild.err
34 | msbuild.wrn
35 |
36 | # Visual Studio 2015
37 | .vs/
38 |
39 | /FragmentServerWV/bin/
40 | logs/
41 | settings.ini
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/OPCODE_DATA_0x787E.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services.Interfaces;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Threading.Tasks;
6 |
7 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data
8 | {
9 | [OpCodeData(0x787E)]
10 | public sealed class OPCODE_DATA_0x787E : SimpleResponseOpCodeHandler
11 | {
12 | public OPCODE_DATA_0x787E() : base(0x787F,new byte[] { 0x00, 0x00 })
13 | {
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/FragmentNetslumServerWebApi/Program.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Hosting;
2 | using Microsoft.Extensions.Hosting;
3 |
4 | namespace FragmentNetslumServerWebApi
5 | {
6 | public class Program
7 | {
8 | public static void Main(string[] args)
9 | {
10 | CreateHostBuilder(args).Build().Run();
11 | }
12 |
13 | public static IHostBuilder CreateHostBuilder(string[] args) =>
14 | Host.CreateDefaultBuilder(args)
15 | .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup(); });
16 | }
17 | }
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/AreaServer/OPCODE_DATA_AS_DISKID.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel;
2 | using FragmentNetslumServer.Entities.Attributes;
3 |
4 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.AreaServer
5 | {
6 | [OpCodeData(OpCodes.OPCODE_DATA_AS_DISKID) , Description("Area Server DISK ID Check")]
7 | public sealed class OPCODE_DATA_AS_DISKID : SimpleResponseOpCodeHandler
8 | {
9 | public OPCODE_DATA_AS_DISKID() : base(OpCodes.OPCODE_DATA_AS_DISKID_OK, new byte[] { 0x00, 0x00 })
10 | {
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Models/Mapping/BbsCategoryModel.hbm.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/OPCODE_DATA_COM.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services.Interfaces;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Threading.Tasks;
6 |
7 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data
8 | {
9 | [OpCodeData(OpCodes.OPCODE_DATA_COM)]
10 | public sealed class OPCODE_DATA_COM : SimpleResponseOpCodeHandler
11 | {
12 |
13 | public OPCODE_DATA_COM() : base(OpCodes.OPCODE_DATA_COM_OK, new byte[] { 0xDE, 0xAD })
14 | {
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/FragmentNetslumServerPubSub/Ioc/Implementations/PubSubPipelineFactory.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServerPubSub.Core;
2 | using FragmentNetslumServerPubSub.Ioc.Interfaces;
3 |
4 | namespace FragmentNetslumServerPubSub.Ioc.Implementations
5 | {
6 | public class PubSubPipelineFactory : IPubSubPipelineFactory
7 | {
8 | private readonly Hub hub;
9 |
10 | public PubSubPipelineFactory()
11 | {
12 | hub = new Hub();
13 | }
14 |
15 | public IPublisher GetPublisher() => new Publisher( hub );
16 |
17 | public ISubscriber GetSubscriber() => new Subscriber( hub );
18 | }
19 | }
--------------------------------------------------------------------------------
/FragmentNetslumServer/Models/Mapping/NewsSectionLogModel.hbm.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Models/MailMetaModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace FragmentNetslumServer.Models
4 | {
5 | public class MailMetaModel
6 | {
7 | public virtual int Mail_ID { get; set; }
8 | public virtual int Receiver_Account_ID { get; set; }
9 | public virtual DateTime date {get; set; }
10 | public virtual int Sender_Account_ID { get; set; }
11 | public virtual byte[] Sender_Name {get; set; }
12 | public virtual byte[] Receiver_Name {get; set; }
13 | public virtual byte[] Mail_Subject {get; set; }
14 | public virtual Boolean Mail_Delivered { get; set; }
15 | }
16 | }
--------------------------------------------------------------------------------
/FragmentNetslumServer/Services/Interfaces/INewsService.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Threading.Tasks;
3 | using FragmentNetslumServer.Models;
4 |
5 | namespace FragmentNetslumServer.Services.Interfaces
6 | {
7 | public interface INewsService : IBaseService
8 | {
9 |
10 | Task RefreshNewsList();
11 | Task> GetNewsArticles();
12 |
13 | Task> GetNewsArticles(string saveID);
14 |
15 | Task CheckIfNewNewsForSaveId(string saveId);
16 |
17 | Task UpdateNewsLog(string saveId, ushort articleId);
18 |
19 | }
20 | }
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/OPCODE_DATA_SELECT_CHAR.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services.Interfaces;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Threading.Tasks;
6 |
7 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data
8 | {
9 | [OpCodeData(OpCodes.OPCODE_DATA_SELECT_CHAR)]
10 | public sealed class OPCODE_DATA_SELECT_CHAR : SimpleResponseOpCodeHandler
11 | {
12 | public OPCODE_DATA_SELECT_CHAR() : base(OpCodes.OPCODE_DATA_SELECT_CHAROK, new byte[] { 0x00, 0x00 })
13 | {
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Models/BbsPostMetaModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace FragmentNetslumServer.Models
4 | {
5 | public class BbsPostMetaModel
6 | {
7 | public virtual int unk0 { get; set; }
8 | public virtual int postID {get; set; }
9 | public virtual int unk2 {get; set; }
10 | public virtual DateTime date {get; set; }
11 | public virtual byte[] username {get; set; }
12 | public virtual byte[] subtitle {get; set; }
13 | public virtual byte[] title {get; set; }
14 | public virtual string unk3 {get; set; }
15 | public virtual int threadID {get; set; }
16 |
17 | }
18 | }
--------------------------------------------------------------------------------
/FragmentNetslumServer/Models/Mapping/BbsThreadModel.hbm.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Models/Mapping/BbsPostBody.hbm.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/OPCODE_DATA_SELECT2_CHAR.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services.Interfaces;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Threading.Tasks;
6 |
7 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data
8 | {
9 | [OpCodeData(OpCodes.OPCODE_DATA_SELECT2_CHAR)]
10 | public sealed class OPCODE_DATA_SELECT2_CHAR : SimpleResponseOpCodeHandler
11 | {
12 | public OPCODE_DATA_SELECT2_CHAR() : base(OpCodes.OPCODE_DATA_SELECT2_CHAROK, new byte[] { 0x30, 0x30, 0x30, 0x30 })
13 | {
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Services/Interfaces/IBaseService.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Enumerations;
2 |
3 | namespace FragmentNetslumServer.Services.Interfaces
4 | {
5 |
6 | ///
7 | /// Defines basic information that all services should be able to provide
8 | ///
9 | public interface IBaseService
10 | {
11 |
12 | ///
13 | /// Gets a friendly display name of the service
14 | ///
15 | string ServiceName { get; }
16 |
17 | ///
18 | /// Gets the current status of the service
19 | ///
20 | ServiceStatusEnum ServiceStatus { get; }
21 |
22 | }
23 |
24 | }
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/Lobby/OPCODE_DATA_LOBBY_GETSERVERS.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services.Interfaces;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.Lobby
9 | {
10 | [OpCodeData(OpCodes.OPCODE_DATA_LOBBY_GETSERVERS)]
11 | public sealed class OPCODE_DATA_LOBBY_GETSERVERS : SimpleResponseOpCodeHandler
12 | {
13 | public OPCODE_DATA_LOBBY_GETSERVERS() : base(OpCodes.OPCODE_DATA_LOBBY_GETSERVERS_OK, new byte[] { 0x00, 0x00 })
14 | {
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/FragmentNetslumServerWebApi/Models/ClientsModel.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | namespace FragmentNetslumServerWebApi.Models
4 | {
5 | public class ClientsModel
6 | {
7 | public List _playerList = new List();
8 | public List _areaServerList = new List();
9 |
10 |
11 | public List PlayerList
12 | {
13 | get => _playerList;
14 | set => _playerList = value;
15 | }
16 |
17 | public List AreaServerList
18 | {
19 | get => _areaServerList;
20 | set => _areaServerList = value;
21 | }
22 | }
23 | }
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/NoResponseOpCodeHandler.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Services.Interfaces;
2 | using System.Collections.Generic;
3 | using System.Threading.Tasks;
4 |
5 | namespace FragmentNetslumServer.Entities.OpCodeHandlers
6 | {
7 | ///
8 | /// A base class that does not have an actual response to the client
9 | ///
10 | public abstract class NoResponseOpCodeHandler : IOpCodeHandler
11 | {
12 | public virtual Task> HandleIncomingRequestAsync(RequestContent request)
13 | => Task.FromResult>(new[] { ResponseContent.Empty });
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/Lobby/OPCODE_DATA_LOBBY_GETSERVERS_EXIT.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services.Interfaces;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.Lobby
9 | {
10 | [OpCodeData(OpCodes.OPCODE_DATA_LOBBY_GETSERVERS_EXIT)]
11 | public sealed class OPCODE_DATA_LOBBY_GETSERVERS_EXIT : SimpleResponseOpCodeHandler
12 | {
13 | public OPCODE_DATA_LOBBY_GETSERVERS_EXIT() : base(OpCodes.OPCODE_DATA_LOBBY_GETSERVERS_EXIT_OK, new byte[] { 0x00, 0x00 })
14 | {
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Models/Mapping/MailBodyModel.hbm.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/FragmentNetslumServerLauncher/FragmentNetslumServerLauncher.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net6.0
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Enumerations/ServiceStatusEnum.cs:
--------------------------------------------------------------------------------
1 | namespace FragmentNetslumServer.Enumerations
2 | {
3 |
4 | ///
5 | /// Defines the various states of execution that a service can be in
6 | ///
7 | public enum ServiceStatusEnum
8 | {
9 | ///
10 | /// The service is currently inactive awaiting activation
11 | ///
12 | Inactive,
13 |
14 | ///
15 | /// The service is currently active and running properly
16 | ///
17 | Active,
18 |
19 | ///
20 | /// The service has experienced an error of some sort and needs to be addressed
21 | ///
22 | Faulted
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Models/GuildItemShopModel.cs:
--------------------------------------------------------------------------------
1 | namespace FragmentNetslumServer.Models
2 | {
3 | public class GuildItemShopModel
4 | {
5 | public virtual int ItemShopID { get; set; }
6 |
7 |
8 | public virtual int GuildID { get; set; }
9 |
10 |
11 | public virtual int ItemID { get; set; }
12 |
13 |
14 | public virtual int Quantity { get; set; }
15 |
16 |
17 | public virtual int GeneralPrice { get; set; }
18 |
19 |
20 | public virtual int MemberPrice { get; set; }
21 |
22 |
23 | public virtual bool AvailableForGeneral { get; set; }
24 |
25 |
26 | public virtual bool AvailableForMember { get; set; }
27 |
28 | public GuildItemShopModel()
29 | {
30 | ItemShopID = -1;
31 | }
32 | }
33 | }
--------------------------------------------------------------------------------
/FragmentNetslumServer/Models/Mapping/NewsSectionModel.hbm.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Models/GuildRepositoryModel.cs:
--------------------------------------------------------------------------------
1 | namespace FragmentNetslumServer.Models
2 | {
3 | public class GuildRepositoryModel
4 | {
5 | public virtual int GuildID { get; set; }
6 |
7 |
8 | public virtual byte[] GuildName { get; set; }
9 |
10 |
11 | public virtual byte[] GuildEmblem { get; set; }
12 |
13 |
14 | public virtual byte[] GuildComment { get; set; }
15 |
16 |
17 | public virtual string EstablishmentDate { get; set; }
18 |
19 |
20 | public virtual int MasterPlayerID { get; set; }
21 |
22 |
23 | public virtual int GoldCoin { get; set; }
24 |
25 |
26 | public virtual int SilverCoin { get; set; }
27 |
28 |
29 | public virtual int BronzeCoin { get; set; }
30 |
31 |
32 | public virtual int Gp { get; set; }
33 | }
34 | }
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/Attributes/OpCodeAttribute.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace FragmentNetslumServer.Entities.Attributes
4 | {
5 | ///
6 | /// Defines a non-data based OpCode
7 | ///
8 | [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
9 | public class OpCodeAttribute : Attribute
10 | {
11 |
12 | ///
13 | /// Gets the OpCode this attribute is meant to represent
14 | ///
15 | public ushort OpCode { get; private set; }
16 |
17 | ///
18 | /// Creates a new instance of
19 | ///
20 | /// The OpCode to use for mapping
21 | public OpCodeAttribute(ushort opcode) => OpCode = opcode;
22 |
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Regular/OPCODE_KEY_EXCHANGE_ACKNOWLEDGMENT.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using System.Collections.Generic;
3 | using System.Threading.Tasks;
4 |
5 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Regular
6 | {
7 | [OpCode(OpCodes.OPCODE_KEY_EXCHANGE_ACKNOWLEDGMENT)]
8 | public sealed class OPCODE_KEY_EXCHANGE_ACKNOWLEDGMENT : NoResponseOpCodeHandler
9 | {
10 | public override Task> HandleIncomingRequestAsync(RequestContent request)
11 | {
12 | request.Client.InitializeDecryptionKey(request.Client.from_key, true);
13 | request.Client.InitializeEncryptionKey(request.Client.to_key, true);
14 | return base.HandleIncomingRequestAsync(request);
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/FragmentNetslumServerPubSub/Ioc/Interfaces/IPublisher.cs:
--------------------------------------------------------------------------------
1 | namespace FragmentNetslumServerPubSub.Ioc.Interfaces
2 | {
3 |
4 | ///
5 | /// One part of the pub-sub model. Provides a meaningful definition for a publisher to notify
6 | /// subscribers that an event or action has occurred that they should be interested in
7 | ///
8 | public interface IPublisher
9 | {
10 |
11 | ///
12 | /// Publishes an object instance to all listeners.
13 | ///
14 | ///
15 | ///
16 | ///
17 | /// If is a reference type, ALL subscribers (listeners) will receive the SAME instance
18 | ///
19 | void Publish(T data);
20 |
21 | }
22 |
23 | }
--------------------------------------------------------------------------------
/FragmentNetslumServer/Services/Interfaces/IOpCodeHandler.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities;
2 | using System.Collections.Generic;
3 | using System.Threading.Tasks;
4 |
5 | namespace FragmentNetslumServer.Services.Interfaces
6 | {
7 |
8 | ///
9 | /// Defines a lightweight interface who is responsible for handling incoming packet requests
10 | ///
11 | public interface IOpCodeHandler
12 | {
13 |
14 | ///
15 | /// Handles the incoming instance
16 | ///
17 | /// The incoming
18 | /// A promise to handle the packet asynchronously
19 | Task> HandleIncomingRequestAsync(RequestContent request);
20 |
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/OPCODE_DATA_RETURN_DESKTOP.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services;
3 | using System.Collections.Generic;
4 | using System.Threading.Tasks;
5 |
6 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data
7 | {
8 | [OpCodeData(OpCodes.OPCODE_DATA_RETURN_DESKTOP)]
9 | public sealed class OPCODE_DATA_RETURN_DESKTOP : SimpleResponseOpCodeHandler
10 | {
11 | public OPCODE_DATA_RETURN_DESKTOP() : base(OpCodes.OPCODE_DATA_RETURN_DESKTOP_OK, new byte[] { 0x00, 0x00 }) { }
12 | public override Task> HandleIncomingRequestAsync(RequestContent request)
13 | {
14 | DBAccess.getInstance().setPlayerAsOffline(request.Client._characterPlayerID);
15 | return base.HandleIncomingRequestAsync(request);
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/FragmentNetslumServerWebApi/Controllers/RefreshNewsSection.cs:
--------------------------------------------------------------------------------
1 | using System.Threading.Tasks;
2 | using FragmentNetslumServer.Services;
3 | using FragmentNetslumServer.Services.Interfaces;
4 | using Microsoft.AspNetCore.Mvc;
5 | using Microsoft.Extensions.Logging;
6 |
7 | namespace FragmentNetslumServerWebApi.Controllers;
8 |
9 | [ApiController]
10 | [Route("refreshNews")]
11 | public class RefreshNewsSection
12 | {
13 | private readonly ILogger _logger;
14 | private readonly INewsService _newsService;
15 |
16 | public RefreshNewsSection(ILogger logger , INewsService newsService)
17 | {
18 | _logger = logger;
19 | _newsService = newsService;
20 | }
21 |
22 | [HttpGet]
23 | public async Task Get()
24 | {
25 | await _newsService.RefreshNewsList();
26 |
27 |
28 | return "News Section Refreshed";
29 | }
30 | }
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/Attributes/OpCodeDataAttribute.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace FragmentNetslumServer.Entities.Attributes
4 | {
5 |
6 | ///
7 | /// Defines an OpCode that is explicitly intended for usage with the data OpCode (0x30)
8 | ///
9 | [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
10 | public sealed class OpCodeDataAttribute : OpCodeAttribute
11 | {
12 |
13 | ///
14 | /// Gets the data-based OpCode
15 | ///
16 | public ushort DataOpCode { get; private set; }
17 |
18 | ///
19 | /// Creates a new instance of
20 | ///
21 | /// The OpCode to use for mapping
22 | public OpCodeDataAttribute(ushort dataOpCode) : base(OpCodes.OPCODE_DATA) => DataOpCode = dataOpCode;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/FragmentNetslumServerWebApi/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://json.schemastore.org/launchsettings.json",
3 | "iisSettings": {
4 | "windowsAuthentication": false,
5 | "anonymousAuthentication": false,
6 | "iisExpress": {
7 | "applicationUrl": "http://localhost:36501",
8 | "sslPort": 44394
9 | }
10 | },
11 | "profiles": {
12 | "IIS Express": {
13 | "commandName": "IISExpress",
14 | "launchBrowser": true,
15 | "launchUrl": "status",
16 | "environmentVariables": {
17 | "ASPNETCORE_ENVIRONMENT": "Development"
18 | }
19 | },
20 | "FragmentServerWV_WebApi": {
21 | "commandName": "Project",
22 | "launchBrowser": true,
23 | "launchUrl": "status",
24 | "applicationUrl": "http://localhost:5001",
25 | "environmentVariables": {
26 | "ASPNETCORE_ENVIRONMENT": "Development"
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/AreaServer/OPCODE_DATA_AS_UPDATE_USERNUM.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.ComponentModel;
5 | using System.Threading.Tasks;
6 | using static FragmentNetslumServer.Services.Extensions;
7 |
8 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.AreaServer
9 | {
10 | [OpCodeData(OpCodes.OPCODE_DATA_AS_UPDATE_USERNUM), Description("Updates how many players are currently on an Area Server")]
11 | public sealed class OPCODE_DATA_AS_UPDATE_USERNUM : NoResponseOpCodeHandler
12 | {
13 | public override Task> HandleIncomingRequestAsync(RequestContent request)
14 | {
15 | request.Client.as_usernum = swap16(BitConverter.ToUInt16(request.Data, 2));
16 | return base.HandleIncomingRequestAsync(request);
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/FragmentNetslumServerWebApi/Controllers/RefreshMOD.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Services;
2 | using Microsoft.AspNetCore.Mvc;
3 | using Microsoft.Extensions.Logging;
4 |
5 | namespace FragmentNetslumServerWebApi.Controllers
6 | {
7 | [ApiController]
8 | [Route("motd")]
9 | public class RefreshMod : ControllerBase
10 | {
11 | private readonly ILogger _logger;
12 |
13 | public RefreshMod(ILogger logger)
14 | {
15 | _logger = logger;
16 | }
17 |
18 | [HttpGet]
19 | public string Get()
20 | {
21 | DBAccess.getInstance().RefreshMessageOfTheDay();
22 |
23 |
24 | return "Message Of the Day Refreshed";
25 | }
26 |
27 | [HttpPut]
28 | public IActionResult Put(string motd)
29 | {
30 | DBAccess.getInstance().SetMessageOfDay(motd);
31 | return Ok();
32 | }
33 |
34 | }
35 | }
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/BBS/OPCODE_DATA_BBS_POST.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Threading.Tasks;
6 | using static FragmentNetslumServer.Services.Extensions;
7 |
8 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.BBS
9 | {
10 | [OpCodeData(OpCodes.OPCODE_DATA_BBS_POST)]
11 | public sealed class OPCODE_DATA_BBS_POST : SimpleResponseOpCodeHandler
12 | {
13 | public OPCODE_DATA_BBS_POST() : base(0x7813, new byte[] { 0x00, 0x00 }) { }
14 |
15 | public override Task> HandleIncomingRequestAsync(RequestContent request)
16 | {
17 | var id = swap32(BitConverter.ToUInt32(request.Data, 0));
18 | DBAccess.getInstance().CreateNewPost(request.Data, id);
19 | return base.HandleIncomingRequestAsync(request);
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/Lobby/OPCODE_DATA_LOBBY_CHATROOM_GETLIST.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services.Interfaces;
3 | using System.Collections.Generic;
4 | using System.Threading.Tasks;
5 |
6 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.Lobby
7 | {
8 | [OpCodeData(OpCodes.OPCODE_DATA_LOBBY_CHATROOM_GETLIST)]
9 | public sealed class OPCODE_DATA_LOBBY_CHATROOM_GETLIST : IOpCodeHandler
10 | {
11 | public Task> HandleIncomingRequestAsync(RequestContent request) =>
12 | Task.FromResult>(new[]
13 | {
14 | request.CreateResponse(OpCodes.OPCODE_DATA_LOBBY_CHATROOM_CATEGORY, new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }),
15 | request.CreateResponse(OpCodes.OPCODE_DATA_LOBBY_CHATROOM_CATEGORY, new byte[] { 0x00, 0x01, 0x00, 0x00 })
16 | });
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Services/Interfaces/IBulletinBoardService.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Threading.Tasks;
3 | using FragmentNetslumServer.Models;
4 |
5 | namespace FragmentNetslumServer.Services.Interfaces
6 | {
7 | public interface IBulletinBoardService: IBaseService
8 | {
9 |
10 | Task> GetCategoriesAsync();
11 |
12 | Task> GetThreadsAsync(int categoryId);
13 |
14 | Task> GetThreadDetailsAsync(int threadId);
15 |
16 | Task GetThreadPostContentAsync(int postId);
17 |
18 |
19 |
20 | Task ConvertCategoryToBytesAsync(BbsCategoryModel categoryModel);
21 |
22 | Task ConvertThreadToBytesAsync(BbsThreadModel threadModel);
23 |
24 | Task ConvertThreadDetailsToBytesAsync(BbsPostMetaModel postMetaModel);
25 |
26 | Task ConvertThreadPostToBytesAsync(BbsPostBody postBody);
27 |
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Models/RankingDataModel.cs:
--------------------------------------------------------------------------------
1 | namespace FragmentNetslumServer.Models
2 | {
3 | public class RankingDataModel
4 | {
5 | public virtual int id { get; set; }
6 | public virtual string antiCheatEngineResult {get; set; }
7 | public virtual string loginTime {get; set; }
8 | public virtual string diskID {get; set; }
9 | public virtual string saveID {get; set; }
10 | public virtual string characterSaveID {get; set; }
11 | public virtual string characterName {get; set; }
12 | public virtual int characterLevel {get; set; }
13 | public virtual string characterClassName {get; set; }
14 | public virtual int characterHP {get; set; }
15 | public virtual int characterSP {get; set; }
16 | public virtual int characterGP {get; set; }
17 | public virtual int godStatusCounterOnline {get; set; }
18 | public virtual int averageFieldLevel {get; set; }
19 | public virtual int accountID { get; set; }
20 |
21 | }
22 | }
--------------------------------------------------------------------------------
/settings.ini.example:
--------------------------------------------------------------------------------
1 | # Server Connection
2 | # 0.0.0.0 binds to any available interface
3 | ip = 0.0.0.0
4 | port = 49000
5 |
6 | # Database Connection
7 | dbhost = 127.0.0.1
8 | dbport = 3306
9 | dbname = fragment_schema
10 | dbuser = root
11 | dbpass = root
12 |
13 | # "is alive"-ping delay in ms
14 | # The lower this is, the more active the server is.
15 | # However, the lower this is, the faster a client
16 | # that has disconnected will be removed from the
17 | # server
18 | ping = 5000
19 |
20 | # Log settings
21 | # Setup the sinks in a CSV related variable
22 | # Valid entries are: console,file
23 | sinks = console,file
24 | folder = logs/
25 | logsize = 100000
26 | # Possible options: Verbose, Debug, Information,
27 | # Warning, Error, Fatal
28 | # This value is case sensitive
29 | lobbyloglevel = Information
30 | apiloglevel = Warning
31 |
32 | # Tick rate, in milliseconds. This is
33 | # how often the server checks for client data
34 | # Recommended Value: 30; any higher will cause
35 | # delays in responding to the client
36 | tick = 30
--------------------------------------------------------------------------------
/FragmentNetslumServer/Models/Mapping/BbsPostMetaModel.hbm.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Models/Mapping/MailMetaModel.hbm.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/FragmentNetslumServerWebApi/Controllers/DebugController.cs:
--------------------------------------------------------------------------------
1 | using System.Threading.Tasks;
2 | using FragmentNetslumServer.Services.Interfaces;
3 | using Microsoft.AspNetCore.Mvc;
4 | using Microsoft.Extensions.Logging;
5 |
6 | namespace FragmentNetslumServerWebApi.Controllers
7 | {
8 |
9 | [ApiController]
10 | [Route("debug")]
11 | public class DebugController : ControllerBase
12 | {
13 | private readonly ILogger logger;
14 | private readonly ILobbyChatService lobbyChatService;
15 |
16 | public DebugController(
17 | ILogger logger,
18 | ILobbyChatService lobbyChatService)
19 | {
20 | this.logger = logger;
21 | this.lobbyChatService = lobbyChatService;
22 | }
23 |
24 |
25 | [HttpGet]
26 | public async Task Get()
27 | {
28 | // foreach(var lobby in lobbyChatService.)
29 | await lobbyChatService.Main.SendServerMessageAsync("This is a test message from a WebAPI controller");
30 | return Ok();
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/Guild/OPCODE_DATA_GUILD_DONATE_COINS.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services.Interfaces;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Threading.Tasks;
6 |
7 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.Guild
8 | {
9 | [OpCodeData(OpCodes.OPCODE_DATA_GUILD_DONATE_COINS)]
10 | public sealed class OPCODE_DATA_GUILD_DONATE_COINS : IOpCodeHandler
11 | {
12 | private readonly IGuildManagementService _guildManagementService;
13 |
14 | public OPCODE_DATA_GUILD_DONATE_COINS(IGuildManagementService guildManagementService)
15 | {
16 | _guildManagementService = guildManagementService;
17 | }
18 |
19 | public Task> HandleIncomingRequestAsync(RequestContent request)
20 | {
21 | return Task.FromResult>(new[]
22 | { request.CreateResponse(0x7701, _guildManagementService.DonateCoinsToGuild(request.Data)) });
23 | }
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/FragmentNetslumServerPubSub/Ioc/Implementations/Subscriber.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using FragmentNetslumServerPubSub.Core;
3 | using FragmentNetslumServerPubSub.Ioc.Interfaces;
4 |
5 | namespace FragmentNetslumServerPubSub.Ioc.Implementations
6 | {
7 |
8 | public class Subscriber : ISubscriber
9 | {
10 | private readonly Hub hub;
11 |
12 | public Subscriber( Hub hub )
13 | {
14 | this.hub = hub;
15 | }
16 |
17 | public bool Exists( object subscriber ) => hub.Exists( subscriber );
18 |
19 | public bool Exists( object subscriber, Action handler ) => hub.Exists( subscriber, handler );
20 |
21 | public void Subscribe( object subscriber, Action handler ) => hub.Subscribe( subscriber, handler );
22 |
23 | public void Unsubscribe( object subscriber ) => hub.Unsubscribe( subscriber );
24 |
25 | public void Unsubscribe( object subscriber ) => hub.Unsubscribe( subscriber, (Action) null );
26 |
27 | public void Unsubscribe( object subscriber, Action handler ) => hub.Unsubscribe( subscriber, handler );
28 | }
29 |
30 | }
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/Mail/OPCODE_DATA_GUILD_MAIL_SEND.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Threading.Tasks;
5 | using FragmentNetslumServer.Entities.Attributes;
6 | using FragmentNetslumServer.Services.Interfaces;
7 |
8 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.Mail;
9 |
10 | [OpCodeData(OpCodes.OPCODE_DATA_GUILD_MAIL_SEND), Description("Send a mail to all the guild members")]
11 | public sealed class OPCODE_DATA_GUILD_MAIL_SEND : SimpleResponseOpCodeHandler
12 | {
13 | private readonly IMailService mailService;
14 |
15 | public OPCODE_DATA_GUILD_MAIL_SEND(IMailService mailService) : base(OpCodes.OPCODE_DATA_GUILD_MAIL_SEND_OK, new byte[] { 0x00, 0x00 })
16 | {
17 | this.mailService = mailService ?? throw new ArgumentNullException(nameof(mailService));
18 | }
19 | public override async Task> HandleIncomingRequestAsync(RequestContent request)
20 | {
21 | await mailService.SaveGuildMailAsync(request.Data);
22 | return await base.HandleIncomingRequestAsync(request);
23 | }
24 | }
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/Guild/OPCODE_DATA_GUILD_DISSOLVED.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services.Interfaces;
3 | using System.Collections.Generic;
4 | using System.Threading.Tasks;
5 |
6 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.Guild
7 | {
8 | [OpCodeData(OpCodes.OPCODE_DATA_GUILD_DISSOLVED)]
9 | public sealed class OPCODE_DATA_GUILD_DISSOLVED : IOpCodeHandler
10 | {
11 | private readonly IGuildManagementService guildManagementService;
12 |
13 | public OPCODE_DATA_GUILD_DISSOLVED(IGuildManagementService guildManagementService)
14 | {
15 | this.guildManagementService = guildManagementService;
16 | }
17 |
18 | public Task> HandleIncomingRequestAsync(RequestContent request)
19 | {
20 | var responses = new List
21 | {
22 | request.CreateResponse(0x761A, guildManagementService.DestroyGuild(request.Client._guildID))
23 | };
24 | return Task.FromResult>(responses);
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/Lobby/OPCODE_DATA_LOBBY_EVENT.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services.Interfaces;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.Lobby
9 | {
10 | [OpCodeData(OpCodes.OPCODE_DATA_LOBBY_EVENT)]
11 | public sealed class OPCODE_DATA_LOBBY_EVENT : NoResponseOpCodeHandler
12 | {
13 | private readonly ILobbyChatService _lobbyChatService;
14 |
15 | public OPCODE_DATA_LOBBY_EVENT(ILobbyChatService lobbyChatService)
16 | {
17 | _lobbyChatService = lobbyChatService;
18 | }
19 |
20 | public override async Task> HandleIncomingRequestAsync(RequestContent request)
21 | {
22 | if (_lobbyChatService.TryFindLobby(request.Client, out var lcr))
23 | {
24 | await lcr.SendPublicMessageAsync(request.Data, request.Client.ClientIndex);
25 | }
26 | return await base.HandleIncomingRequestAsync(request);
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/Guild/OPCODE_DATA_GUILD_BUY_ITEM.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services;
3 | using FragmentNetslumServer.Services.Interfaces;
4 | using System.Collections.Generic;
5 | using System.Threading.Tasks;
6 |
7 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.Guild
8 | {
9 | [OpCodeData(OpCodes.OPCODE_DATA_GUILD_BUY_ITEM)]
10 | public sealed class OPCODE_DATA_GUILD_BUY_ITEM : IOpCodeHandler
11 | {
12 | private readonly IGuildManagementService guildManagementService;
13 |
14 | public OPCODE_DATA_GUILD_BUY_ITEM(IGuildManagementService guildManagementService)
15 | {
16 | this.guildManagementService = guildManagementService;
17 | }
18 |
19 | public Task> HandleIncomingRequestAsync(RequestContent request)
20 | {
21 | var responses = new List
22 | {
23 | request.CreateResponse(0x770D, guildManagementService.BuyItemFromGuild(request.Data))
24 | };
25 | return Task.FromResult>(responses);
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/Guild/OPCODE_DATA_GUILD_GET_DONATION_SETTINGS.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services.Interfaces;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Threading.Tasks;
6 |
7 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.Guild
8 | {
9 | [OpCodeData(OpCodes.OPCODE_DATA_GUILD_GET_DONATION_SETTINGS)]
10 | public sealed class OPCODE_DATA_GUILD_GET_DONATION_SETTINGS : IOpCodeHandler
11 | {
12 | private readonly IGuildManagementService _guildManagementService;
13 |
14 | public OPCODE_DATA_GUILD_GET_DONATION_SETTINGS(IGuildManagementService guildManagementService)
15 | {
16 | _guildManagementService = guildManagementService;
17 | }
18 |
19 | public Task> HandleIncomingRequestAsync(RequestContent request)
20 | {
21 | return Task.FromResult>(new[]
22 | {
23 | request.CreateResponse(0x787a,
24 | _guildManagementService.GetItemDonationSettings(request.Client.isGuildMaster))
25 | });
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/Guild/OPCODE_DATA_GUILD_UPDATE_DETAILS.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services.Interfaces;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Threading.Tasks;
6 |
7 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.Guild
8 | {
9 | [OpCodeData(OpCodes.OPCODE_DATA_GUILD_UPDATE_DETAILS)]
10 | public sealed class OPCODE_DATA_GUILD_UPDATE_DETAILS : IOpCodeHandler
11 | {
12 | private readonly IGuildManagementService _guildManagementService;
13 |
14 | public OPCODE_DATA_GUILD_UPDATE_DETAILS(IGuildManagementService guildManagementService)
15 | {
16 | _guildManagementService = guildManagementService;
17 |
18 | }
19 |
20 | public Task> HandleIncomingRequestAsync(RequestContent request)
21 | {
22 | return Task.FromResult>(new[]
23 | {
24 | request.CreateResponse(0x761D,
25 | _guildManagementService.UpdateGuildEmblemComment(request.Data,request.Client._guildID))
26 | });
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/Guild/OPCODE_DATA_GUILD_LOGGEDIN_MEMBERS.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services.Interfaces;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Threading.Tasks;
6 | using static FragmentNetslumServer.Services.Extensions;
7 |
8 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.Guild
9 | {
10 | [OpCodeData(OpCodes.OPCODE_DATA_GUILD_LOGGEDIN_MEMBERS)]
11 | public sealed class OPCODE_DATA_GUILD_LOGGEDIN_MEMBERS : IOpCodeHandler
12 | {
13 | private readonly IGuildManagementService guildManagementService;
14 |
15 | public OPCODE_DATA_GUILD_LOGGEDIN_MEMBERS(IGuildManagementService guildManagementService)
16 | {
17 | this.guildManagementService = guildManagementService;
18 | }
19 |
20 | public Task> HandleIncomingRequestAsync(RequestContent request)
21 | {
22 | var guildId = swap16(BitConverter.ToUInt16(request.Data, 0));
23 | return Task.FromResult>(new[] { request.CreateResponse(0x789d, guildManagementService.GetGuildInfo(guildId)) });
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/Guild/OPCODE_DATA_GUILD_PLAYER_LEAVING.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services.Interfaces;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.Guild
9 | {
10 | [OpCodeData(OpCodes.OPCODE_DATA_GUILD_PLAYER_LEAVING)]
11 | public sealed class OPCODE_DATA_GUILD_PLAYER_LEAVING : IOpCodeHandler
12 | {
13 |
14 | private readonly IGuildManagementService _guildManagementService;
15 |
16 | public OPCODE_DATA_GUILD_PLAYER_LEAVING(IGuildManagementService guildManagementService)
17 | {
18 | _guildManagementService = guildManagementService;
19 | }
20 |
21 | public Task> HandleIncomingRequestAsync(RequestContent request)
22 | {
23 | return Task.FromResult>(new[]
24 | {
25 | request.CreateResponse(0x7617,
26 | _guildManagementService.LeaveGuild(request.Client._guildID, request.Client._characterPlayerID))
27 | });
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Models/NewsSectionModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace FragmentNetslumServer.Models
4 | {
5 | public class NewsSectionModel
6 | {
7 | public virtual ushort ArticleID { get; set; }
8 | public virtual string ArticleTitle { get; set; }
9 | public virtual string ArticleBody { get; set; }
10 | public virtual DateTime ArticleDate { get; set; }
11 | public virtual byte[] ArticleImage { get; set; }
12 |
13 | public virtual byte[] ArticleByteArray { get; set; }
14 | public virtual byte[] ImageSizeInfo { get; set; }
15 | public virtual byte[] ImageDetails { get; set; }
16 |
17 | public virtual NewsSectionModel Clone()
18 | {
19 | NewsSectionModel clone = new NewsSectionModel
20 | {
21 | ArticleID = this.ArticleID,
22 | ArticleTitle = this.ArticleTitle,
23 | ArticleBody = this.ArticleBody,
24 | ArticleDate = this.ArticleDate,
25 | ArticleImage = this.ArticleImage,
26 | ArticleByteArray = this.ArticleByteArray,
27 | ImageSizeInfo = this.ImageSizeInfo
28 | };
29 |
30 | return clone;
31 | }
32 | }
33 | }
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/Ranking/OPCODE_RANKING_VIEW_PLAYER.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Threading.Tasks;
4 | using FragmentNetslumServer.Entities.Attributes;
5 | using FragmentNetslumServer.Services;
6 | using FragmentNetslumServer.Services.Interfaces;
7 |
8 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.Ranking
9 | {
10 | [OpCodeData(OpCodes.OPCODE_RANKING_VIEW_PLAYER)]
11 | public sealed class OPCODE_RANKING_VIEW_PLAYER : IOpCodeHandler
12 | {
13 | private readonly IRankingManagementService _rankingManagementService;
14 |
15 | public OPCODE_RANKING_VIEW_PLAYER(IRankingManagementService rankingManagementService)
16 | {
17 | _rankingManagementService = rankingManagementService;
18 | }
19 |
20 | public Task> HandleIncomingRequestAsync(RequestContent request)
21 | {
22 | uint rankPlayerID = BitConverter.ToUInt32(request.Data, 0).Swap();
23 | ResponseContent response = request.CreateResponse(0x7839, _rankingManagementService.GetRankingPlayerInfo(rankPlayerID));
24 |
25 | return Task.FromResult>(new [] {response});
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/SimpleResponseOpCodeHandler.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Services.Interfaces;
2 | using System.Collections.Generic;
3 | using System.Threading.Tasks;
4 |
5 | namespace FragmentNetslumServer.Entities.OpCodeHandlers
6 | {
7 | ///
8 | /// A base class that supports a single response of a predictable result to the client
9 | ///
10 | ///
11 | /// This is only useful when the response is deterministic. Thankfully, there are several OPCODES where the response is indeed deterministic
12 | ///
13 | public abstract class SimpleResponseOpCodeHandler : IOpCodeHandler
14 | {
15 | private readonly ushort responseOpCode;
16 | private readonly byte[] responseData;
17 |
18 | public SimpleResponseOpCodeHandler(ushort responseOpCode, byte[] responseData)
19 | {
20 | this.responseOpCode = responseOpCode;
21 | this.responseData = responseData;
22 | }
23 |
24 | public virtual Task> HandleIncomingRequestAsync(RequestContent request) =>
25 | Task.FromResult>(new[] { request.CreateResponse(responseOpCode, responseData) });
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/Guild/OPCODE_DATA_GUILD_CREATE.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services.Interfaces;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Threading.Tasks;
6 | using static FragmentNetslumServer.Services.Extensions;
7 |
8 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.Guild
9 | {
10 | [OpCodeData(OpCodes.OPCODE_DATA_GUILD_CREATE)]
11 | public sealed class OPCODE_DATA_GUILD_CREATE : IOpCodeHandler
12 | {
13 | private readonly IGuildManagementService guildManagementService;
14 |
15 | public OPCODE_DATA_GUILD_CREATE(IGuildManagementService guildManagementService)
16 | {
17 | this.guildManagementService = guildManagementService;
18 | }
19 |
20 | public Task> HandleIncomingRequestAsync(RequestContent request)
21 | {
22 | var u = guildManagementService.CreateGuild(request.Data, request.Client._characterPlayerID);
23 | request.Client._guildID = u;
24 | request.Client.isGuildMaster = true;
25 | return Task.FromResult>(new[] { request.CreateResponse(0x7601, BitConverter.GetBytes(swap16(u))) });
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/Guild/OPCODE_DATA_GUILD_UPDATEITEM_PRICING.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services.Interfaces;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using FragmentNetslumServer.Services;
8 | using Serilog;
9 |
10 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.Guild
11 | {
12 | [OpCodeData(OpCodes.OPCODE_DATA_GUILD_UPDATEITEM_PRICING)]
13 | public sealed class OPCODE_DATA_GUILD_UPDATEITEM_PRICING : IOpCodeHandler
14 | {
15 |
16 | private readonly IGuildManagementService _guildManagementService;
17 |
18 | public OPCODE_DATA_GUILD_UPDATEITEM_PRICING(IGuildManagementService guildManagementService)
19 | {
20 | _guildManagementService = guildManagementService;
21 |
22 | }
23 |
24 | public Task> HandleIncomingRequestAsync(RequestContent request)
25 | {
26 | return Task.FromResult>(new[]
27 | {
28 | request.CreateResponse(0x7713,
29 | _guildManagementService.SetItemVisibilityAndPrice(request.Data))
30 | });
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/OPCODE_DATA_0x788C.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services.Interfaces;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.ComponentModel;
6 | using System.Threading.Tasks;
7 | using FragmentNetslumServer.Services;
8 |
9 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data
10 | {
11 | [OpCodeData(0x788C) , Description("Send a Direct message in the lobby ")]
12 | public sealed class OPCODE_DATA_0x788C : NoResponseOpCodeHandler
13 | {
14 | private readonly ILobbyChatService _lobbyChatService;
15 | public OPCODE_DATA_0x788C(ILobbyChatService lobbyChatService)
16 | {
17 | _lobbyChatService = lobbyChatService;
18 | }
19 |
20 | public override async Task> HandleIncomingRequestAsync(RequestContent request)
21 | {
22 | var destid = BitConverter.ToUInt16(request.Data, 2).Swap();
23 | if (_lobbyChatService.TryFindLobby(request.Client, out var p))
24 | {
25 | await p.SendDirectMessageAsync(request.Data, request.Client.ClientIndex, destid);
26 | }
27 |
28 | return await base.HandleIncomingRequestAsync(request);
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/Guild/OPCODE_DATA_GUILD_GET_INFO.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services.Interfaces;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Threading.Tasks;
6 | using static FragmentNetslumServer.Services.Extensions;
7 |
8 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.Guild
9 | {
10 | [OpCodeData(OpCodes.OPCODE_DATA_GUILD_GET_INFO)]
11 | public sealed class OPCODE_DATA_GUILD_GET_INFO : IOpCodeHandler
12 | {
13 | private readonly IGuildManagementService guildManagementService;
14 |
15 | public OPCODE_DATA_GUILD_GET_INFO(IGuildManagementService guildManagementService)
16 | {
17 | this.guildManagementService = guildManagementService;
18 | }
19 |
20 | public Task> HandleIncomingRequestAsync(RequestContent request)
21 | {
22 | var guildId = swap16(BitConverter.ToUInt16(request.Data, 0));
23 | return Task.FromResult>(
24 | new[]
25 | {
26 | request.CreateResponse(OpCodes.OPCODE_DATA_GET_GUILD_INFO_RESPONSE, guildManagementService.GetGuildInfo(guildId))
27 | });
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/Mail/OPCODE_DATA_MAILCHECK.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services.Interfaces;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Threading.Tasks;
6 | using FragmentNetslumServer.Services;
7 |
8 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.Mail
9 | {
10 | [OpCodeData(OpCodes.OPCODE_DATA_MAILCHECK)]
11 | public sealed class OPCODE_DATA_MAILCHECK : IOpCodeHandler
12 | {
13 | public async Task> HandleIncomingRequestAsync(RequestContent request)
14 | {
15 | bool isNew = await Task.Run(() =>
16 | DBAccess.getInstance().checkForNewMailByAccountID(Extensions.ReadAccountId(request.Data, 0)));
17 | ResponseContent responseContent;
18 | if (isNew)
19 | {
20 | responseContent = request.CreateResponse(OpCodes.OPCODE_DATA_MAILCHECK_OK,
21 | new byte[] { 0x00, 0x00, 0x01, 0x00 });
22 | }
23 | else
24 | {
25 | responseContent = request.CreateResponse(OpCodes.OPCODE_DATA_MAILCHECK_OK, new byte[] { 0x00, 0x01 });
26 | }
27 |
28 | return new[] { responseContent };
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/Lobby/OPCODE_DATA_LOBBY_STATUS_UPDATE.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services.Interfaces;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.ComponentModel;
6 | using System.Threading.Tasks;
7 |
8 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.Lobby
9 | {
10 | [OpCodeData(OpCodes.OPCODE_DATA_LOBBY_STATUS_UPDATE), Description("Propagates updates from a Client to the entire Lobby")]
11 | public sealed class OPCODE_DATA_LOBBY_STATUS_UPDATE : NoResponseOpCodeHandler
12 | {
13 | private readonly ILobbyChatService lobbyChatService;
14 |
15 | public OPCODE_DATA_LOBBY_STATUS_UPDATE(ILobbyChatService lobbyChatService)
16 | {
17 | this.lobbyChatService = lobbyChatService ?? throw new ArgumentNullException(nameof(lobbyChatService));
18 | }
19 |
20 | public override async Task> HandleIncomingRequestAsync(RequestContent request)
21 | {
22 | if (lobbyChatService.TryFindLobby(request.Client, out var rm))
23 | {
24 | await rm.UpdateLobbyStatusAsync(request.Data, request.Client.ClientIndex);
25 | }
26 | return await base.HandleIncomingRequestAsync(request);
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Models/CharacterRepositoryModel.cs:
--------------------------------------------------------------------------------
1 | namespace FragmentNetslumServer.Models
2 | {
3 | public class CharacterRepositoryModel
4 | {
5 | public virtual int PlayerID { get; set; }
6 | public virtual byte[] CharacterName { get; set; }
7 | public virtual int ClassID { get; set; }
8 | public virtual int CharacterLevel { get; set; }
9 | public virtual byte[] Greeting { get; set; }
10 | public virtual int GuildID { get; set; }
11 | public virtual int GuildMaster { get; set; }
12 | public virtual int ModelNumber { get; set; }
13 | public virtual bool OnlineStatus { get; set; }
14 | public virtual int accountID { get; set; }
15 | public virtual string characterSaveID { get; set; }
16 |
17 | public virtual int charHP { get; set; }
18 | public virtual int charSP { get; set; }
19 | public virtual int charGP { get; set; }
20 | public virtual int charOnlineGoat { get; set; }
21 | public virtual int charOfflineGoat { get; set; }
22 | public virtual int charGoldCoin { get; set; }
23 | public virtual int charSilverCoin { get; set; }
24 | public virtual int charBronzeCoin { get; set; }
25 |
26 | public CharacterRepositoryModel()
27 | {
28 | PlayerID = -1;
29 | }
30 | }
31 | }
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/Guild/OPCODE_DATA_GUILD_PLAYER_KICKED.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services.Interfaces;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using FragmentNetslumServer.Services;
8 |
9 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.Guild
10 | {
11 | [OpCodeData(OpCodes.OPCODE_DATA_GUILD_PLAYER_KICKED)]
12 | public sealed class OPCODE_DATA_GUILD_PLAYER_KICKED : IOpCodeHandler
13 | {
14 |
15 | private readonly IGuildManagementService _guildManagementService;
16 |
17 | public OPCODE_DATA_GUILD_PLAYER_KICKED(IGuildManagementService guildManagementService)
18 | {
19 | _guildManagementService = guildManagementService;
20 | }
21 | public Task> HandleIncomingRequestAsync(RequestContent request)
22 | {
23 | uint playerToKick = BitConverter.ToUInt32(request.Data, 0).Swap();
24 |
25 | return Task.FromResult>(new[]
26 | {
27 | request.CreateResponse(0x7865,
28 | _guildManagementService.KickPlayerFromGuild(request.Client._guildID, playerToKick))
29 | });
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/Guild/OPCODE_DATA_GUILD_VIEW.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services.Interfaces;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using FragmentNetslumServer.Services;
8 |
9 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.Guild
10 | {
11 | [OpCodeData(OpCodes.OPCODE_DATA_GUILD_VIEW)]
12 | public sealed class OPCODE_DATA_GUILD_VIEW : IOpCodeHandler
13 | {
14 |
15 | private readonly IGuildManagementService _guildManagementService;
16 |
17 | public OPCODE_DATA_GUILD_VIEW(IGuildManagementService guildManagementService)
18 | {
19 | _guildManagementService = guildManagementService;
20 |
21 | }
22 |
23 | public Task> HandleIncomingRequestAsync(RequestContent request)
24 | {
25 | var u = BitConverter.ToUInt16(request.Data, 0).Swap();
26 | request.Client.currentGuildInvitaionSelection = u;
27 | return Task.FromResult>(new[]
28 | {
29 | request.CreateResponse(0x772D,
30 | _guildManagementService.GetGuildInfo(u))
31 | });
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/FragmentNetslumServerWebApi/Startup.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Builder;
2 | using Microsoft.AspNetCore.Hosting;
3 | using Microsoft.Extensions.Configuration;
4 | using Microsoft.Extensions.DependencyInjection;
5 | using Microsoft.Extensions.Hosting;
6 |
7 | namespace FragmentNetslumServerWebApi
8 | {
9 | public class Startup
10 | {
11 | public Startup(IConfiguration configuration)
12 | {
13 | Configuration = configuration;
14 | }
15 |
16 | public IConfiguration Configuration { get; }
17 |
18 | // This method gets called by the runtime. Use this method to add services to the container.
19 | public void ConfigureServices(IServiceCollection services)
20 | {
21 | services.AddControllers();
22 | }
23 |
24 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
25 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
26 | {
27 | if (env.IsDevelopment())
28 | {
29 | app.UseDeveloperExceptionPage();
30 | }
31 |
32 | //app.UseHttpsRedirection();
33 |
34 | app.UseRouting();
35 |
36 | //app.UseAuthorization();
37 |
38 | app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
39 | }
40 | }
41 | }
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/AreaServer/OPCODE_DATA_AS_UPDATE_STATUS.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Threading.Tasks;
4 | using FragmentNetslumServer.Entities.Attributes;
5 | using static FragmentNetslumServer.Services.Extensions;
6 |
7 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.AreaServer
8 | {
9 | [OpCodeData(OpCodes.OPCODE_DATA_AS_UPDATE_STATUS)]
10 | public sealed class OPCODE_DATA_AS_UPDATE_STATUS : NoResponseOpCodeHandler
11 | {
12 | public override Task> HandleIncomingRequestAsync(RequestContent request)
13 | {
14 | request.Client.publish_data_2 = request.Data;
15 | ExtractAreaServerData(request);
16 | return base.HandleIncomingRequestAsync(request);
17 | }
18 |
19 | private void ExtractAreaServerData(RequestContent request)
20 | {
21 | var data = request.Data;
22 | var client = request.Client;
23 | int pos = 67; // isn't this interesting
24 | client.areaServerName = ReadByteString(data, pos);
25 | pos += client.areaServerName.Length;
26 | client.areaServerLevel = swap16(BitConverter.ToUInt16(data, pos));
27 | pos += 4;
28 | client.areaServerStatus = data[pos++];
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/Guild/OPCODE_DATA_GUILD_GM_LEAVING.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services.Interfaces;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using FragmentNetslumServer.Services;
8 |
9 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.Guild
10 | {
11 | [OpCodeData(OpCodes.OPCODE_DATA_GUILD_GM_LEAVING)]
12 | public sealed class OPCODE_DATA_GUILD_GM_LEAVING : IOpCodeHandler
13 | {
14 |
15 | private readonly IGuildManagementService _guildManagementService;
16 |
17 | public OPCODE_DATA_GUILD_GM_LEAVING(IGuildManagementService guildManagementService)
18 | {
19 | _guildManagementService = guildManagementService;
20 | }
21 | public Task> HandleIncomingRequestAsync(RequestContent request)
22 | {
23 | uint assigningPlayerID = BitConverter.ToUInt32(request.Data, 0).Swap();
24 |
25 | return Task.FromResult>(new[]
26 | {
27 | request.CreateResponse(0x788E,
28 | _guildManagementService.LeaveGuildAndAssignMaster(request.Client._guildID, assigningPlayerID))
29 | });
30 |
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/Mail/OPCODE_DATA_MAIL_SEND.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services.Interfaces;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.ComponentModel;
6 | using System.Threading.Tasks;
7 |
8 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.Mail
9 | {
10 |
11 | [OpCodeData(OpCodes.OPCODE_DATA_MAIL_SEND), Description("Sends mail from one player to another")]
12 | public sealed class OPCODE_DATA_MAIL_SEND : SimpleResponseOpCodeHandler
13 | {
14 | private readonly IMailService mailService;
15 |
16 | public OPCODE_DATA_MAIL_SEND(IMailService mailService) : base(OpCodes.OPCODE_DATA_MAIL_SEND_OK, new byte[] { 0x00, 0x00 })
17 | {
18 | this.mailService = mailService ?? throw new ArgumentNullException(nameof(mailService));
19 | }
20 |
21 | public override async Task> HandleIncomingRequestAsync(RequestContent request)
22 | {
23 | // Do I need to do this still???
24 | //var buffer = new byte[4096];
25 | //while (ns.DataAvailable) await ns.ReadAsync(buffer, 0, buffer.Length);
26 | await mailService.SaveMailAsync(request.Data);
27 | return await base.HandleIncomingRequestAsync(request);
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/Lobby/OPCODE_DATA_LOBBY_EXITROOM.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services.Interfaces;
3 | using System.Collections.Generic;
4 | using System.ComponentModel;
5 | using System.Threading.Tasks;
6 |
7 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.Lobby
8 | {
9 | [OpCodeData(OpCodes.OPCODE_DATA_LOBBY_EXITROOM), Description("Announces to the client's current Lobby that it is leaving")]
10 | public sealed class OPCODE_DATA_LOBBY_EXITROOM : SimpleResponseOpCodeHandler
11 | {
12 | private readonly ILobbyChatService lobbyChatService;
13 |
14 | public OPCODE_DATA_LOBBY_EXITROOM(ILobbyChatService lobbyChatService) : base(OpCodes.OPCODE_DATA_LOBBY_EXITROOM_OK, new byte[] { 0x00, 0x00 })
15 | {
16 | this.lobbyChatService = lobbyChatService ?? throw new System.ArgumentNullException(nameof(lobbyChatService));
17 | }
18 |
19 | public override async Task> HandleIncomingRequestAsync(RequestContent request)
20 | {
21 | if (lobbyChatService.TryFindLobby(request.Client, out var lobby))
22 | {
23 | await lobbyChatService.AnnounceRoomDeparture(lobby, (uint)request.Client.ClientIndex);
24 | }
25 | return await base.HandleIncomingRequestAsync(request);
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/Mail/OPCODE_DATA_MAIL_GET_MAIL_BODY.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services.Interfaces;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.ComponentModel;
6 | using System.Threading.Tasks;
7 | using static FragmentNetslumServer.Services.Extensions;
8 |
9 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.Mail
10 | {
11 | [OpCodeData(OpCodes.OPCODE_DATA_MAIL_GET_MAIL_BODY), Description("Returns the full message body for the specified mail")]
12 | public sealed class OPCODE_DATA_MAIL_GET_MAIL_BODY : IOpCodeHandler
13 | {
14 | private readonly IMailService mailService;
15 |
16 | public OPCODE_DATA_MAIL_GET_MAIL_BODY(IMailService mailService)
17 | {
18 | this.mailService = mailService ?? throw new ArgumentNullException(nameof(mailService));
19 | }
20 |
21 | public async Task> HandleIncomingRequestAsync(RequestContent request)
22 | {
23 | var mailId = (int)swap32(BitConverter.ToUInt32(request.Data, 4));
24 | var messageBodyModel = await mailService.GetMailContent(mailId);
25 | var messageBody = await mailService.ConvertMailBodyIntoBytes(messageBodyModel);
26 | return new[] { request.CreateResponse(OpCodes.OPCODE_DATA_MAIL_GET_MAIL_BODY_RESPONSE, messageBody) };
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/Guild/OPCODE_DATA_ACCEPT_GUILD_INVITE.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services;
3 | using FragmentNetslumServer.Services.Interfaces;
4 | using System.Collections.Generic;
5 | using System.IO;
6 | using System.Threading.Tasks;
7 |
8 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.Guild
9 | {
10 | [OpCodeData(OpCodes.OPCODE_DATA_ACCEPT_GUILD_INVITE)]
11 | public sealed class OPCODE_DATA_ACCEPT_GUILD_INVITE : IOpCodeHandler
12 | {
13 | public async Task> HandleIncomingRequestAsync(RequestContent request)
14 | {
15 | var responses = new List();
16 | var ms = new MemoryStream();
17 | await ms.WriteAsync(new byte[] { 0x76, 0x0B});
18 |
19 | if (request.Data[1] == 0x08) //accepted the invitation
20 | {
21 | DBAccess.getInstance().EnrollPlayerInGuild(request.Client.currentGuildInvitaionSelection, request.Client._characterPlayerID, false);
22 | responses.Add(request.CreateResponse(0x760A, ms.ToArray())); // send guild ID
23 | }
24 | else
25 | {
26 | // rejected
27 | responses.Add(request.CreateResponse(0x760A, ms.ToArray())); // send guild ID
28 | }
29 | return responses;
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/Guild/OPCODE_DATA_GUILD_DONATE_ITEM.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services.Interfaces;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using FragmentNetslumServer.Services;
8 |
9 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.Guild
10 | {
11 | [OpCodeData(OpCodes.OPCODE_DATA_GUILD_DONATE_ITEM)]
12 | public sealed class OPCODE_DATA_GUILD_DONATE_ITEM : IOpCodeHandler
13 | {
14 | private readonly IGuildManagementService _guildManagementService;
15 |
16 | public OPCODE_DATA_GUILD_DONATE_ITEM(IGuildManagementService guildManagementService)
17 | {
18 | _guildManagementService = guildManagementService;
19 | }
20 |
21 | public Task> HandleIncomingRequestAsync(RequestContent request)
22 | {
23 | request.Client._itemDontationID = BitConverter.ToUInt32(request.Data, 2).Swap();
24 | request.Client._itemDonationQuantity = BitConverter.ToUInt16(request.Data, 6).Swap();
25 |
26 | return Task.FromResult>(new [] {request.CreateResponse(0x7704,
27 | _guildManagementService.GetPriceOfItemToBeDonated(request.Client._guildID,
28 | request.Client._itemDontationID))});
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/BBS/OPCODE_DATA_BBS_THREAD_GET_CONTENT.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services.Interfaces;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Threading.Tasks;
6 | using static FragmentNetslumServer.Services.Extensions;
7 |
8 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.BBS
9 | {
10 | [OpCodeData(OpCodes.OPCODE_DATA_BBS_THREAD_GET_CONTENT)]
11 | public sealed class OPCODE_DATA_BBS_THREAD_GET_CONTENT : IOpCodeHandler
12 | {
13 | private readonly IBulletinBoardService bulletinBoardService;
14 |
15 | public OPCODE_DATA_BBS_THREAD_GET_CONTENT(IBulletinBoardService bulletinBoardService)
16 | {
17 | this.bulletinBoardService = bulletinBoardService ?? throw new ArgumentNullException(nameof(bulletinBoardService));
18 | }
19 |
20 | public async Task> HandleIncomingRequestAsync(RequestContent request)
21 | {
22 | var responses = new List();
23 | var q = swap32(BitConverter.ToUInt32(request.Data, 4));
24 | var postID = Convert.ToInt32(q);
25 | var bbsPostBody = await bulletinBoardService.GetThreadPostContentAsync(postID);
26 | var bbsPostData = await bulletinBoardService.ConvertThreadPostToBytesAsync(bbsPostBody);
27 | responses.Add(request.CreateResponse(0x781d, bbsPostData));
28 | return responses;
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Services/Interfaces/IOpCodeProviderService.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Threading.Tasks;
5 |
6 | namespace FragmentNetslumServer.Services.Interfaces
7 | {
8 |
9 | ///
10 | /// A service provider that's responsible for the discovery and management of the various instances
11 | ///
12 | public interface IOpCodeProviderService : IBaseService
13 | {
14 |
15 | ///
16 | /// Gets a collection of s but as their defined type
17 | ///
18 | IReadOnlyCollection Handlers { get; }
19 |
20 | ///
21 | /// Handles processing the incoming
22 | ///
23 | /// The that submitted the request
24 | /// The to handle
25 | Task> HandlePacketAsync(GameClientAsync gameClient, PacketAsync packet);
26 |
27 | ///
28 | /// Determines whether or not can currently handle this
29 | ///
30 | ///
31 | /// True if possible
32 | bool CanHandleRequest(PacketAsync packet);
33 |
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/News/OPCODE_DATA_NEWCHECK.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.ComponentModel;
3 | using System.Text;
4 | using System.Threading.Tasks;
5 | using FragmentNetslumServer.Entities.Attributes;
6 | using FragmentNetslumServer.Services.Interfaces;
7 |
8 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.News
9 | {
10 | [OpCodeData(OpCodes.OPCODE_DATA_NEWCHECK) , Description("Check if there's new Articles to read")]
11 | public sealed class OPCODE_DATA_NEWCHECK : IOpCodeHandler
12 | {
13 | private readonly INewsService _newsService;
14 | private readonly Encoding _encoding;
15 | public OPCODE_DATA_NEWCHECK(INewsService newsService)
16 | {
17 | _newsService = newsService;
18 | Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
19 | _encoding = Encoding.GetEncoding("Shift-JIS");
20 | }
21 |
22 | public async Task> HandleIncomingRequestAsync(RequestContent request)
23 | {
24 | bool isNew = await _newsService.CheckIfNewNewsForSaveId(_encoding.GetString(request.Client.save_id));
25 |
26 | if (isNew)
27 | {
28 | return new[] { request.CreateResponse(OpCodes.OPCODE_DATA_NEWCHECK_OK, new byte[] { 0x00, 0x01 }) }; // send the new flag
29 | }
30 | else
31 | {
32 | return new[] { request.CreateResponse(OpCodes.OPCODE_DATA_NEWCHECK_OK, new byte[] { 0x00, 0x00 }) }; // there are no new articles to read
33 | }
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Models/Mapping/RankingDataModel.hbm.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/OPCODE_DATA_LOGON.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services.Interfaces;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Threading.Tasks;
6 | using Serilog;
7 |
8 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data
9 | {
10 | [OpCodeData(OpCodes.OPCODE_DATA_LOGON)]
11 | public sealed class OPCODE_DATA_LOGON : IOpCodeHandler
12 | {
13 | private readonly ILogger _logger;
14 | public OPCODE_DATA_LOGON(ILogger logger)
15 | {
16 | _logger = logger;
17 | }
18 |
19 | public Task> HandleIncomingRequestAsync(RequestContent request)
20 | {
21 |
22 | if (request.Data[1] == OpCodes.OPCODE_DATA_SERVERKEY_CHANGE)
23 | {
24 | _logger.Information("Client #{@clientIndex} has identified itself as an Area Server", request.Client.ClientIndex);
25 | request.Client.isAreaServer = true;
26 | return Task.FromResult>(new[] { request.CreateResponse(OpCodes.OPCODE_DATA_AREASERVER_OK, new byte[] { 0xDE, 0xAD }) });
27 |
28 | }
29 | else
30 | {
31 | _logger.Information("Client #{@clientIndex} has identified itself as a Game Client (PS2 / PCSX2)", request.Client.ClientIndex);
32 | return Task.FromResult>(new[] { request.CreateResponse(OpCodes.OPCODE_DATA_LOGON_RESPONSE, new byte[] { 0x74, 0x32 }) });
33 | }
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Models/Mapping/GuildItemShopModel.hbm.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/Guild/OPCODE_DATA_GUILD_GETITEMS.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services.Interfaces;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using FragmentNetslumServer.Services;
8 |
9 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.Guild
10 | {
11 | [OpCodeData(OpCodes.OPCODE_DATA_GUILD_GETITEMS)]
12 | public sealed class OPCODE_DATA_GUILD_GETITEMS : IOpCodeHandler
13 | {
14 | private readonly IGuildManagementService _guildManagementService;
15 |
16 | public OPCODE_DATA_GUILD_GETITEMS(IGuildManagementService guildManagementService)
17 | {
18 | _guildManagementService = guildManagementService;
19 | }
20 |
21 | public Task> HandleIncomingRequestAsync(RequestContent request)
22 | {
23 | List responseContents = new List();
24 |
25 | var u = BitConverter.ToUInt16(request.Data, 0).Swap();
26 |
27 | List allGuildItems = _guildManagementService.GetAllGuildItemsWithSettings(u);
28 |
29 | responseContents.Add(request.CreateResponse(0x7729,
30 | BitConverter.GetBytes(((ushort)allGuildItems.Count).Swap()))); // number of items
31 |
32 | foreach (var item in allGuildItems)
33 | {
34 | responseContents.Add(request.CreateResponse(0x772A, item));
35 | }
36 |
37 | return Task.FromResult>(responseContents);
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/Guild/OPCODE_DATA_GUILD_GETITEMS_TOBUY.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services.Interfaces;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Threading.Tasks;
6 | using FragmentNetslumServer.Services;
7 |
8 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.Guild
9 | {
10 | [OpCodeData(OpCodes.OPCODE_DATA_GUILD_GETITEMS_TOBUY)]
11 | public sealed class OPCODE_DATA_GUILD_GETITEMS_TOBUY : IOpCodeHandler
12 | {
13 |
14 | private readonly IGuildManagementService _guildManagementService;
15 |
16 | public OPCODE_DATA_GUILD_GETITEMS_TOBUY(IGuildManagementService guildManagementService)
17 | {
18 | _guildManagementService = guildManagementService;
19 | }
20 |
21 | public Task> HandleIncomingRequestAsync(RequestContent request)
22 | {
23 | List responseContents = new List();
24 |
25 | var u = BitConverter.ToUInt16(request.Data, 0).Swap();
26 | List membersItemList = _guildManagementService.GetGuildItems(u, false);
27 |
28 | responseContents.Add(request.CreateResponse(0x7709,
29 | BitConverter.GetBytes(((ushort)membersItemList.Count).Swap()))); // number of items
30 |
31 | foreach (var item in membersItemList)
32 | {
33 | responseContents.Add(request.CreateResponse(0x770a, item));
34 | }
35 |
36 | return Task.FromResult>(responseContents);
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/Guild/OPCODE_DATA_GUILD_TAKE_GP.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services.Interfaces;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using FragmentNetslumServer.Services;
8 | using Serilog;
9 |
10 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.Guild
11 | {
12 | [OpCodeData(OpCodes.OPCODE_DATA_GUILD_TAKE_GP)]
13 | public sealed class OPCODE_DATA_GUILD_TAKE_GP : IOpCodeHandler
14 | {
15 | private readonly ILogger _logger;
16 | private readonly IGuildManagementService _guildManagementService;
17 |
18 | public OPCODE_DATA_GUILD_TAKE_GP(ILogger logger,IGuildManagementService guildManagementService)
19 | {
20 | _logger = logger;
21 | _guildManagementService = guildManagementService;
22 |
23 | }
24 |
25 | public Task> HandleIncomingRequestAsync(RequestContent request)
26 | {
27 | ushort guildIDTakeMoney = BitConverter.ToUInt16(request.Data, 0).Swap();
28 | uint amountOfMoneyToTakeOut = BitConverter.ToUInt32(request.Data, 2).Swap();
29 |
30 | _logger.Debug("Guild ID {guildIDTakeMoney} \nAmount of money to Take out {amountOfMoneyToTakeOut}",guildIDTakeMoney,amountOfMoneyToTakeOut);
31 | return Task.FromResult>(new[]
32 | {
33 | request.CreateResponse(0x770F,
34 | _guildManagementService.TakeMoneyFromGuild(guildIDTakeMoney, amountOfMoneyToTakeOut))
35 | });
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/OPCODE_DATA_SAVEID.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services;
3 | using FragmentNetslumServer.Services.Interfaces;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.ComponentModel;
7 | using System.IO;
8 | using System.Text;
9 | using System.Threading.Tasks;
10 | using static FragmentNetslumServer.Services.Extensions;
11 |
12 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data
13 | {
14 | [OpCodeData(OpCodes.OPCODE_DATA_SAVEID), Description("Associates a GameClient with an Account ID and loads out the MOTD")]
15 | public sealed class OPCODE_DATA_SAVEID : IOpCodeHandler
16 | {
17 | public async Task> HandleIncomingRequestAsync(RequestContent request)
18 | {
19 | var encoding = Encoding.GetEncoding("Shift-JIS");
20 | MemoryStream m;
21 | byte[] saveID = ReadByteString(request.Data, 0);
22 | request.Client.save_id = saveID;
23 | m = new MemoryStream();
24 | request.Client.AccountId = DBAccess.getInstance().GetPlayerAccountId(encoding.GetString(saveID));
25 | uint swapped = swap32((uint)request.Client.AccountId);
26 | await m.WriteAsync(BitConverter.GetBytes(swapped), 0, 4);
27 | byte[] buff = encoding.GetBytes(DBAccess.getInstance().MessageOfTheDay);
28 | m.WriteByte((byte)(buff.Length - 1));
29 | await m.WriteAsync(buff, 0, buff.Length);
30 | while (m.Length < 0x200) m.WriteByte(0);
31 | byte[] response = m.ToArray();
32 | return new[] { request.CreateResponse(0x742A, response) };
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Exceptions/LobbyEmuCrashException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading;
3 |
4 | namespace FragmentNetslumServer.Exceptions
5 | {
6 | [Serializable(), Obsolete("Don't use this class please, thank you", true)]
7 | public class LobbyEmuCrashException : System.Exception
8 | {
9 | public LobbyEmuCrashException() : base() { }
10 | public LobbyEmuCrashException(string message) : base(message) { }
11 | public LobbyEmuCrashException(string message, System.Exception inner) : base(message, inner) { }
12 |
13 | // :(
14 | public LobbyEmuCrashException(string message, Thread t, System.Exception inner) : base(message, inner)
15 | {
16 | //Console.WriteLine("Lobby Emulator Crashed");
17 |
18 | //if (t.IsAlive)
19 | //{
20 | // t.Abort();
21 | //}
22 |
23 | //foreach (GameClient client in Server.Instance.clients)
24 | // if (!client._exited)
25 | // client.Exit();
26 | //foreach (ProxyClient client in Server.Instance.proxies)
27 | // if (!client._exited)
28 | // client.Exit();
29 |
30 | //Log.Writeline("Server exited");
31 |
32 | //Console.WriteLine("Restarting the Lobby Emulator ");
33 |
34 | //Server.Instance.Start();
35 | }
36 |
37 | // A constructor is needed for serialization when an
38 | // exception propagates from a remoting server to the client.
39 | protected LobbyEmuCrashException(System.Runtime.Serialization.SerializationInfo info,
40 | System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
41 | }
42 | }
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/Guild/OPCODE_DATA_INVITE_TO_GUILD.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services.Interfaces;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using FragmentNetslumServer.Services;
8 |
9 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.Guild
10 | {
11 | [OpCodeData(OpCodes.OPCODE_DATA_INVITE_TO_GUILD)]
12 | public sealed class OPCODE_DATA_INVITE_TO_GUILD : IOpCodeHandler
13 | {
14 |
15 | private readonly ILobbyChatService _lobbyChatService;
16 |
17 | public OPCODE_DATA_INVITE_TO_GUILD(ILobbyChatService lobbyChatService)
18 | {
19 | _lobbyChatService = lobbyChatService;
20 |
21 | }
22 | public async Task> HandleIncomingRequestAsync(RequestContent request)
23 | {
24 | var u = BitConverter.ToUInt16(request.Data, 0).Swap();
25 | // This is probably only possible in the MAIN lobby so
26 | if (_lobbyChatService.TryFindLobby(request.Client, out var lobby))
27 | {
28 | await lobby.InviteClientToGuildAsync(request.Data, request.Client.ClientIndex, u, request.Client._guildID);
29 |
30 |
31 | return new[]
32 | {
33 | request.CreateResponse(0x772D, new byte[]{0x00 ,0x00})
34 | };//send to confirm that the player accepted the invite
35 |
36 | }
37 | return new[]
38 | {
39 | ResponseContent.Empty
40 | };// failed to find lobby ???
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/Guild/OPCODE_DATA_GUILD_GET_LIST_OF_ITEMS.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services.Interfaces;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Threading.Tasks;
6 | using static FragmentNetslumServer.Services.Extensions;
7 |
8 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.Guild
9 | {
10 | [OpCodeData(OpCodes.OPCODE_DATA_GUILD_GET_LIST_OF_ITEMS)]
11 | public sealed class OPCODE_DATA_GUILD_GET_LIST_OF_ITEMS : IOpCodeHandler
12 | {
13 | private readonly IGuildManagementService guildManagementService;
14 |
15 | public OPCODE_DATA_GUILD_GET_LIST_OF_ITEMS(IGuildManagementService guildManagementService)
16 | {
17 | this.guildManagementService = guildManagementService;
18 | }
19 |
20 | public Task> HandleIncomingRequestAsync(RequestContent request)
21 | {
22 | var responses = new List();
23 | var guildId = swap16(BitConverter.ToUInt16(request.Data, 0));
24 | bool isGeneral = guildId != request.Client._guildID;
25 |
26 | var listOfItemsForGeneralStore = guildManagementService.GetGuildItems(guildId, isGeneral);
27 | responses.Add(request.CreateResponse(OpCodes.OPCODE_DATA_GUILD_ITEMS_COUNT, BitConverter.GetBytes(swap16((ushort)listOfItemsForGeneralStore.Count))));
28 |
29 | foreach (var item in listOfItemsForGeneralStore)
30 | {
31 | responses.Add(request.CreateResponse(OpCodes.OPCODE_DATA_GUILD_ITEM_DETAILS, item));
32 | }
33 |
34 | return Task.FromResult>(responses);
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Services/Interfaces/IGuildManagementService.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | namespace FragmentNetslumServer.Services.Interfaces
4 | {
5 | public interface IGuildManagementService : IBaseService
6 | {
7 | byte[] AddItemToGuildInventory(ushort guildID, uint itemID, ushort itemQuantity, uint generalPrice, uint memberPrice, bool isGeneral, bool isMember, bool isGuildMaster);
8 | byte[] BuyItemFromGuild(byte[] argument);
9 | ushort CreateGuild(byte[] argument, uint masterPlayerID);
10 | byte[] DestroyGuild(ushort guildID);
11 | byte[] DonateCoinsToGuild(byte[] argument);
12 | List GetAllGuildItemsWithSettings(ushort guildID);
13 | byte[] GetGuildInfo(ushort guildID);
14 | List GetGuildItems(ushort guildId, bool isGeneral);
15 | List GetGuildMembersListByClass(ushort guildID, ushort categoryID, uint playerID);
16 | byte[] GetItemDonationSettings(bool isMaster);
17 | List GetListOfGuilds();
18 | byte[] GetPlayerGuild(uint characterID);
19 | byte[] GetPriceOfItemToBeDonated(ushort guildID, uint itemID);
20 | byte[] KickPlayerFromGuild(ushort guildID, uint playerToKick);
21 | byte[] LeaveGuild(ushort guildID, uint characterID);
22 | byte[] LeaveGuildAndAssignMaster(ushort guildID, uint playerToAssign);
23 | byte[] ReadByteGuildEmblem(byte[] data, int pos);
24 | byte[] ReadByteString(byte[] data, int pos);
25 | byte[] SetItemVisibilityAndPrice(byte[] argument);
26 | byte[] TakeItemFromGuild(ushort guildID, uint itemID, ushort quantity);
27 | byte[] TakeMoneyFromGuild(ushort guildID, uint amountOfMoney);
28 | byte[] UpdateGuildEmblemComment(byte[] argument, ushort guildID);
29 | }
30 | }
--------------------------------------------------------------------------------
/FragmentNetslumServerWebApi/Models/AreaServerModel.cs:
--------------------------------------------------------------------------------
1 | using System.Text;
2 | using FragmentNetslumServer.Entities;
3 |
4 | namespace FragmentNetslumServerWebApi.Models
5 | {
6 | public class AreaServerModel
7 | {
8 | private string _serverName;
9 | private int _serverLevel;
10 | private string _serverStatus;
11 | private int _numberOfPlayers;
12 |
13 |
14 | public static AreaServerModel ConvertDate(GameClientAsync client)
15 | {
16 | if (null == client.AreaServerName)
17 | return null;
18 |
19 |
20 | AreaServerModel model = new AreaServerModel();
21 |
22 | Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
23 |
24 | model._serverName = Encoding.GetEncoding("Shift-JIS").GetString(client.AreaServerName,0,client.AreaServerName.Length-1);
25 | model._serverLevel = client.AreaServerLevel;
26 | model._serverStatus = client.AreaServerStatus == 0 ? "Available" : "Busy";
27 | model._numberOfPlayers = client.Players;
28 |
29 | return model;
30 | }
31 |
32 | public string ServerName
33 | {
34 | get => _serverName;
35 | set => _serverName = value;
36 | }
37 |
38 | public int ServerLevel
39 | {
40 | get => _serverLevel;
41 | set => _serverLevel = value;
42 | }
43 |
44 | public string ServerStatus
45 | {
46 | get => _serverStatus;
47 | set => _serverStatus = value;
48 | }
49 |
50 | public int NumberOfPlayers
51 | {
52 | get => _numberOfPlayers;
53 | set => _numberOfPlayers = value;
54 | }
55 | }
56 | }
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/BBS/OPCODE_DATA_BBS_THREAD_GETMENU.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services.Interfaces;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Threading.Tasks;
6 | using static FragmentNetslumServer.Services.Extensions;
7 |
8 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.BBS
9 | {
10 | [OpCodeData(OpCodes.OPCODE_DATA_BBS_THREAD_GETMENU)]
11 | public sealed class OPCODE_DATA_BBS_THREAD_GETMENU : IOpCodeHandler
12 | {
13 | private readonly IBulletinBoardService bulletinBoardService;
14 |
15 | public OPCODE_DATA_BBS_THREAD_GETMENU(IBulletinBoardService bulletinBoardService)
16 | {
17 | this.bulletinBoardService = bulletinBoardService ?? throw new ArgumentNullException(nameof(bulletinBoardService));
18 | }
19 |
20 | public async Task> HandleIncomingRequestAsync(RequestContent request)
21 | {
22 | var responses = new List();
23 | var i = swap32(BitConverter.ToUInt32(request.Data, 0));
24 | var threadID = Convert.ToInt32(i);
25 | var postMetaList = await bulletinBoardService.GetThreadDetailsAsync(threadID);
26 | responses.Add(request.CreateResponse(OpCodes.OPCODE_DATA_BBS_THREAD_LIST, BitConverter.GetBytes(swap32((uint)postMetaList.Count))));
27 | foreach (var meta in postMetaList)
28 | {
29 | var postMetaBytes = await bulletinBoardService.ConvertThreadDetailsToBytesAsync(meta);
30 | responses.Add(request.CreateResponse(OpCodes.OPCODE_DATA_BBS_ENTRY_POST_META, postMetaBytes));
31 | }
32 | return responses;
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/AreaServer/OPCODE_DATA_AS_PUBLISH_DETAILS.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Threading.Tasks;
5 | using FragmentNetslumServer.Entities.Attributes;
6 | using FragmentNetslumServer.Services.Interfaces;
7 |
8 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.AreaServer
9 | {
10 | [OpCodeData(OpCodes.OPCODE_DATA_AS_PUBLISH_DETAILS1),
11 | OpCodeData(OpCodes.OPCODE_DATA_AS_PUBLISH_DETAILS2)]
12 | class OPCODE_DATA_AS_PUBLISH_DETAILS : IOpCodeHandler
13 | {
14 | public async Task> HandleIncomingRequestAsync(RequestContent request)
15 | {
16 | switch(request.DataOpCode)
17 | {
18 | case OpCodes.OPCODE_DATA_AS_PUBLISH_DETAILS1:
19 | MemoryStream m;
20 | int end = request.Data.Length - 1;
21 | while (request.Data[end] == 0) end--;
22 | end++;
23 | m = new MemoryStream();
24 | await m.WriteAsync(request.Data, 65, end - 65);
25 | request.Client.publish_data_1 = m.ToArray();
26 | return new[] { request.CreateResponse(OpCodes.OPCODE_DATA_AS_PUBLISH_DETAILS1_OK, new byte[] { 0x00, 0x01 }) };
27 | case OpCodes.OPCODE_DATA_AS_PUBLISH_DETAILS2:
28 | return new[] { request.CreateResponse(OpCodes.OPCODE_DATA_AS_PUBLISH_DETAILS2_OK, new byte[] { 0xDE, 0xAD }) };
29 | }
30 | throw new ArgumentOutOfRangeException(nameof(request.DataOpCode), $"{request.DataOpCode:X2} is outside the expected values ({OpCodes.OPCODE_DATA_AS_PUBLISH_DETAILS1:X2} & {OpCodes.OPCODE_DATA_AS_PUBLISH_DETAILS2:X2})");
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/Guild/OPCODE_DATA_GUILD_TAKE_ITEM.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services.Interfaces;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using FragmentNetslumServer.Services;
8 | using Serilog;
9 |
10 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.Guild
11 | {
12 | [OpCodeData(OpCodes.OPCODE_DATA_GUILD_TAKE_ITEM)]
13 | public sealed class OPCODE_DATA_GUILD_TAKE_ITEM : IOpCodeHandler
14 | {
15 | private readonly ILogger _logger;
16 | private readonly IGuildManagementService _guildManagementService;
17 |
18 | public OPCODE_DATA_GUILD_TAKE_ITEM(ILogger logger,IGuildManagementService guildManagementService)
19 | {
20 | _logger = logger;
21 | _guildManagementService = guildManagementService;
22 |
23 | }
24 | public Task> HandleIncomingRequestAsync(RequestContent request)
25 | {
26 | ushort guildIDTakeItem = BitConverter.ToUInt16(request.Data, 0).Swap();
27 | uint itemIDToTakeOut = BitConverter.ToUInt32(request.Data, 2).Swap();
28 | ushort quantityToTake = BitConverter.ToUInt16(request.Data, 6).Swap();
29 |
30 | _logger.Debug("Guild ID {guildIDTakeItem}\nItem ID to take {itemIDToTakeOut}\n quantity to take out {quantityToTake}" ,guildIDTakeItem , itemIDToTakeOut,quantityToTake);
31 |
32 | return Task.FromResult>(new[]
33 | {
34 | request.CreateResponse(0x7711,
35 | _guildManagementService.TakeItemFromGuild(guildIDTakeItem, itemIDToTakeOut,quantityToTake))
36 | });
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/README.MD:
--------------------------------------------------------------------------------
1 | # .hack//frägment Server Emulator
2 |
3 | [](https://app.travis-ci.com/Zackmon/FragmentNetslumServer)
4 | [](https://sonarcloud.io/dashboard?id=Zackmon_FragmentServer_netCore)
5 |
6 | A private Lobby Server Emulator for the PS2 game .hack//frägment
7 |
8 | # Credits
9 | Big thanks to Warranty Voider for the original port of the C/C++ [Lobby Server](https://github.com/Lord-Ptolemy/lobbyemu).
10 | Lobby Server in action: https://www.youtube.com/watch?v=VErjuUM4AQM (Credit to Warranty Voider for the video)
11 |
12 | # Setup
13 | The Lobby Server requires a MySQL/MariaDB backend. The file `settings.ini.example` located in the root of this repository should be copied and renamed to `settings.ini`, then modified with the connection details for the database.
14 |
15 | ## Database Setup
16 | Once your configuration file has been adjusted, you will need to run `FragmentNetslumServer/SQL/DB.SQL` to lay out the correct schema objects.
17 |
18 | # Web Interface
19 | `FragmentNetslumServerLauncher` includes a reference to `FragmentNetslumServerWebAPI` and fires it up, attempting to expose all internal services to the WebAPI. For the time being, there is no proper UI but rather API calls. In the future, I hope to include a barebones Web UI that would allow for an Administrator to remotely control the system.
20 |
21 | # Notes
22 | There are plenty of things I'm considering doing with the code base. These are listed in no particular order:
23 | - Some additional refactoring / abstractions to properly handle Clients versus Area Servers
24 | - Consider a fully functional Web UI (complete with security abstractions)
25 | - Provide a consistent, fully documented, read only API
26 | - Figure out why Guild Chat doesn't work
--------------------------------------------------------------------------------
/FragmentNetslumServer/Models/Mapping/GuildRepositoryModel.hbm.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/Mail/OPCODE_DATA_MAIL_GET.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services.Interfaces;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.ComponentModel;
6 | using System.Threading.Tasks;
7 | using static FragmentNetslumServer.Services.Extensions;
8 |
9 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.Mail
10 | {
11 |
12 | [OpCodeData(OpCodes.OPCODE_DATA_MAIL_GET), Description("Retrieves mail for a requesting client")]
13 | public sealed class OPCODE_DATA_MAIL_GET : IOpCodeHandler
14 | {
15 | private readonly IMailService mailService;
16 |
17 | public OPCODE_DATA_MAIL_GET(IMailService mailService)
18 | {
19 | this.mailService = mailService ?? throw new ArgumentNullException(nameof(mailService));
20 | }
21 |
22 | public async Task> HandleIncomingRequestAsync(RequestContent request)
23 | {
24 | var responses = new List();
25 | var accountId = ReadAccountID(request.Data, 0);
26 | var mail = await mailService.GetMailAsync(accountId);
27 | responses.Add(request.CreateResponse(OpCodes.OPCODE_DATA_MAIL_GETOK, BitConverter.GetBytes(swap32((uint)mail.Count))));
28 | foreach (var item in mail)
29 | {
30 | var mailContent = await mailService.ConvertMailMetaIntoBytes(item);
31 | responses.Add(request.CreateResponse(OpCodes.OPCODE_DATA_MAIL_GET_NEWMAIL_HEADER, mailContent));
32 | }
33 | return responses;
34 | }
35 |
36 | static int ReadAccountID(byte[] data, int pos)
37 | {
38 | byte[] accountID = new byte[4];
39 | Buffer.BlockCopy(data, pos, accountID, 0, 4);
40 | return (int)swap32(BitConverter.ToUInt32(accountID));
41 | }
42 |
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/AreaServer/OPCODE_DATA_AS_IPPORT.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.ComponentModel;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 | using FragmentNetslumServer.Entities.Attributes;
7 |
8 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.AreaServer
9 | {
10 | [OpCodeData(OpCodes.OPCODE_DATA_AS_IPPORT), Description("Determines the external IP address for the Client. This does also attempt to handle rewriting 127.0.0.1 to a 'more correct' IP address")]
11 | public sealed class OPCODE_DATA_AS_IPPORT : SimpleResponseOpCodeHandler
12 | {
13 | public OPCODE_DATA_AS_IPPORT() : base(OpCodes.OPCODE_DATA_AS_IPPORT_OK, new byte[] { 0x00, 0x00 }) { }
14 |
15 | public override Task> HandleIncomingRequestAsync(RequestContent request)
16 | {
17 | using (MemoryStream memoryStream = new MemoryStream())
18 | {
19 | memoryStream.Write(request.Data);
20 | request.Client.ipdata = memoryStream.ToArray(); // local ip coming from Area Server
21 | }
22 | var externalIpAddress = request.Client.ipEndPoint.Address.ToString(); // Capturing the external IP from ipEndpoint
23 | if (externalIpAddress == Helpers.IPAddressHelpers.LOOPBACK_IP_ADDRESS)
24 | {
25 | externalIpAddress = Helpers.IPAddressHelpers.GetLocalIPAddress2();
26 | }
27 | var ipAddress = externalIpAddress.Split('.');
28 | // var ipAddressBytes = ipAddress.Reverse().Select(c => byte.Parse(c)).ToArray();
29 |
30 | request.Data[3] = byte.Parse(ipAddress[0]);
31 | request.Data[2] = byte.Parse(ipAddress[1]);
32 | request.Data[1] = byte.Parse(ipAddress[2]);
33 | request.Data[0] = byte.Parse(ipAddress[3]);
34 |
35 | request.Client.externalIPAddress = request.Data;
36 | return base.HandleIncomingRequestAsync(request);
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Regular/OPCODE_KEY_EXCHANGE_REQUEST.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services.Interfaces;
3 | using System.Collections.Generic;
4 | using System.ComponentModel;
5 | using System.IO;
6 | using System.Security.Cryptography;
7 | using System.Threading.Tasks;
8 |
9 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Regular
10 | {
11 | [OpCode(OpCodes.OPCODE_KEY_EXCHANGE_REQUEST),
12 | Description("Handles initializing encryption & decryption keys on the connected Client")]
13 | public sealed class OPCODE_KEY_EXCHANGE_REQUEST : IOpCodeHandler
14 | {
15 | public async Task> HandleIncomingRequestAsync(RequestContent request)
16 | {
17 | var responseStream = new MemoryStream();
18 | responseStream.Write(request.Data, 4, 16);
19 | var from_key = responseStream.ToArray();
20 | var to_key = new byte[16];
21 | using (var rng = new RNGCryptoServiceProvider())
22 | {
23 | rng.GetBytes(to_key);
24 | }
25 | await responseStream.DisposeAsync();
26 | request.Client.InitializeDecryptionKey(from_key);
27 | request.Client.InitializeEncryptionKey(to_key);
28 |
29 | responseStream = new MemoryStream();
30 | responseStream.WriteByte(0);
31 | responseStream.WriteByte(0x10);
32 | responseStream.Write(from_key, 0, 16);
33 | responseStream.WriteByte(0);
34 | responseStream.WriteByte(0x10);
35 | responseStream.Write(to_key, 0, 16);
36 | responseStream.Write(new byte[] { 0, 0, 0, 0xe, 0, 0, 0, 0, 0, 0 }, 0, 10);
37 | var responseArray = responseStream.ToArray();
38 | var checksum = Crypto.Checksum(responseArray);
39 | await responseStream.DisposeAsync();
40 | return new[] { new ResponseContent(request, OpCodes.OPCODE_KEY_EXCHANGE_RESPONSE, responseArray, checksum) };
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/FragmentNetslumServerWebApi/Controllers/StatusPageController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using FragmentNetslumServer.Services.Interfaces;
3 | using FragmentNetslumServerWebApi.Models;
4 | using Microsoft.AspNetCore.Mvc;
5 | using Microsoft.Extensions.Logging;
6 |
7 | namespace FragmentNetslumServerWebApi.Controllers
8 | {
9 | [ApiController]
10 | [Route("status")]
11 | public class StatusPageController : ControllerBase
12 | {
13 | private readonly ILogger _logger;
14 | private readonly IClientProviderService clientProviderService;
15 | private readonly IClientConnectionService clientConnectionService;
16 |
17 | public StatusPageController(
18 | ILogger logger,
19 | IClientProviderService clientProviderService,
20 | IClientConnectionService clientConnectionService)
21 | {
22 | _logger = logger ?? throw new ArgumentNullException(nameof(logger));
23 | this.clientProviderService = clientProviderService ?? throw new ArgumentNullException(nameof(clientProviderService));
24 | this.clientConnectionService = clientConnectionService ?? throw new ArgumentNullException(nameof(clientConnectionService));
25 | }
26 |
27 | [HttpGet]
28 | public ClientsModel Get()
29 | {
30 | ClientsModel clientList = new ClientsModel();
31 | foreach (var client in clientProviderService.Clients)
32 | {
33 | if (client.IsAreaServer)
34 | {
35 | AreaServerModel model = AreaServerModel.ConvertDate(client);
36 | if (model!= null)
37 | clientList._areaServerList.Add(model);
38 | }
39 | else
40 | {
41 | PlayerModel model = PlayerModel.ConvertData(client);
42 | if (model != null)
43 | clientList.PlayerList.Add(model);
44 | }
45 | }
46 |
47 | return clientList;
48 | }
49 | }
50 | }
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/News/OPCODE_DATA_NEWS_GETPOST.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using FragmentNetslumServer.Entities.Attributes;
8 | using FragmentNetslumServer.Services;
9 | using FragmentNetslumServer.Services.Interfaces;
10 |
11 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.News;
12 |
13 | [OpCodeData(OpCodes.OPCODE_DATA_NEWS_GETPOST), Description("Get the image for the requested article")]
14 | public sealed class OPCODE_DATA_NEWS_GETPOST : IOpCodeHandler
15 | {
16 | private readonly INewsService _newsService;
17 | private readonly Encoding _encoding;
18 |
19 | public OPCODE_DATA_NEWS_GETPOST(INewsService newsService)
20 | {
21 | _newsService = newsService;
22 | Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
23 | _encoding = Encoding.GetEncoding("Shift-JIS");
24 |
25 | }
26 | public async Task> HandleIncomingRequestAsync(RequestContent request)
27 | {
28 | List listOfResponse = new List();
29 |
30 | var articleId = BitConverter.ToUInt16(request.Data, 0).Swap();
31 |
32 | var article = (await _newsService.GetNewsArticles()).First(a => a.ArticleID == articleId);
33 |
34 | if (article.ImageSizeInfo == null || article.ImageDetails == null)
35 | {
36 | listOfResponse.Add(request.CreateResponse(0x7857, new byte[] {0x00,0x00 })); // Error while getting the image data
37 | }
38 | else
39 | {
40 | listOfResponse.Add(request.CreateResponse(0x7855, article.ImageSizeInfo)); // send the image size and chunk count
41 | listOfResponse.Add(request.CreateResponse(0x7856, article.ImageDetails)); // send the color pallets and the image indices
42 | }
43 |
44 | await _newsService.UpdateNewsLog(_encoding.GetString(request.Client.save_id), articleId);
45 |
46 | return listOfResponse;
47 | }
48 | }
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/Guild/OPCODE_DATA_GUILD_UPDATEITEM_PRICING_AVAILABILITY.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services.Interfaces;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using FragmentNetslumServer.Services;
8 | using Serilog;
9 |
10 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.Guild
11 | {
12 | [OpCodeData(OpCodes.OPCODE_DATA_GUILD_UPDATEITEM_PRICING_AVAILABILITY)]
13 | public sealed class OPCODE_DATA_GUILD_UPDATEITEM_PRICING_AVAILABILITY : IOpCodeHandler
14 | {
15 | private readonly ILogger _logger;
16 | private readonly IGuildManagementService _guildManagementService;
17 |
18 | public OPCODE_DATA_GUILD_UPDATEITEM_PRICING_AVAILABILITY(ILogger logger,IGuildManagementService guildManagementService)
19 | {
20 | _logger = logger;
21 | _guildManagementService = guildManagementService;
22 |
23 | }
24 | public Task> HandleIncomingRequestAsync(RequestContent request)
25 | {
26 | uint generalPrice = BitConverter.ToUInt32(request.Data, 0).Swap();
27 | uint memberPrice = BitConverter.ToUInt32(request.Data, 4).Swap();
28 | bool isGeneral = BitConverter.ToBoolean(request.Data, 8);
29 | bool isMember = BitConverter.ToBoolean(request.Data, 9);
30 |
31 | _logger.Debug("GenePrice {GeneralPrice}\nMemberPrice {MemberPrice}\nisGeneral {isGeneral}\nisMember {isMember}",generalPrice,memberPrice,isGeneral,isMember);
32 |
33 | return Task.FromResult>(new[]
34 | {
35 | request.CreateResponse(0x7705,
36 | _guildManagementService.AddItemToGuildInventory(
37 | request.Client._guildID,request.Client._itemDontationID,
38 | request.Client._itemDonationQuantity,
39 | generalPrice,memberPrice,isGeneral,isMember,request.Client.isGuildMaster))
40 | });
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/Guild/OPCODE_DATA_GUILD_MEMBERLIST.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services;
3 | using FragmentNetslumServer.Services.Interfaces;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Threading.Tasks;
7 | using static FragmentNetslumServer.Services.Extensions;
8 |
9 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.Guild
10 | {
11 | [OpCodeData(OpCodes.OPCODE_DATA_GUILD_MEMBERLIST)]
12 | public sealed class OPCODE_DATA_GUILD_MEMBERLIST : IOpCodeHandler
13 | {
14 | private readonly IGuildManagementService guildManagementService;
15 |
16 | public OPCODE_DATA_GUILD_MEMBERLIST(IGuildManagementService guildManagementService)
17 | {
18 | this.guildManagementService = guildManagementService;
19 | }
20 |
21 | public Task> HandleIncomingRequestAsync(RequestContent request)
22 | {
23 | var responses = new List();
24 | var u = swap16(BitConverter.ToUInt16(request.Data, 0));
25 | if (u == 0)// Guild Member Category List
26 | {
27 | List listOfClasses = GetClassList();
28 | responses.Add(request.CreateResponse(0x7611, BitConverter.GetBytes(swap16((ushort)listOfClasses.Count))));
29 | foreach (var className in listOfClasses)
30 | {
31 | responses.Add(request.CreateResponse(0x7613, className));
32 | }
33 |
34 | }
35 | else //MemberList in that Category
36 | {
37 | List memberList = guildManagementService.GetGuildMembersListByClass(request.Client._guildID, u, request.Client._characterPlayerID);
38 | responses.Add(request.CreateResponse(0x7614, BitConverter.GetBytes(swap16((ushort)memberList.Count))));
39 | foreach (var member in memberList)
40 | {
41 | responses.Add(request.CreateResponse(0x7615, member));
42 | }
43 | }
44 | return Task.FromResult>(responses);
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Services/Interfaces/IMailService.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Threading.Tasks;
3 | using FragmentNetslumServer.Models;
4 |
5 | namespace FragmentNetslumServer.Services.Interfaces
6 | {
7 |
8 | ///
9 | /// Defines a service for interacting with the mail
10 | ///
11 | public interface IMailService: IBaseService
12 | {
13 |
14 | ///
15 | /// Asynchronously saves (and subsequently sends) all Mail information to the database
16 | ///
17 | /// The mail content
18 | /// A promise to save the mail
19 | Task SaveMailAsync(byte[] content);
20 |
21 | Task SaveGuildMailAsync(byte[] content);
22 |
23 | ///
24 | /// Retrieves mail for the given account ID
25 | ///
26 | /// The player account ID
27 | /// A promise that, when awaited, will return a collection of
28 | Task> GetMailAsync(int accountId);
29 |
30 | ///
31 | /// Retrieves the message body for a given piece of mail
32 | ///
33 | /// The ID for the piece of mail
34 | ///
35 | Task GetMailContent(int mailId);
36 |
37 | ///
38 | /// Converts a received into a transmittable byte array
39 | ///
40 | ///
41 | /// A promise to convert the to a byte array
42 | Task ConvertMailMetaIntoBytes(MailMetaModel mail);
43 |
44 | ///
45 | /// Converts a received into a transmittable byte array
46 | ///
47 | ///
48 | /// A promise to convert the to a byte array
49 | Task ConvertMailBodyIntoBytes(MailBodyModel mail);
50 |
51 | }
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/Guild/OPCODE_DATA_GUILD_GET_ALL_GUILDS.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services.Interfaces;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Threading.Tasks;
6 | using static FragmentNetslumServer.Services.Extensions;
7 |
8 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.Guild
9 | {
10 | [OpCodeData(OpCodes.OPCODE_DATA_GUILD_GET_ALL_GUILDS)]
11 | public sealed class OPCODE_DATA_GUILD_GET_ALL_GUILDS : IOpCodeHandler
12 | {
13 | private readonly IGuildManagementService guildManagementService;
14 |
15 | public OPCODE_DATA_GUILD_GET_ALL_GUILDS(IGuildManagementService guildManagementService)
16 | {
17 | this.guildManagementService = guildManagementService;
18 | }
19 |
20 | public Task> HandleIncomingRequestAsync(RequestContent request)
21 | {
22 | var responses = new List();
23 | var u = swap16(BitConverter.ToUInt16(request.Data, 0));
24 | // This is very similar to the area server handler
25 | // If this is zero, show the guild category breakdown (basically)
26 | // otherwise, show them all the guilds
27 | if (u == 0)
28 | {
29 | // Tell them we have ONE guild listing
30 | responses.Add(request.CreateResponse(OpCodes.OPCODE_DATA_GUILD_GROUP_COUNT, new byte[] { 0x00, 0x01 }));
31 |
32 | // This should print "ALL" on the game
33 | responses.Add(request.CreateResponse(OpCodes.OPCODE_DATA_GUILD_GROUP_CATEGORY, new byte[] { 0x00, 0x01, 0x41, 0x6c, 0x6c, 0x00 }));
34 | }
35 | else
36 | {
37 | var listOfGuilds = guildManagementService.GetListOfGuilds();
38 | responses.Add(request.CreateResponse(OpCodes.OPCODE_DATA_GUILD_COUNT, BitConverter.GetBytes(swap16((ushort)listOfGuilds.Count))));
39 | foreach (var guildName in listOfGuilds)
40 | {
41 | responses.Add(request.CreateResponse(OpCodes.OPCODE_DATA_GUILD_ENTRY, guildName));
42 | }
43 | }
44 | return Task.FromResult>(responses);
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/Lobby/OPCODE_DATA_LOBBY_GETMENU.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services.Interfaces;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.ComponentModel;
6 | using System.IO;
7 | using System.Linq;
8 | using System.Threading.Tasks;
9 | using static FragmentNetslumServer.Services.Extensions;
10 |
11 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.Lobby
12 | {
13 |
14 | [OpCodeData(OpCodes.OPCODE_DATA_LOBBY_GETMENU), Description("Returns a list of available lobbies and participants")]
15 | public sealed class OPCODE_DATA_LOBBY_GETMENU : IOpCodeHandler
16 | {
17 | private readonly ILobbyChatService lobbyChatService;
18 |
19 | public OPCODE_DATA_LOBBY_GETMENU(ILobbyChatService lobbyChatService)
20 | {
21 | this.lobbyChatService = lobbyChatService ?? throw new System.ArgumentNullException(nameof(lobbyChatService));
22 | }
23 |
24 | public async Task> HandleIncomingRequestAsync(RequestContent request)
25 | {
26 | var responses = new List();
27 | var nonGuildLobbies = new List(lobbyChatService.Lobbies.Values.Where(c => c.Type == OpCodes.LOBBY_TYPE_MAIN));
28 |
29 | responses.Add(request.CreateResponse(OpCodes.OPCODE_DATA_LOBBY_LOBBYLIST, BitConverter.GetBytes(swap16((ushort)nonGuildLobbies.Count))));
30 | foreach (var room in nonGuildLobbies)
31 | {
32 | var m = new MemoryStream();
33 | await m.WriteAsync(BitConverter.GetBytes(swap16(room.ID)), 0, 2);
34 | foreach (char c in room.Name)
35 | m.WriteByte((byte)c);
36 | m.WriteByte(0);
37 | await m.WriteAsync(BitConverter.GetBytes(swap16((ushort)room.Clients.Count)), 0, 2);
38 | await m.WriteAsync(BitConverter.GetBytes(swap16((ushort)(room.Clients.Count + 1))), 0, 2);
39 | // looks like some form of padding to align the message
40 | while (((m.Length + 2) % 8) != 0) m.WriteByte(0);
41 | responses.Add(request.CreateResponse(OpCodes.OPCODE_DATA_LOBBY_ENTRY_LOBBY, m.ToArray()));
42 | }
43 |
44 | return responses;
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Config.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Collections.ObjectModel;
4 | using System.IO;
5 |
6 | namespace FragmentNetslumServer
7 | {
8 |
9 | ///
10 | /// A simple key-value pair configuration class that also supports line comments
11 | ///
12 | ///
13 | /// INI lite
14 | ///
15 | public sealed class SimpleConfiguration
16 | {
17 |
18 | private readonly Dictionary configurationValues;
19 |
20 |
21 | ///
22 | /// Gets a that represents the loaded configuration
23 | ///
24 | public ReadOnlyDictionary Values => new ReadOnlyDictionary(configurationValues);
25 |
26 | ///
27 | /// Creates a new instance of the Configuration class
28 | ///
29 | public SimpleConfiguration()
30 | {
31 | configurationValues = new Dictionary(StringComparer.OrdinalIgnoreCase);
32 | if (File.Exists("settings.ini"))
33 | {
34 | var lines = File.ReadAllLines("settings.ini");
35 | foreach (var line in lines)
36 | {
37 | var clean = line.Trim();
38 | if (!string.IsNullOrWhiteSpace(clean) && !clean.StartsWith("#"))
39 | {
40 | var parts = line.Split('=');
41 | var key = parts[0].Trim();
42 | var value = string.Join('=', parts[1..]).Trim();
43 | configurationValues.Add(key.ToLowerInvariant(), value);
44 | }
45 | }
46 |
47 | }
48 | }
49 |
50 | ///
51 | /// Retrieves a value if it exists, otherwise returns
52 | ///
53 | /// The name of the configuration value
54 | /// The value to return if doesn't exist
55 | ///
56 | public string Get(string name, string @default = "") => configurationValues.ContainsKey(name) ? configurationValues[name] : @default;
57 |
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/Guild/OPCODE_DATA_GUILD_GETMENU.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services;
3 | using FragmentNetslumServer.Services.Interfaces;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Threading.Tasks;
7 | using static FragmentNetslumServer.Services.Extensions;
8 |
9 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.Guild
10 | {
11 | ///
12 | /// Looks quite simliar to but uses different opcodes...
13 | ///
14 | [OpCodeData(OpCodes.OPCODE_DATA_GUILD_GETMENU)]
15 | public sealed class OPCODE_DATA_GUILD_GETMENU : IOpCodeHandler
16 | {
17 | private readonly IGuildManagementService guildManagementService;
18 |
19 | public OPCODE_DATA_GUILD_GETMENU(IGuildManagementService guildManagementService)
20 | {
21 | this.guildManagementService = guildManagementService;
22 | }
23 |
24 | public Task> HandleIncomingRequestAsync(RequestContent request)
25 | {
26 | var responses = new List();
27 | var u = swap16(BitConverter.ToUInt16(request.Data, 0));
28 | // This is very similar to the area server handler
29 | // If this is zero, show the guild category breakdown (basically)
30 | // otherwise, show them all the guilds
31 | if (u == 0)
32 | {
33 | // Tell them we have ONE guild listing
34 | responses.Add(request.CreateResponse(0x7734, new byte[] { 0x00, 0x01 }));
35 |
36 | // This should print "ALL" on the game
37 | responses.Add(request.CreateResponse(0x7736, new byte[] { 0x00, 0x01, 0x41, 0x6c, 0x6c, 0x00 }));
38 | }
39 | else
40 | {
41 | var listOfGuilds = guildManagementService.GetListOfGuilds();
42 | responses.Add(request.CreateResponse(0x7737, BitConverter.GetBytes(swap16((ushort)listOfGuilds.Count))));
43 | foreach (var guildName in listOfGuilds)
44 | {
45 | responses.Add(request.CreateResponse(0x7738, guildName));
46 | }
47 | }
48 | return Task.FromResult>(responses);
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Services/Interfaces/IClientConnectionService.cs:
--------------------------------------------------------------------------------
1 | using System.Net;
2 |
3 | namespace FragmentNetslumServer.Services.Interfaces
4 | {
5 |
6 | ///
7 | /// Defines a service that's responsible for managing the initial listener that accepts connections
8 | ///
9 | ///
10 | /// The implementation of this service should not block at any instance
11 | ///
12 | public interface IClientConnectionService: IBaseService
13 | {
14 |
15 | ///
16 | /// Activates and allows for connections
17 | ///
18 | /// The IP address the service should bind to
19 | /// The port number to listen on
20 | ///
21 | /// can accept a single at a time. Subsequent calls to this method will basically not work
22 | ///
23 | void BeginListening(string ipAddress, ushort port);
24 |
25 | ///
26 | /// Activates and allows for connections
27 | ///
28 | /// The IP address the service should bind to
29 | /// The port number to listen on
30 | ///
31 | /// can accept a single at a time. Subsequent calls to this method will basically not work
32 | ///
33 | void BeginListening(IPAddress ipAddress, ushort port);
34 |
35 | ///
36 | /// Disables and no longer accepts more connections
37 | ///
38 | ///
39 | /// As a programmer note, this is more like disabling a 'login' server rather than shutting down existing connections
40 | ///
41 | void EndListening();
42 |
43 | ///
44 | /// Restarts in the event that it was shutdown
45 | ///
46 | ///
47 | /// This method will do nothing if the system is still running properly
48 | ///
49 | void RestartService();
50 |
51 | }
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Helpers/IPAddressHelpers.cs:
--------------------------------------------------------------------------------
1 | using System.Net;
2 | using System.Net.NetworkInformation;
3 | using System.Net.Sockets;
4 |
5 | namespace FragmentNetslumServer.Helpers
6 | {
7 |
8 | ///
9 | /// Some IP address related helper functions
10 | ///
11 | public static class IPAddressHelpers
12 | {
13 |
14 | ///
15 | /// Defines, as a global constant, the permanent loopback IP address (aka LOCALHOST)
16 | ///
17 | public const string LOOPBACK_IP_ADDRESS = "127.0.0.1";
18 |
19 |
20 | ///
21 | /// Selects an IPv4 address to use instead of 127.0.0.1
22 | ///
23 | public static string GetLocalIPAddress()
24 | {
25 |
26 | // Get a list of all network interfaces (usually one per network card, dialup, and VPN connection)
27 | NetworkInterface[] networkInterfaces = NetworkInterface.GetAllNetworkInterfaces();
28 |
29 | foreach (NetworkInterface network in networkInterfaces)
30 | {
31 | // Read the IP configuration for each network
32 | IPInterfaceProperties properties = network.GetIPProperties();
33 |
34 | // Each network interface may have multiple IP addresses
35 | foreach (IPAddressInformation address in properties.UnicastAddresses)
36 | {
37 | // We're only interested in IPv4 addresses for now
38 | if (address.Address.AddressFamily != AddressFamily.InterNetwork)
39 | continue;
40 |
41 | // Ignore loopback addresses (e.g., 127.0.0.1)
42 | if (IPAddress.IsLoopback(address.Address))
43 | continue;
44 |
45 | return address.Address.ToString();
46 | }
47 | }
48 |
49 | return "0.0.0.0";
50 |
51 | }
52 |
53 |
54 | public static string GetLocalIPAddress2()
55 | {
56 | var addresses = Dns.GetHostAddresses(Dns.GetHostName());
57 | foreach (IPAddress a in addresses)
58 | {
59 | if (a.AddressFamily == AddressFamily.InterNetwork)
60 | {
61 | return a.ToString();
62 | }
63 | }
64 |
65 | return "0.0.0.0";
66 |
67 | }
68 |
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/BBS/OPCODE_DATA_BBS_GETMENU.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services.Interfaces;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using static FragmentNetslumServer.Services.Extensions;
8 |
9 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.BBS
10 | {
11 | [OpCodeData(OpCodes.OPCODE_DATA_BBS_GETMENU)]
12 | public sealed class OPCODE_DATA_BBS_GETMENU : IOpCodeHandler
13 | {
14 | private readonly IBulletinBoardService bulletinBoardService;
15 |
16 | public OPCODE_DATA_BBS_GETMENU(IBulletinBoardService bulletinBoardService)
17 | {
18 | this.bulletinBoardService = bulletinBoardService ?? throw new ArgumentNullException(nameof(bulletinBoardService));
19 | }
20 |
21 | public async Task> HandleIncomingRequestAsync(RequestContent request)
22 | {
23 | var responses = new List();
24 | var u = swap16(BitConverter.ToUInt16(request.Data, 0));
25 | if (u == 0)
26 | {
27 | var categoryList = await bulletinBoardService.GetCategoriesAsync();
28 | responses.Add(request.CreateResponse(OpCodes.OPCODE_DATA_BBS_CATEGORYLIST, BitConverter.GetBytes(swap16((ushort)categoryList.Count))));
29 | foreach (var category in categoryList)
30 | {
31 | var categoryData = await bulletinBoardService.ConvertCategoryToBytesAsync(category);
32 | responses.Add(request.CreateResponse(OpCodes.OPCODE_DATA_BBS_ENTRY_CATEGORY, categoryData));
33 | }
34 | }
35 | else
36 | {
37 | var categoryID = Convert.ToInt32(u);
38 | var threadsList = await bulletinBoardService.GetThreadsAsync(categoryID);
39 | responses.Add(request.CreateResponse(OpCodes.OPCODE_DATA_BBS_THREADLIST, BitConverter.GetBytes(swap16((ushort)threadsList.Count))));
40 | foreach (var thread in threadsList)
41 | {
42 | var threadData = await bulletinBoardService.ConvertThreadToBytesAsync(thread);
43 | responses.Add(request.CreateResponse(OpCodes.OPCODE_DATA_BBS_ENTRY_THREAD, threadData));
44 | }
45 | }
46 | return responses;
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Services/Interfaces/IClientProviderService.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.ObjectModel;
2 | using System.Net.Sockets;
3 | using FragmentNetslumServer.Entities;
4 |
5 | namespace FragmentNetslumServer.Services.Interfaces
6 | {
7 | ///
8 | /// Defines a service that's responsible for managing connected client
9 | ///
10 | public interface IClientProviderService: IBaseService
11 | {
12 |
13 | ///
14 | /// Gets a collection of currently connected instances
15 | ///
16 | ReadOnlyCollection Clients { get; }
17 |
18 | ///
19 | /// Gets a collection of currently connected that have declared themselves as Area Servers
20 | ///
21 | ReadOnlyCollection AreaServers { get; }
22 |
23 |
24 |
25 | ///
26 | /// Adds a new client to the
27 | ///
28 | /// The newly connected
29 | /// An identifier for the client
30 | void AddClient(TcpClient client, uint clientId);
31 |
32 | ///
33 | /// Adds a new client to the
34 | ///
35 | /// The newly created
36 | void AddClient(GameClientAsync client);
37 |
38 |
39 | ///
40 | /// Removes an existing client from
41 | ///
42 | /// The identifier for the client
43 | void RemoveClient(uint clientId);
44 |
45 | ///
46 | /// Removes an existing client from
47 | ///
48 | /// to remove
49 | void RemoveClient(GameClientAsync client);
50 |
51 | ///
52 | /// Attempts to retrieve a based on its index
53 | ///
54 | /// The expected client index
55 | /// The
56 | /// A boolean value to indicate success or failure
57 | bool TryGetClient(uint index, out GameClientAsync client);
58 | }
59 |
60 | }
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/Lobby/OPCODE_DATA_LOBBY_ENTERROOM.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services.Interfaces;
3 | using Serilog;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.ComponentModel;
7 | using System.Threading.Tasks;
8 | using static FragmentNetslumServer.Services.Extensions;
9 |
10 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.Lobby
11 | {
12 |
13 | [OpCodeData(OpCodes.OPCODE_DATA_LOBBY_ENTERROOM), Description("Informs a Lobby that a new Client has joined")]
14 | public sealed class OPCODE_DATA_LOBBY_ENTERROOM : IOpCodeHandler
15 | {
16 | private readonly ILobbyChatService lobbyChatService;
17 | private readonly ILogger logger;
18 |
19 | public OPCODE_DATA_LOBBY_ENTERROOM(ILobbyChatService lobbyChatService, ILogger logger)
20 | {
21 | this.lobbyChatService = lobbyChatService ?? throw new ArgumentNullException(nameof(lobbyChatService));
22 | this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
23 | }
24 |
25 | public Task> HandleIncomingRequestAsync(RequestContent request)
26 | {
27 | List responseList = new List();
28 | LobbyChatRoom room;
29 | var currentLobbyIndex = (short)swap16(BitConverter.ToUInt16(request.Data, 0));
30 | var currentLobbyType = swap16(BitConverter.ToUInt16(request.Data, 2));
31 | logger.Verbose("Lobby Room ID: {@room_index}", currentLobbyIndex);
32 | logger.Verbose("Lobby Type ID: {@lobbyType}", currentLobbyType);
33 |
34 | if (currentLobbyType == OpCodes.LOBBY_TYPE_GUILD) //Guild Room
35 | {
36 | //TODO add Guild Specific Code
37 | room = lobbyChatService.GetOrAddLobby((ushort)currentLobbyIndex, "Guild Room", OpCodes.LOBBY_TYPE_GUILD, out var _);
38 | }
39 | else
40 | {
41 | lobbyChatService.TryGetLobby((ushort)currentLobbyIndex, out room);
42 | }
43 |
44 | responseList.Add(request.CreateResponse(OpCodes.OPCODE_DATA_LOBBY_ENTERROOM_OK, BitConverter.GetBytes(swap16((ushort)room.Clients.Count))));
45 | responseList.AddRange(room.ClientJoinedLobbyPacketHandler(request.Client,request));
46 | logger.Information("Client #{0} has joined Lobby {1}. There are now {2} client(s) in the room", request.Client.ClientIndex, room.Name, room.Clients.Count );
47 | return Task.FromResult>(responseList);
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/Ranking/OPCODE_RANKING_VIEW_ALL.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Threading.Tasks;
4 | using FragmentNetslumServer.Entities.Attributes;
5 | using FragmentNetslumServer.Services;
6 | using FragmentNetslumServer.Services.Interfaces;
7 |
8 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.Ranking
9 | {
10 | [OpCodeData(OpCodes.OPCODE_RANKING_VIEW_ALL)]
11 | public sealed class OPCODE_RANKING_VIEW_ALL : IOpCodeHandler
12 | {
13 | private readonly IRankingManagementService _rankingManagementService;
14 |
15 | public OPCODE_RANKING_VIEW_ALL(IRankingManagementService rankingManagementService)
16 | {
17 | _rankingManagementService = rankingManagementService;
18 | }
19 |
20 | public Task> HandleIncomingRequestAsync(RequestContent request)
21 | {
22 | List responseContents = new List();
23 | var rankingArgs = (BitConverter.ToUInt16(request.Data, 0).Swap());
24 | if (rankingArgs == 0) // get the first ranking page
25 | {
26 | var rankCategoryList = _rankingManagementService.GetRankingCategory();
27 |
28 | responseContents.Add(request.CreateResponse(0x7833,
29 | BitConverter.GetBytes(((ushort)rankCategoryList.Count).Swap())));
30 |
31 | foreach (var category in rankCategoryList)
32 | {
33 | responseContents.Add(request.CreateResponse(0x7835, category));
34 | }
35 | }
36 | else if (rankingArgs >= 8) // get class List
37 | {
38 | request.Client._rankingCategoryID = rankingArgs;
39 | var rankClassList = Extensions.GetClassList();
40 | responseContents.Add(request.CreateResponse(0x7833, BitConverter.GetBytes(((ushort)rankClassList.Count).Swap())));
41 | foreach (var category in rankClassList)
42 | {
43 | responseContents.Add(request.CreateResponse(0x7835, category));
44 | }
45 | }
46 | else
47 | {
48 | var playerRankingList = _rankingManagementService.GetPlayerRanking(request.Client._rankingCategoryID, rankingArgs);
49 | responseContents.Add(request.CreateResponse(0x7836, BitConverter.GetBytes(((uint)playerRankingList.Count).Swap())));
50 | foreach (var player in playerRankingList)
51 | {
52 | responseContents.Add(request.CreateResponse(0x7837, player));
53 | }
54 | }
55 |
56 | return Task.FromResult>(responseContents);
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/FragmentNetslumServer.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.30406.217
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FragmentNetslumServer", "FragmentNetslumServer\FragmentNetslumServer.csproj", "{E24F2253-4792-4DB6-AA71-7262CA891A3C}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FragmentNetslumServerLauncher", "FragmentNetslumServerLauncher\FragmentNetslumServerLauncher.csproj", "{F1360378-9ED1-46D6-AB60-1CF4F1B79F96}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FragmentNetslumServerWebApi", "FragmentNetslumServerWebApi\FragmentNetslumServerWebApi.csproj", "{A6BB141E-02F4-46EB-82E4-B7A02D86F1E8}"
11 | EndProject
12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FragmentNetslumServerPubSub", "FragmentNetslumServerPubSub\FragmentNetslumServerPubSub.csproj", "{B19DBDC7-2568-4E63-A140-F6E0AB9BB5E5}"
13 | EndProject
14 | Global
15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
16 | Debug|Any CPU = Debug|Any CPU
17 | Release|Any CPU = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
20 | {E24F2253-4792-4DB6-AA71-7262CA891A3C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {E24F2253-4792-4DB6-AA71-7262CA891A3C}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {E24F2253-4792-4DB6-AA71-7262CA891A3C}.Release|Any CPU.ActiveCfg = Release|Any CPU
23 | {E24F2253-4792-4DB6-AA71-7262CA891A3C}.Release|Any CPU.Build.0 = Release|Any CPU
24 | {F1360378-9ED1-46D6-AB60-1CF4F1B79F96}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
25 | {F1360378-9ED1-46D6-AB60-1CF4F1B79F96}.Debug|Any CPU.Build.0 = Debug|Any CPU
26 | {F1360378-9ED1-46D6-AB60-1CF4F1B79F96}.Release|Any CPU.ActiveCfg = Release|Any CPU
27 | {F1360378-9ED1-46D6-AB60-1CF4F1B79F96}.Release|Any CPU.Build.0 = Release|Any CPU
28 | {A6BB141E-02F4-46EB-82E4-B7A02D86F1E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
29 | {A6BB141E-02F4-46EB-82E4-B7A02D86F1E8}.Debug|Any CPU.Build.0 = Debug|Any CPU
30 | {A6BB141E-02F4-46EB-82E4-B7A02D86F1E8}.Release|Any CPU.ActiveCfg = Release|Any CPU
31 | {A6BB141E-02F4-46EB-82E4-B7A02D86F1E8}.Release|Any CPU.Build.0 = Release|Any CPU
32 | {B19DBDC7-2568-4E63-A140-F6E0AB9BB5E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
33 | {B19DBDC7-2568-4E63-A140-F6E0AB9BB5E5}.Debug|Any CPU.Build.0 = Debug|Any CPU
34 | {B19DBDC7-2568-4E63-A140-F6E0AB9BB5E5}.Release|Any CPU.ActiveCfg = Release|Any CPU
35 | {B19DBDC7-2568-4E63-A140-F6E0AB9BB5E5}.Release|Any CPU.Build.0 = Release|Any CPU
36 | EndGlobalSection
37 | GlobalSection(SolutionProperties) = preSolution
38 | HideSolutionNode = FALSE
39 | EndGlobalSection
40 | GlobalSection(ExtensibilityGlobals) = postSolution
41 | SolutionGuid = {2CCF6F06-C7E8-47F1-A7C5-39C6ED7CC7D7}
42 | EndGlobalSection
43 | EndGlobal
44 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/News/OPCODE_DATA_NEWS_GETMENU.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using FragmentNetslumServer.Entities.Attributes;
7 | using FragmentNetslumServer.Models;
8 | using FragmentNetslumServer.Services;
9 | using FragmentNetslumServer.Services.Interfaces;
10 |
11 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.News
12 | {
13 | [OpCodeData(OpCodes.OPCODE_DATA_NEWS_GETMENU) , Description("Get List of Articles")]
14 | public sealed class OPCODE_DATA_NEWS_GETMENU : IOpCodeHandler
15 | {
16 | private readonly INewsService _newsService;
17 | private readonly Encoding _encoding;
18 |
19 | public OPCODE_DATA_NEWS_GETMENU(INewsService newsService)
20 | {
21 | _newsService = newsService;
22 | Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
23 | _encoding = Encoding.GetEncoding("Shift-JIS");
24 | }
25 |
26 | public async Task> HandleIncomingRequestAsync(RequestContent request)
27 | {
28 | var u = BitConverter.ToUInt16(request.Data, 0).Swap(); // Get CategoryID
29 |
30 | // we are skipping category listing and we will list only the articles , but either way here is the code for it
31 |
32 | // Ignore categories only send the article list
33 | /*if (u == 0)
34 | {
35 | ushort count = 1;
36 | await SendDataPacket(OpCodes.OPCODE_DATA_NEWS_CATEGORYLIST, BitConverter.GetBytes(swap16(count)));
37 |
38 | ushort catID = 1;
39 | string catName = "Testing Category";
40 | using MemoryStream memoryStream = new MemoryStream();
41 | await memoryStream.WriteAsync(BitConverter.GetBytes(swap16(catID)));
42 | await memoryStream.WriteAsync(encoding.GetBytes(catName + char.MinValue));
43 | await SendDataPacket(OpCodes.OPCODE_DATA_NEWS_ENTRY_CATEGORY, memoryStream.ToArray());
44 | } else*/
45 | List listOfResponse = new List();
46 |
47 | // send articles
48 | ushort count = (ushort)(await _newsService.GetNewsArticles()).Count;
49 | listOfResponse.Add(request.CreateResponse(OpCodes.OPCODE_DATA_NEWS_ARTICLELIST,
50 | BitConverter.GetBytes((count.Swap()))));
51 |
52 | foreach (NewsSectionModel article in
53 | (await _newsService.GetNewsArticles(
54 | _encoding.GetString(request.Client
55 | .save_id)))) // get the articles data and set the isNew flag based on the saveID
56 | {
57 | listOfResponse.Add(request.CreateResponse(OpCodes.OPCODE_DATA_NEWS_ENTRY_ARTICLE,
58 | article.ArticleByteArray));
59 | }
60 |
61 | return listOfResponse;
62 | }
63 | }
64 | }
--------------------------------------------------------------------------------
/FragmentNetslumServer/Models/Mapping/CharacterRepositoryModel.hbm.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/RequestContent.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using System;
3 | using static FragmentNetslumServer.Services.Extensions;
4 |
5 | namespace FragmentNetslumServer.Entities
6 | {
7 |
8 | ///
9 | /// Defines a particular request that was sent via a connected client
10 | ///
11 | public sealed class RequestContent
12 | {
13 |
14 | ///
15 | /// Gets the that has submitted this request
16 | ///
17 | public GameClientAsync Client { get; private set; }
18 |
19 | ///
20 | /// Gets the OpCode that was submitted by the
21 | ///
22 | public ushort OpCode { get; private set; }
23 |
24 | ///
25 | /// Gets the optional Data OpCode that was submitted by the
26 | ///
27 | ///
28 | /// If does not equal (or 0x30) then this will be NULL
29 | ///
30 | public ushort? DataOpCode { get; private set; }
31 |
32 | ///
33 | /// Gets the data payload that was submitted by the
34 | ///
35 | public byte[] Data { get; private set; }
36 |
37 |
38 |
39 | ///
40 | /// Creates a new instance for the given client and packet
41 | ///
42 | /// The that has received a packet of information
43 | /// The of data that was received
44 | public RequestContent(
45 | GameClientAsync gameClient,
46 | PacketAsync packet)
47 | {
48 | this.Client = gameClient;
49 | this.OpCode = packet.Code;
50 | this.Data = packet.Data;
51 |
52 | if (this.OpCode == OpCodes.OPCODE_DATA)
53 | {
54 |
55 | // For the DATA opcode, we have some special handling
56 | // that needs to occur now. This additional logic is
57 | // responsible for the "data opcode" and also properly
58 | // decoding the data payload
59 | var data = packet.Data;
60 | if (Client != null) // Client can be NULL if we're just asking 'can we handle this'
61 | {
62 | Client.SetClientSequenceNumber(swap16(BitConverter.ToUInt16(data, 2)));
63 | }
64 | var arglen = (ushort)(swap16(BitConverter.ToUInt16(data, 6)) - 2);
65 | var code = swap16(BitConverter.ToUInt16(data, 8));
66 | var m = new MemoryStream();
67 | m.Write(data, 10, arglen);
68 |
69 | this.DataOpCode = code;
70 | this.Data = m.ToArray();
71 | }
72 |
73 | }
74 |
75 | ///
76 | /// A shortcut method to create a response
77 | ///
78 | /// The OpCode to respond with
79 | /// The data to transmit
80 | /// An optional checksum of the data
81 | ///
82 | public ResponseContent CreateResponse(
83 | ushort responseOpCode,
84 | byte[] responseData,
85 | uint? checksum = null)
86 | {
87 | return new ResponseContent(this, responseOpCode, responseData, checksum);
88 | }
89 |
90 | }
91 |
92 | }
93 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/OPCODE_DATA_NORESPONSE.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using FragmentNetslumServer.Entities.Attributes;
4 | using System.ComponentModel;
5 | using System.IO;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 | using FragmentNetslumServer.Services;
9 | using FragmentNetslumServer.Services.Interfaces;
10 | using Serilog;
11 |
12 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data
13 | {
14 | [OpCodeData(OpCodes.OPCODE_DATA_PING),
15 | OpCodeData(OpCodes.OPCODE_DATA_LOBBY_FAVORITES_AS_INQUIRY),
16 | OpCodeData(OpCodes.OPCODE_DATA_AS_PUBLISH_DETAILS3),
17 | OpCodeData(OpCodes.OPCODE_DATA_AS_PUBLISH_DETAILS4),
18 | OpCodeData(OpCodes.OPCODE_DATA_AS_PUBLISH_DETAILS6),
19 | Description("Provides no response to DATA OpCodes")]
20 | public sealed class OPCODE_DATA_NORESPONSE : NoResponseOpCodeHandler
21 | {
22 | private readonly ILogger logger;
23 | private readonly IClientProviderService clientProviderService;
24 |
25 | public OPCODE_DATA_NORESPONSE(ILogger logger, IClientProviderService clientProviderService)
26 | {
27 | this.logger = logger;
28 | this.clientProviderService = clientProviderService;
29 | }
30 |
31 | public override async Task> HandleIncomingRequestAsync(RequestContent request)
32 | {
33 | var responses = new List();
34 | if (request.DataOpCode == OpCodes.OPCODE_DATA_LOBBY_FAVORITES_AS_INQUIRY)
35 | {
36 | logger.LogData(request.Data,request.OpCode,request.Client.ClientIndex,"Get Bookmark",0,0);
37 | var encoding = Encoding.GetEncoding("Shift-JIS");
38 | var areaServers = clientProviderService.AreaServers;
39 | responses.Add(request.CreateResponse(0x7859, BitConverter.GetBytes(((ushort)areaServers.Count).Swap())));
40 |
41 | // Now we need to send all the area servers to the client
42 | foreach (var client in areaServers)
43 | {
44 | var m = new MemoryStream();
45 | m.WriteByte(0);
46 | if (client.ipEndPoint.Address == request.Client.ipEndPoint.Address)
47 | await m.WriteAsync(client.ipdata, 0, 6);
48 | else
49 | await m.WriteAsync(client.externalIPAddress, 0, 6);
50 |
51 | var buff = BitConverter.GetBytes((client.as_usernum.Swap()));
52 | int pos = 0;
53 | while (client.publish_data_1[pos++] != 0) ;
54 | pos += 4;
55 | client.publish_data_1[pos++] = buff[0];
56 | client.publish_data_1[pos++] = buff[1];
57 | await m.WriteAsync(client.publish_data_1, 0, client.publish_data_1.Length);
58 | while (m.Length < 45) m.WriteByte(0);
59 |
60 | var usr = encoding.GetString(BitConverter.GetBytes((client.as_usernum.Swap())));
61 | var pup1 = encoding.GetString(client.publish_data_1);
62 | var pup2 = encoding.GetString(client.publish_data_2);
63 | logger.Debug($"AREA SERVER: {pup1}; {pup2}; {usr}", pup1, pup2, usr);
64 |
65 | responses.Add(request.CreateResponse(0x786A, m.ToArray()));
66 | }
67 |
68 | return responses;
69 | }
70 |
71 |
72 | else
73 | {
74 | return await base.HandleIncomingRequestAsync(request);
75 | }
76 |
77 |
78 | }
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Services/Interfaces/ILobbyChatService.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.ObjectModel;
2 | using System.Threading.Tasks;
3 | using FragmentNetslumServer.Entities;
4 |
5 | namespace FragmentNetslumServer.Services.Interfaces
6 | {
7 |
8 | ///
9 | /// Defines how the lobby service system should operate
10 | ///
11 | public interface ILobbyChatService: IBaseService
12 | {
13 |
14 | ///
15 | /// Gets a collection of currently created Lobbies
16 | ///
17 | ReadOnlyDictionary Lobbies { get; }
18 |
19 | ///
20 | /// Gets the main lobby room
21 | ///
22 | LobbyChatRoom Main { get; }
23 |
24 | ///
25 | /// Returns an instance of
26 | ///
27 | /// The unique Lobby ID
28 | /// The name of the lobby to create
29 | /// The type of lobby to create
30 | /// Indicates if the supplied already existed
31 | ///
32 | /// For more information on the correct TYPE to pass in, take a look in
33 | LobbyChatRoom GetOrAddLobby(ushort lobbyId, string lobbyName, ushort lobbyType, out bool isCreated);
34 |
35 | ///
36 | /// Attempts to retrieve a
37 | ///
38 | /// The unique Lobby ID
39 | /// The found, if applicable
40 | ///
41 | bool TryGetLobby(ushort lobbyId, out LobbyChatRoom lobbyChatRoom);
42 |
43 | ///
44 | /// Announces that a client has left a particular
45 | ///
46 | ///
47 | /// The identifier of the client
48 | /// A Task that intends to complete the departure announcement
49 | Task AnnounceRoomDeparture(LobbyChatRoom lobbyChatRoom, uint clientIndex);
50 |
51 | ///
52 | /// Announces that a client has left a particular
53 | ///
54 | /// The lobby identifier
55 | /// The identifier of the client
56 | /// A Task that intends to complete the departure announcement
57 | Task AnnounceRoomDeparture(ushort lobbyId, uint clientIndex);
58 |
59 | ///
60 | /// Attempts to locate the lobby where the client is currently at
61 | ///
62 | /// The index of the client
63 | /// The discovered
64 | /// True or false depending on whether or not the lobby was found
65 | bool TryFindLobby(uint clientIndex, out LobbyChatRoom lobbyChatRoom);
66 |
67 | ///
68 | /// Attempts to locate the lobby where the client is currently at
69 | ///
70 | /// The game client reference
71 | /// The discovered
72 | /// True or false depending on whether or not the lobby was found
73 | bool TryFindLobby(GameClientAsync gameClientAsync, out LobbyChatRoom lobbyChatRoom);
74 |
75 | }
76 |
77 | }
--------------------------------------------------------------------------------
/FragmentNetslumServer/Services/GameClientService.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Collections.ObjectModel;
4 | using System.Linq;
5 | using System.Net.Sockets;
6 | using FragmentNetslumServer.Entities;
7 | using FragmentNetslumServer.Enumerations;
8 | using FragmentNetslumServer.Services.Interfaces;
9 | using Microsoft.Extensions.DependencyInjection;
10 | using Serilog;
11 |
12 | namespace FragmentNetslumServer.Services
13 | {
14 | public sealed class GameClientService : IClientProviderService
15 | {
16 |
17 | private readonly List clients;
18 | private readonly ILogger logger;
19 | private readonly ILobbyChatService lobbyChatService;
20 | private readonly IServiceProvider provider;
21 |
22 | public ReadOnlyCollection Clients => clients.AsReadOnly();
23 |
24 | public ReadOnlyCollection AreaServers => clients.Where(c => c.isAreaServer).ToList().AsReadOnly();
25 |
26 | public string ServiceName => "Game Client Service";
27 |
28 | public ServiceStatusEnum ServiceStatus { get; private set; }
29 |
30 |
31 |
32 | public GameClientService(ILogger logger,ILobbyChatService lobbyChatService ,IServiceProvider provider)
33 | {
34 | this.logger = logger;
35 | this.lobbyChatService = lobbyChatService;
36 | this.provider = provider;
37 | this.clients = new List();
38 | this.ServiceStatus = ServiceStatusEnum.Active;
39 | }
40 |
41 |
42 |
43 | public void AddClient(TcpClient client, uint clientId)
44 | {
45 | var gameClient = provider.GetRequiredService();
46 | gameClient.InitializeClient(clientId, client);
47 | this.AddClient(gameClient);
48 | }
49 |
50 | public void AddClient(GameClientAsync client)
51 | {
52 | this.logger.Information($"Client {client.ClientIndex} has connected");
53 | client.OnGameClientDisconnected += Client_OnGameClientDisconnected;
54 | this.clients.Add(client);
55 | this.logger.Information($"There are {clients.Count:N0} connected clients");
56 |
57 | }
58 |
59 | public void RemoveClient(uint index) => this.RemoveClient(clients.Find(c => c.ClientIndex == (int)index));
60 |
61 | public void RemoveClient(GameClientAsync client)
62 | {
63 | this.logger.Information($"Client {client.ClientIndex} has disconnected");
64 | this.clients.Remove(client);
65 | this.logger.Information($"There are {clients.Count:N0} connected clients");
66 | }
67 |
68 | public bool TryGetClient(uint index, out GameClientAsync client)
69 | {
70 | client = null;
71 | foreach (var c in clients)
72 | {
73 | if (c.ClientIndex == index)
74 | {
75 | client = c;
76 | return true;
77 | }
78 | }
79 | return false;
80 | }
81 |
82 | private void Client_OnGameClientDisconnected(object sender, EventArgs e)
83 | {
84 | if (!(sender is GameClientAsync client)) return;
85 | RemoveClient(client);
86 | if (client.PlayerID != 0)
87 | {
88 | DBAccess.getInstance().setPlayerAsOffline(client.PlayerID);
89 | }
90 | if (!client.IsAreaServer && lobbyChatService.TryFindLobby(client, out var lobby))
91 | {
92 | lobbyChatService.AnnounceRoomDeparture(lobby, (uint)client.ClientIndex);
93 | }
94 | client.OnGameClientDisconnected -= Client_OnGameClientDisconnected;
95 | }
96 |
97 | }
98 |
99 | }
100 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/FragmentNetslumServer.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net6.0
4 | Library
5 |
6 |
7 | false
8 | FragmentNetslumServer
9 | FragmentNetslumServer
10 |
11 |
12 | TRACE;USE_HYBRID_APPROACH
13 |
14 |
15 | TRACE;USE_HYBRID_APPROACH
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
71 |
72 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Services/LobbyChatService.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Concurrent;
2 | using System.Collections.ObjectModel;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using FragmentNetslumServer.Entities;
6 | using FragmentNetslumServer.Enumerations;
7 | using FragmentNetslumServer.Services.Interfaces;
8 | using Serilog;
9 |
10 | namespace FragmentNetslumServer.Services
11 | {
12 | public sealed class LobbyChatService : ILobbyChatService
13 | {
14 |
15 | private readonly ConcurrentDictionary lobbies;
16 | private readonly ILogger logger;
17 | private LobbyChatRoom mainLobby;
18 |
19 | public ReadOnlyDictionary Lobbies => new ReadOnlyDictionary(lobbies);
20 |
21 | public LobbyChatRoom Main => mainLobby;
22 |
23 | public string ServiceName => "Lobby Service";
24 |
25 | public ServiceStatusEnum ServiceStatus { get; private set; } = ServiceStatusEnum.Inactive;
26 |
27 | public LobbyChatService(ILogger logger)
28 | {
29 | this.logger = logger;
30 | this.lobbies = new ConcurrentDictionary();
31 | this.ServiceStatus = ServiceStatusEnum.Active;
32 | this.mainLobby = GetOrAddLobby(1, "Main Lobby", OpCodes.LOBBY_TYPE_MAIN, out var _);
33 | }
34 |
35 |
36 | public LobbyChatRoom GetOrAddLobby(ushort lobbyId, string lobbyName, ushort lobbyType, out bool isCreated)
37 | {
38 | var localCreated = false;
39 | this.logger.Debug("Looking for a Lobby of ID {@lobbyId}", lobbyId);
40 | var lobby = lobbies.GetOrAdd(lobbyId, _ =>
41 | {
42 | localCreated = true;
43 | this.logger.Debug("Lobby {@lobbyId} does not exist. Creating a new Lobby named '{@lobbyName}'", lobbyId, lobbyName);
44 | return new LobbyChatRoom(lobbyName, lobbyId, lobbyType);
45 | });
46 | isCreated = localCreated;
47 | return lobby;
48 | }
49 |
50 | public bool TryGetLobby(ushort lobbyId, out LobbyChatRoom lobbyChatRoom)
51 | {
52 | this.logger.Debug("Looking for a Lobby of ID {@lobbyId}", lobbyId);
53 | lobbyChatRoom = null;
54 | if (lobbies.ContainsKey(lobbyId))
55 | {
56 | lobbyChatRoom = lobbies[lobbyId];
57 | this.logger.Debug("Found Lobby ID {@lobbyId}", lobbyId);
58 | return true;
59 | }
60 | this.logger.Debug("Could not find {@lobbyId}", lobbyId);
61 | return false;
62 | }
63 |
64 | public async Task AnnounceRoomDeparture(LobbyChatRoom lobbyChatRoom, uint clientIndex)
65 | {
66 | logger.Debug("Client #{@clientIndex} is leaving their lobby", clientIndex);
67 | await lobbyChatRoom.ClientLeavingRoomAsync((int)clientIndex);
68 | logger.Debug($"Lobby '{lobbyChatRoom.Name}' now has {lobbyChatRoom.Clients.Count:N0} Users");
69 | await Task.Yield();
70 | }
71 |
72 | public async Task AnnounceRoomDeparture(ushort lobbyId, uint clientIndex)
73 | {
74 | if (TryGetLobby(lobbyId, out var lobby))
75 | {
76 | await AnnounceRoomDeparture(lobby, clientIndex);
77 | }
78 | }
79 |
80 | public bool TryFindLobby(uint clientIndex, out LobbyChatRoom lobbyChatRoom)
81 | {
82 | lobbyChatRoom = null;
83 | foreach(var lobby in Lobbies)
84 | {
85 | var lobbyId = lobby.Key;
86 | var lcr = lobby.Value;
87 | if (lcr.Clients.Any(c => c.ClientIndex == clientIndex))
88 | {
89 | lobbyChatRoom = lcr;
90 | return true;
91 | }
92 | }
93 | return false;
94 | }
95 |
96 | public bool TryFindLobby(GameClientAsync gameClientAsync, out LobbyChatRoom lobbyChatRoom)
97 | {
98 | return TryFindLobby((uint)gameClientAsync.ClientIndex, out lobbyChatRoom);
99 | }
100 | }
101 |
102 | }
103 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/OPCODE_DATA_REGISTER_CHAR.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services;
3 | using FragmentNetslumServer.Services.Interfaces;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Threading.Tasks;
7 | using static FragmentNetslumServer.Services.Extensions;
8 |
9 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data
10 | {
11 | [OpCodeData(OpCodes.OPCODE_DATA_REGISTER_CHAR)]
12 | public sealed class OPCODE_DATA_REGISTER_CHAR : IOpCodeHandler
13 | {
14 | private readonly IGuildManagementService guildManagementService;
15 |
16 | public OPCODE_DATA_REGISTER_CHAR(IGuildManagementService guildManagementService)
17 | {
18 | this.guildManagementService = guildManagementService;
19 | }
20 |
21 | public Task> HandleIncomingRequestAsync(RequestContent request)
22 | {
23 | request.Client._characterPlayerID = ExtractCharacterData(request.Client, request.Data);
24 | byte[] guildStatus = guildManagementService.GetPlayerGuild(request.Client._characterPlayerID);
25 | if (guildStatus[0] == 0x01)
26 | {
27 | request.Client.isGuildMaster = true;
28 | }
29 | request.Client._guildID = swap16(BitConverter.ToUInt16(guildStatus, 1));
30 | // The first byte is membership status: 0=none 1= master 2= member
31 | return Task.FromResult>(new[] { request.CreateResponse(OpCodes.OPCODE_DATA_REGISTER_CHAROK, guildStatus) });
32 | }
33 |
34 | uint ExtractCharacterData(GameClientAsync client, byte[] data)
35 | {
36 | client.save_slot = data[0];
37 | client.char_id = ReadByteString(data, 1);
38 | int pos = 1 + client.char_id.Length;
39 | client.char_name = ReadByteString(data, pos);
40 | pos += client.char_name.Length;
41 | client.char_class = data[pos++];
42 | client.char_level = swap16(BitConverter.ToUInt16(data, pos));
43 | pos += 2;
44 | client.greeting = ReadByteString(data, pos);
45 | pos += client.greeting.Length;
46 | client.char_model = swap32(BitConverter.ToUInt32(data, pos));
47 | pos += 5;
48 | client.char_HP = swap16(BitConverter.ToUInt16(data, pos));
49 | pos += 2;
50 | client.char_SP = swap16(BitConverter.ToUInt16(data, pos));
51 | pos += 2;
52 | client.char_GP = swap32(BitConverter.ToUInt32(data, pos));
53 | pos += 4;
54 | client.online_god_counter = swap16(BitConverter.ToUInt16(data, pos));
55 | pos += 2;
56 | client.offline_godcounter = swap16(BitConverter.ToUInt16(data, pos));
57 | pos += 2;
58 | client.goldCoinCount = swap16(BitConverter.ToUInt16(data, pos));
59 | pos += 2;
60 | client.silverCoinCount = swap16(BitConverter.ToUInt16(data, pos));
61 | pos += 2;
62 | client.bronzeCoinCount = swap16(BitConverter.ToUInt16(data, pos));
63 |
64 | client.classLetter = GetCharacterModelClass(client.char_model);
65 | client.modelNumber = GetCharacterModelNumber(client.char_model);
66 | client.modelType = GetCharacterModelType(client.char_model);
67 | client.colorCode = GetCharacterModelColorCode(client.char_model);
68 |
69 | client.charModelFile = "xf" + client.classLetter + client.modelNumber + client.modelType + "_" + client.colorCode;
70 | return DBAccess.getInstance().PlayerLogin(client);
71 | }
72 |
73 | static char GetCharacterModelClass(uint modelNumber)
74 | {
75 | char[] classLetters = { 't', 'b', 'h', 'a', 'l', 'w' };
76 | int index = (int)(modelNumber & 0x0F);
77 | return classLetters[index];
78 | }
79 |
80 | static int GetCharacterModelNumber(uint modelNumber)
81 | {
82 | return (int)(modelNumber >> 4 & 0x0F) + 1;
83 | }
84 |
85 | static char GetCharacterModelType(uint modelNumber)
86 | {
87 | char[] typeLetters = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i' };
88 | int index = (int)(modelNumber >> 12) & 0x0F;
89 | return typeLetters[index];
90 | }
91 |
92 | static string GetCharacterModelColorCode(uint modelNumber)
93 | {
94 | string[] colorCodes = { "rd", "bl", "yl", "gr", "br", "pp" };
95 | int index = (int)(modelNumber >> 8) & 0x0F;
96 | return colorCodes[index];
97 | }
98 |
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/FragmentNetslumServer/Entities/OpCodeHandlers/Data/Lobby/OPCODE_DATA_LOBBY_GETSERVERS_GETLIST.cs:
--------------------------------------------------------------------------------
1 | using FragmentNetslumServer.Entities.Attributes;
2 | using FragmentNetslumServer.Services.Interfaces;
3 | using Serilog;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.IO;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using static FragmentNetslumServer.Services.Extensions;
10 |
11 | namespace FragmentNetslumServer.Entities.OpCodeHandlers.Data.Lobby
12 | {
13 |
14 | [OpCodeData(OpCodes.OPCODE_DATA_LOBBY_GETSERVERS_GETLIST)]
15 | public sealed class OPCODE_DATA_LOBBY_GETSERVERS_GETLIST : IOpCodeHandler
16 | {
17 | private readonly ILogger logger;
18 | private readonly IClientProviderService clientProviderService;
19 |
20 | public OPCODE_DATA_LOBBY_GETSERVERS_GETLIST(ILogger logger, IClientProviderService clientProviderService)
21 | {
22 | this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
23 | this.clientProviderService = clientProviderService ?? throw new ArgumentNullException(nameof(clientProviderService));
24 | }
25 |
26 | public async Task> HandleIncomingRequestAsync(RequestContent request)
27 | {
28 | // Zero indicates "gimme the list of categories"
29 | var encoding = Encoding.GetEncoding("Shift-JIS");
30 | var responses = new List();
31 | if (request.Data[1] == 0)
32 | {
33 |
34 | logger.Information("Client #{@clientIndex} has requested the list of available categories for Area Server Selection", new { clientIndex = request.Client.ClientIndex });
35 |
36 | // Tell the game there's ONE category
37 | responses.Add(request.CreateResponse(OpCodes.OPCODE_DATA_LOBBY_GETSERVERS_CATEGORYLIST, new byte[] { 0x00, 0x01 }));
38 |
39 | // This is the category. This byte array translates to, basically, MAIN:
40 | // "\0\u0001MAIN\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ne"
41 | // Uses \u0001MAIN with the rest as padding, more than likely
42 | responses.Add(request.CreateResponse(OpCodes.OPCODE_DATA_LOBBY_GETSERVERS_ENTRY_CATEGORY,
43 | new byte[]
44 | {
45 | 0x00, 0x01, 0x4D, 0x41, 0x49, 0x4E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
46 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
47 | 0x00, 0x00, 0x00, 0x00, 0x6E, 0x65
48 | }));
49 | }
50 | else
51 | {
52 | logger.Information("Client #{@clientIndex} has requested the list of area servers for the MAIN category", new { clientIndex = request.Client.ClientIndex });
53 |
54 | // We don't care about categories any longer. We're here for the list of servers
55 | var areaServers = clientProviderService.AreaServers;
56 |
57 | // Tell the client how many area servers we got
58 | responses.Add(request.CreateResponse(OpCodes.OPCODE_DATA_LOBBY_GETSERVERS_SERVERLIST, BitConverter.GetBytes(swap16((ushort)areaServers.Count))));
59 |
60 | // Now we need to send all the area servers to the client
61 | foreach (var client in areaServers)
62 | {
63 | var m = new MemoryStream();
64 | m.WriteByte(0);
65 | if (client.ipEndPoint.Address == request.Client.ipEndPoint.Address)
66 | await m.WriteAsync(client.ipdata, 0, 6);
67 | else
68 | await m.WriteAsync(client.externalIPAddress, 0, 6);
69 |
70 | var buff = BitConverter.GetBytes(swap16(client.as_usernum));
71 | int pos = 0;
72 | while (client.publish_data_1[pos++] != 0) ;
73 | pos += 4;
74 | client.publish_data_1[pos++] = buff[0];
75 | client.publish_data_1[pos++] = buff[1];
76 | await m.WriteAsync(client.publish_data_1, 0, client.publish_data_1.Length);
77 | while (m.Length < 45) m.WriteByte(0);
78 |
79 | var usr = encoding.GetString(BitConverter.GetBytes(swap16(client.as_usernum)));
80 | var pup1 = encoding.GetString(client.publish_data_1);
81 | var pup2 = encoding.GetString(client.publish_data_2);
82 | logger.Debug($"AREA SERVER: {pup1}; {pup2}; {usr}", pup1, pup2, usr);
83 |
84 | responses.Add(request.CreateResponse(OpCodes.OPCODE_DATA_LOBBY_GETSERVERS_ENTRY_SERVER, m.ToArray()));
85 | }
86 |
87 | // Shorten the TTL / ping timer so we can detect more
88 | // quickly when a player disconnects and hops over to an area server.
89 | // pingTimer.Interval = EnhancedPingTimeout.TotalMilliseconds;
90 |
91 | }
92 | return responses;
93 | }
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/FragmentNetslumServerWebApi/Models/PlayerModel.cs:
--------------------------------------------------------------------------------
1 | using System.Text;
2 | using FragmentNetslumServer.Entities;
3 | using FragmentNetslumServer.Models;
4 |
5 | namespace FragmentNetslumServerWebApi.Models
6 | {
7 | public class PlayerModel
8 | {
9 | public int save_slot;
10 | public string save_id;
11 | public string char_id;
12 | public string char_name;
13 | public string char_class;
14 | public int char_level;
15 | public string greeting;
16 | public int char_model;
17 | public string charModelFile;
18 | public int char_HP;
19 | public int char_SP;
20 | public int char_GP;
21 | public int online_god_counter;
22 | public int offline_godCounter;
23 |
24 | public static PlayerModel ConvertData(GameClientAsync client)
25 | {
26 | PlayerModel model = new PlayerModel();
27 |
28 | /*
29 | *
30 | *Console.WriteLine("Character Date \n save_slot "+ save_slot + "\n char_id " +Encoding.ASCII.GetString(save_id) + " \n char_name " + Encoding.ASCII.GetString(char_id) +
31 | "\n char_class " + char_class + "\n char_level " + char_level + "\n greeting "+ Encoding.ASCII.GetString(greeting) +"\n charmodel " +char_model + "\n char_hp " + char_HP+
32 | "\n char_sp " + char_SP + "\n char_gp " + char_GP + "\n onlien god counter "+ online_god_counter + "\n offline god counter "+ offline_godcounter +"\n\n\n\n full byte araray " + BitConverter.ToString(data));
33 | *
34 | */
35 |
36 | if (null == client.save_id || null == client.char_id ||
37 | null == client.char_name || null == client.greeting)
38 | return null;
39 |
40 | Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
41 |
42 | model.save_slot = client.save_slot;
43 | model.save_id = Encoding.GetEncoding("Shift-JIS").GetString(client.save_id,0,client.save_id.Length-1);
44 | model.char_id = Encoding.GetEncoding("Shift-JIS").GetString(client.char_id,0,client.char_id.Length-1);
45 | model.char_name = Encoding.GetEncoding("Shift-JIS").GetString(client.char_name,0,client.char_name.Length-1);
46 |
47 | PlayerClass playerClass = (PlayerClass) client.char_class;
48 | model.char_class = playerClass.ToString();
49 | model.char_level = client.char_level;
50 |
51 | model.greeting = Encoding.GetEncoding("Shift-JIS").GetString(client.greeting,0,client.greeting.Length-1);
52 | model.char_model = (int) client.char_model;
53 | model.char_HP = client.char_HP;
54 | model.char_SP = client.char_SP;
55 | model.char_GP = (int) client.char_GP;
56 | model.online_god_counter = client.online_god_counter;
57 | model.offline_godCounter = client.offline_godcounter;
58 | model.charModelFile = client.charModelFile;
59 |
60 | return model;
61 | }
62 |
63 | public int SaveSlot
64 | {
65 | get => save_slot;
66 | set => save_slot = value;
67 | }
68 |
69 | public string SaveId
70 | {
71 | get => save_id;
72 | set => save_id = value;
73 | }
74 |
75 | public string CharId
76 | {
77 | get => char_id;
78 | set => char_id = value;
79 | }
80 |
81 | public string CharName
82 | {
83 | get => char_name;
84 | set => char_name = value;
85 | }
86 |
87 | public string CharClass
88 | {
89 | get => char_class;
90 | set => char_class = value;
91 | }
92 |
93 | public int CharLevel
94 | {
95 | get => char_level;
96 | set => char_level = value;
97 | }
98 |
99 | public string Greeting
100 | {
101 | get => greeting;
102 | set => greeting = value;
103 | }
104 |
105 | public int CharModel
106 | {
107 | get => char_model;
108 | set => char_model = value;
109 | }
110 |
111 | public int CharHp
112 | {
113 | get => char_HP;
114 | set => char_HP = value;
115 | }
116 |
117 | public int CharSp
118 | {
119 | get => char_SP;
120 | set => char_SP = value;
121 | }
122 |
123 | public int CharGp
124 | {
125 | get => char_GP;
126 | set => char_GP = value;
127 | }
128 |
129 | public int OnlineGodCounter
130 | {
131 | get => online_god_counter;
132 | set => online_god_counter = value;
133 | }
134 |
135 | public int OfflineGodCounter
136 | {
137 | get => offline_godCounter;
138 | set => offline_godCounter = value;
139 | }
140 |
141 | public string CharModelFile
142 | {
143 | get => charModelFile;
144 | set => charModelFile = value;
145 | }
146 | }
147 |
148 |
149 | }
--------------------------------------------------------------------------------