├── .editorconfig ├── .gitattributes ├── .github ├── CODEOWNERS ├── dependabot.yml └── workflows │ └── test-build.yml ├── .gitignore ├── .run └── Fragment.NetSlum.Server.run.xml ├── Dockerfile ├── Fragment.NetSlum.sln ├── LICENSE ├── README.md ├── docker-compose.yml ├── docs ├── about │ ├── coding-style.md │ ├── contributing.md │ ├── license.md │ └── project-overview.md ├── hosting │ └── area-server-hosting.md ├── index.md ├── networking │ ├── encoding.md │ ├── framing.md │ └── index.md └── static │ ├── fragment.jpg │ └── project_diagram.png ├── mkdocs.yml ├── src ├── Fragment.NetSlum.Console │ ├── Commands │ │ ├── MigrateBbsCommand.cs │ │ ├── MigrateGuildShopCommand.cs │ │ ├── MigrateGuildsCommand.cs │ │ ├── MigrateMailCommand.cs │ │ └── MigratePlayersCommand.cs │ ├── DependencyInjection │ │ ├── TypeRegistrar.cs │ │ └── TypeResolver.cs │ ├── Fragment.NetSlum.Console.csproj │ └── Program.cs ├── Fragment.NetSlum.Core │ ├── Buffers │ │ ├── MemoryWriter.cs │ │ └── SpanReader.cs │ ├── CommandBus │ │ ├── Contracts │ │ │ ├── Commands │ │ │ │ ├── CommandHandler.cs │ │ │ │ ├── ICommand.cs │ │ │ │ └── ICommandHandler.cs │ │ │ ├── Events │ │ │ │ ├── EventHandler.cs │ │ │ │ ├── IEvent.cs │ │ │ │ └── IEventHandler.cs │ │ │ └── Queries │ │ │ │ ├── IQuery.cs │ │ │ │ ├── IQueryHandler.cs │ │ │ │ └── QueryHandler.cs │ │ ├── ICommandBus.cs │ │ └── MediatorCommandBus.cs │ ├── Constants │ │ ├── CharacterClass.cs │ │ ├── CharacterColor.cs │ │ ├── CharacterRanks.cs │ │ ├── ChatLobbyStatus.cs │ │ ├── ChatLobbyType.cs │ │ └── GuildStatus.cs │ ├── DependencyInjection │ │ └── IScopeable.cs │ ├── Extensions │ │ ├── CharacterExtensions.cs │ │ ├── DataExtensions.cs │ │ ├── DateExtensions.cs │ │ ├── IpAddressExtensions.cs │ │ ├── ServiceCollectionExtensions.cs │ │ └── StringExtensions.cs │ ├── Fragment.NetSlum.Core.csproj │ └── Models │ │ ├── CharacterInfo.cs │ │ └── ImageInfo.cs ├── Fragment.NetSlum.Networking │ ├── Attributes │ │ └── FragmentPacket.cs │ ├── Commands │ │ ├── Accounts │ │ │ └── RegisterPlayerAccountCommand.cs │ │ ├── Characters │ │ │ └── RegisterCharacterCommand.cs │ │ └── News │ │ │ └── MarkNewsArticleReadCommand.cs │ ├── Constants │ │ ├── MessageType.cs │ │ └── OpCodes.cs │ ├── Crypto │ │ ├── BlowfishProvider.cs │ │ └── CryptoHandler.cs │ ├── Entrypoint.cs │ ├── Events │ │ └── CharacterLoggedInEvent.cs │ ├── Extensions │ │ ├── PacketExtensions.cs │ │ └── ServiceCollectionExtensions.cs │ ├── Fragment.NetSlum.Networking.csproj │ ├── Messaging │ │ ├── FragmentPacketHandler.cs │ │ ├── IPacketHandler.cs │ │ └── PacketCache.cs │ ├── Models │ │ ├── AreaServerInformation.cs │ │ ├── ChatLobbyModel.cs │ │ └── ChatLobbyPlayer.cs │ ├── Objects │ │ └── FragmentMessage.cs │ ├── Packets │ │ ├── Request │ │ │ ├── AreaServer │ │ │ │ ├── AreaServerDateTimeRequest.cs │ │ │ │ ├── AreaServerFavoritesRequest.cs │ │ │ │ ├── AreaServerIPAddressPortRequest.cs │ │ │ │ ├── AreaServerPublishDetailsRequest.cs │ │ │ │ ├── AreaServerPublishRequest.cs │ │ │ │ ├── AreaServerUpdateStatusRequest.cs │ │ │ │ └── AreaServerUpdateUserCountRequest.cs │ │ │ ├── Articles │ │ │ │ ├── ArticleCheckRequest.cs │ │ │ │ ├── GetNewsArticlesRequest.cs │ │ │ │ └── GetNewsPostRequest.cs │ │ │ ├── BBS │ │ │ │ ├── CheckCreateBBSThreadRequest.cs │ │ │ │ ├── CreateBBSPostRequest.cs │ │ │ │ ├── GetBBSMenuRequest.cs │ │ │ │ ├── GetBBSPostContent.cs │ │ │ │ ├── GetBBSThreadDetailsRequest.cs │ │ │ │ └── GetBBSUpdatesRequest.cs │ │ │ ├── BaseRequest.cs │ │ │ ├── Character │ │ │ │ ├── RegisterCharacterRequest.cs │ │ │ │ ├── Select2CharacterRequest.cs │ │ │ │ ├── SelectCharacterRequest.cs │ │ │ │ └── UnregisterCharacterRequest.cs │ │ │ ├── ChatLobby │ │ │ │ ├── ChatLobbyEnterRoomRequest.cs │ │ │ │ ├── ChatLobbyGetMenuRequest.cs │ │ │ │ ├── ChatLobbyStatusUpdateRequest.cs │ │ │ │ ├── CreateLobbyChatroomRequest.cs │ │ │ │ ├── GetLobbyChatroomListRequest.cs │ │ │ │ ├── GetLobbyServerListRequest.cs │ │ │ │ ├── GetLobbyServersExitRequest.cs │ │ │ │ ├── GetLobbyServersRequest.cs │ │ │ │ ├── LobbyEventRequest.cs │ │ │ │ └── LobbyExitRoomRequest.cs │ │ │ ├── Guilds │ │ │ │ ├── CreateGuildRequest.cs │ │ │ │ ├── DissolveGuildRequest.cs │ │ │ │ ├── DonateCoinsToGuildRequest.cs │ │ │ │ ├── GetGuildInfoRequest.cs │ │ │ │ ├── GetGuildItemListRequest.cs │ │ │ │ ├── GetGuildLoggedInMembersRequest.cs │ │ │ │ ├── GetGuildMenuRequest.cs │ │ │ │ ├── GetGuildShopItemsRequest.cs │ │ │ │ ├── GetShoppableGuildListRequest.cs │ │ │ │ ├── GuildInvitationResultRequest.cs │ │ │ │ ├── GuildMemberListRequest.cs │ │ │ │ ├── KickPlayerFromGuildRequest.cs │ │ │ │ ├── LeaveGuildRequest.cs │ │ │ │ ├── PurchaseGuildShopItemRequest.cs │ │ │ │ ├── ReassignGuildMasterRequest.cs │ │ │ │ ├── SendGuildInviteRequest.cs │ │ │ │ ├── TakeGuildShopItemRequest.cs │ │ │ │ ├── UpdateGuildDetailsRequest.cs │ │ │ │ ├── UpdateGuildShopItemRequest.cs │ │ │ │ └── ViewGuildRequest.cs │ │ │ ├── Login │ │ │ │ ├── AreaServerDiskAuthorizationRequest.cs │ │ │ │ ├── AreaServerShutdownRequest.cs │ │ │ │ ├── DiskAuthorizationRequest.cs │ │ │ │ ├── LogonRepeatRequest.cs │ │ │ │ └── LogonRequest.cs │ │ │ ├── Mail │ │ │ │ ├── GetMailContentRequest.cs │ │ │ │ ├── GetMailListRequest.cs │ │ │ │ ├── MailCheckRequest.cs │ │ │ │ ├── SendGuildMailRequest.cs │ │ │ │ └── SendMailRequest.cs │ │ │ ├── Misc │ │ │ │ ├── DataComRequest.cs │ │ │ │ ├── PingRequest.cs │ │ │ │ ├── PrivateBroadcastRequest.cs │ │ │ │ ├── ReturnToDesktopRequest.cs │ │ │ │ └── Unknown787ERequest.cs │ │ │ ├── Ranking │ │ │ │ ├── RankingLeaderboardRequest.cs │ │ │ │ └── RankingPlayerInfoRequest.cs │ │ │ ├── Saves │ │ │ │ └── GetAccountInfoForSaveIdRequest.cs │ │ │ └── Security │ │ │ │ ├── KeyExchangeAcknowledgementRequest.cs │ │ │ │ └── KeyExchangeRequest.cs │ │ └── Response │ │ │ ├── AreaServer │ │ │ ├── AreaServerDateTimeResponse.cs │ │ │ ├── AreaServerFavoriteEntry.cs │ │ │ ├── AreaServerFavoritesCountResponse.cs │ │ │ ├── AreaServerIPAddressPortResponse.cs │ │ │ ├── AreaServerPublishDetailsResponse.cs │ │ │ └── AreaServerPublishResponse.cs │ │ │ ├── Articles │ │ │ ├── ArticleCheckResponse.cs │ │ │ ├── GetNewsPostErrorResponse.cs │ │ │ ├── NewsArticleCountResponse.cs │ │ │ ├── NewsArticleEntryResponse.cs │ │ │ ├── NewsArticleListResponse.cs │ │ │ ├── NewsCategoryCountResponse.cs │ │ │ ├── NewsCategoryEntryResponse.cs │ │ │ ├── NewsPostImageDetailsResponse.cs │ │ │ └── NewsPostImageSizeResponse.cs │ │ │ ├── BBS │ │ │ ├── BbsCategoryCountResponse.cs │ │ │ ├── BbsCategoryEntryResponse.cs │ │ │ ├── BbsPostContentResponse.cs │ │ │ ├── BbsThreadCountResponse.cs │ │ │ ├── BbsThreadEntryResponse.cs │ │ │ ├── BbsThreadPostCountResponse.cs │ │ │ ├── BbsThreadPostEntryInfoResponse.cs │ │ │ ├── CheckCreateBBSThreadResponse.cs │ │ │ ├── CreateBBSPostResponse.cs │ │ │ └── GetBBSUpdatesResponse.cs │ │ │ ├── BaseResponse.cs │ │ │ ├── Character │ │ │ ├── RegisterCharacterResponse.cs │ │ │ ├── Select2CharacterResponse.cs │ │ │ ├── SelectCharacterResponse.cs │ │ │ └── UnregisterCharacterResponse.cs │ │ │ ├── ChatLobby │ │ │ ├── ChatLobbyCountResponse.cs │ │ │ ├── ChatLobbyEnterRoomResponse.cs │ │ │ ├── ChatLobbyEntryResponse.cs │ │ │ ├── ChatLobbyStatusUpdateResponse.cs │ │ │ ├── ClientLeftChatLobbyResponse.cs │ │ │ ├── CreateLobbyChatroomResponse.cs │ │ │ ├── LobbyChatroomCategoryCountResponse.cs │ │ │ ├── LobbyChatroomCategoryEntryResponse.cs │ │ │ ├── LobbyEventResponse.cs │ │ │ ├── LobbyExitResponse.cs │ │ │ ├── LobbyGetServersExitResponse.cs │ │ │ ├── LobbyGetServersResponse.cs │ │ │ ├── LobbyServerCategoryCountResponse.cs │ │ │ ├── LobbyServerCategoryEntryResponse.cs │ │ │ ├── LobbyServerEntryCountResponse.cs │ │ │ └── LobbyServerEntryResponse.cs │ │ │ ├── Guilds │ │ │ ├── CreateGuildResponse.cs │ │ │ ├── DissolveGuildResponse.cs │ │ │ ├── DonateCoinsToGuildResponse.cs │ │ │ ├── GuildInfoResponse.cs │ │ │ ├── GuildInvitationResultConfirmationResponse.cs │ │ │ ├── GuildItemListCountResponse.cs │ │ │ ├── GuildItemListEntryResponse.cs │ │ │ ├── GuildListEntryCountResponse.cs │ │ │ ├── GuildLoggedInMembersResponse.cs │ │ │ ├── GuildMemberListCategoryCountResponse.cs │ │ │ ├── GuildMemberListCategoryEntryResponse.cs │ │ │ ├── GuildMemberListEntryCountResponse.cs │ │ │ ├── GuildMemberListEntryResponse.cs │ │ │ ├── GuildMenuCategoryCountResponse.cs │ │ │ ├── GuildMenuCategoryResponse.cs │ │ │ ├── GuildMenuListEntryResponse.cs │ │ │ ├── GuildShopEntryCountResponse.cs │ │ │ ├── GuildShopEntryResponse.cs │ │ │ ├── GuildShopItemCountResponse.cs │ │ │ ├── GuildShopItemEntryResponse.cs │ │ │ ├── InvitePlayerToGuildResponse.cs │ │ │ ├── KickPlayerFromGuildResponse.cs │ │ │ ├── LeaveGuildResponse.cs │ │ │ ├── PurchaseGuildShopItemResponse.cs │ │ │ ├── ReassignGuildMasterResponse.cs │ │ │ ├── ShoppableGuildEntryCountResponse.cs │ │ │ ├── ShoppableGuildEntryResponse.cs │ │ │ ├── TakeGuildShopItemResponse.cs │ │ │ ├── UpdateGuildDetailsResponse.cs │ │ │ └── UpdateGuildShopItemResponse.cs │ │ │ ├── Login │ │ │ ├── AreaServerDiskAuthorizationResponse.cs │ │ │ ├── AreaServerLogonResponse.cs │ │ │ ├── AreaServerShutdownResponse.cs │ │ │ ├── DiskAuthorizationResponse.cs │ │ │ ├── LogonRepeatResponse.cs │ │ │ └── LogonResponse.cs │ │ │ ├── Mail │ │ │ ├── MailCheckResponse.cs │ │ │ ├── MailContentResponse.cs │ │ │ ├── MailEntryResponse.cs │ │ │ ├── MailListCountResponse.cs │ │ │ └── SendMailResponse.cs │ │ │ ├── Misc │ │ │ ├── DataComResponse.cs │ │ │ ├── PingResponse.cs │ │ │ ├── PrivateBroadcastResponse.cs │ │ │ ├── ReturnToDesktopResponse.cs │ │ │ └── UnknownResponse.cs │ │ │ ├── Ranking │ │ │ ├── RankingLeaderboardCategoryCountResponse.cs │ │ │ ├── RankingLeaderboardCategoryEntryResponse.cs │ │ │ ├── RankingLeaderboardPlayerCountResponse.cs │ │ │ ├── RankingLeaderboardPlayerEntryResponse.cs │ │ │ └── RankingPlayerInfoResponse.cs │ │ │ ├── Saves │ │ │ └── PlayerAccountInformationResponse.cs │ │ │ └── Security │ │ │ └── KeyExchangeResponse.cs │ ├── Pipeline │ │ ├── Builder │ │ │ ├── PacketPipelineBuilder.cs │ │ │ └── PacketPipelineBuilderExtensions.cs │ │ ├── Decoders │ │ │ ├── FragmentFrameDecoder.cs │ │ │ └── IPacketDecoder.cs │ │ ├── Encoders │ │ │ ├── DataTypeEnvelopeEncoder.cs │ │ │ ├── EncryptionEncoder.cs │ │ │ └── IMessageEncoder.cs │ │ └── FragmentPacketPipeline.cs │ ├── Queries │ │ ├── Images │ │ │ └── GetImageInfoQuery.cs │ │ ├── Infrastructure │ │ │ └── IsIpAddressBannedQuery.cs │ │ └── News │ │ │ └── HasPlayerReadNewsArticle.cs │ ├── Sessions │ │ └── FragmentTcpSession.cs │ └── Stores │ │ └── ChatLobbyStore.cs ├── Fragment.NetSlum.Persistence │ ├── Attributes │ │ └── TimestampableAttribute.cs │ ├── Builders │ │ └── EntityListenerBuilder.cs │ ├── Entities │ │ ├── AreaServerCategory.cs │ │ ├── AreaServerIpMapping.cs │ │ ├── BannedIp.cs │ │ ├── BbsCategory.cs │ │ ├── BbsPost.cs │ │ ├── BbsPostContent.cs │ │ ├── BbsThread.cs │ │ ├── Character.cs │ │ ├── CharacterIpLog.cs │ │ ├── CharacterStatHistory.cs │ │ ├── CharacterStats.cs │ │ ├── ChatLobby.cs │ │ ├── Deprecated │ │ │ ├── BbsCategory.cs │ │ │ ├── BbsPostBody.cs │ │ │ ├── BbsPostMetum.cs │ │ │ ├── BbsThread.cs │ │ │ ├── Characterrepository.cs │ │ │ ├── FailedJob.cs │ │ │ ├── Guilditemshop.cs │ │ │ ├── Guildrepository.cs │ │ │ ├── MailBody.cs │ │ │ ├── MailMetum.cs │ │ │ ├── Messageoftheday.cs │ │ │ ├── Migration.cs │ │ │ ├── News.cs │ │ │ ├── NewsSection.cs │ │ │ ├── NewsSectionLog.cs │ │ │ ├── PasswordReset.cs │ │ │ ├── PlayerAccountId.cs │ │ │ ├── RankingDatum.cs │ │ │ ├── SaveFileIntegration.cs │ │ │ └── User.cs │ │ ├── Guild.cs │ │ ├── GuildActivityLog.cs │ │ ├── GuildShopItem.cs │ │ ├── GuildStats.cs │ │ ├── IConfigurableEntity.cs │ │ ├── Mail.cs │ │ ├── MailContent.cs │ │ ├── PlayerAccount.cs │ │ ├── ServerNews.cs │ │ ├── WebNewsArticle.cs │ │ ├── WebNewsCategory.cs │ │ └── WebNewsReadLog.cs │ ├── Extensions │ │ ├── EntityListenerServerExtensions.cs │ │ ├── QueryExtensions.cs │ │ └── ServiceCollectionExtensions.cs │ ├── Fragment.NetSlum.Persistence.csproj │ ├── FragmentContext.cs │ ├── Interceptors │ │ └── EntityChangeInterceptor.cs │ ├── Listeners │ │ ├── AbstractEntityChangeListener.cs │ │ ├── CharacterStatsChangeListener.cs │ │ ├── IEntityChangeListener.cs │ │ └── TimestampableEntityListener.cs │ ├── Migrations │ │ ├── 20230609073554_Initial.Designer.cs │ │ ├── 20230609073554_Initial.cs │ │ ├── 20230610143706_AreaServerIpMappingsForDiscord.Designer.cs │ │ ├── 20230610143706_AreaServerIpMappingsForDiscord.cs │ │ ├── 20230612015705_GuildActivityLog.Designer.cs │ │ ├── 20230612015705_GuildActivityLog.cs │ │ ├── 20230612020916_GuildShopItems.Designer.cs │ │ ├── 20230612020916_GuildShopItems.cs │ │ ├── 20230707151942_ChatLobbyTypes.Designer.cs │ │ ├── 20230707151942_ChatLobbyTypes.cs │ │ ├── 20230710144002_IpLogs.Designer.cs │ │ ├── 20230710144002_IpLogs.cs │ │ ├── 20230711022204_Mail.Designer.cs │ │ ├── 20230711022204_Mail.cs │ │ ├── 20230711034307_MailLengthConstraints.Designer.cs │ │ ├── 20230711034307_MailLengthConstraints.cs │ │ ├── 20240110034631_CharSaveSlot.Designer.cs │ │ ├── 20240110034631_CharSaveSlot.cs │ │ └── FragmentContextModelSnapshot.cs │ ├── OldFragmentContext.cs │ └── Services │ │ └── AutoDbContextMigrationService.cs ├── Fragment.NetSlum.Server │ ├── Api │ │ ├── Controllers │ │ │ ├── AreaServersController.cs │ │ │ ├── GuildsController.cs │ │ │ ├── LobbiesController.cs │ │ │ ├── PlayersController.cs │ │ │ └── StatsController.cs │ │ └── Models │ │ │ ├── AreaServerStatus.cs │ │ │ ├── Client.cs │ │ │ ├── GuildInfo.cs │ │ │ ├── Lobby.cs │ │ │ ├── LobbyPlayer.cs │ │ │ ├── PagedResult.cs │ │ │ ├── PlayerInfo.cs │ │ │ ├── PlayerStats.cs │ │ │ └── ServerStats.cs │ ├── Converters │ │ └── ImageConverter.cs │ ├── Fragment.NetSlum.Server.csproj │ ├── Handlers │ │ ├── Accounts │ │ │ └── RegisterPlayerAccountCommandHandler.cs │ │ ├── Character │ │ │ └── RegisterCharacterCommandHandler.cs │ │ ├── Events │ │ │ └── CharacterLoggedInEventHandler.cs │ │ ├── Images │ │ │ └── GetImageInfoQueryHandler.cs │ │ ├── Infrastructure │ │ │ └── IsIpAddressBannedQueryHandler.cs │ │ └── News │ │ │ ├── HasPlayerReadNewsArticleQueryHandler.cs │ │ │ └── MarksNewsArticleReadCommandHandler.cs │ ├── Mappings │ │ ├── AreaServerMapper.cs │ │ ├── CharacterInfoMapper.cs │ │ ├── CharacterMapper.cs │ │ ├── GuildMapper.cs │ │ └── LobbyMapper.cs │ ├── Program.cs │ ├── Servers │ │ ├── Server.cs │ │ └── ServerConfiguration.cs │ ├── Services │ │ ├── ChatLobbyBackgroundServicecs.cs │ │ ├── ClientTickService.cs │ │ └── ServerBackgroundService.cs │ ├── Startup.cs │ ├── serverConfig.Production.json │ ├── serverConfig.json │ └── wwwroot │ │ └── swagger │ │ ├── css │ │ └── ui.css │ │ └── img │ │ └── logo.svg └── Fragment.NetSlum.TcpServer │ ├── Buffers │ └── PooledBuffer.cs │ ├── Extensions │ └── SocketExtensions.cs │ ├── Fragment.NetSlum.TcpServer.csproj │ ├── ITcpServer.cs │ ├── Options │ └── TcpServerOptions.cs │ ├── TcpServer.cs │ └── TcpSession.cs └── test └── Fragment.NetSlum.Networking.Test ├── Fragment.NetSlum.Networking.Test.csproj ├── Pipeline ├── Decoders │ └── FragmentFrameDecoderTest.cs └── FragmentPacketPipelineTest.cs └── UnitTest1.cs /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | indent_size = 4 7 | indent_style = space 8 | insert_final_newline = true 9 | max_line_length = 140 10 | tab_width = 4 11 | trim_trailing_whitespace = true 12 | ij_continuation_indent_size = 8 13 | ij_formatter_off_tag = @formatter:off 14 | ij_formatter_on_tag = @formatter:on 15 | ij_formatter_tags_enabled = false 16 | ij_smart_tabs = false 17 | ij_visual_guides = none 18 | ij_wrap_on_typing = false 19 | 20 | [.editorconfig] 21 | ij_editorconfig_align_group_field_declarations = false 22 | ij_editorconfig_space_after_colon = false 23 | ij_editorconfig_space_after_comma = true 24 | ij_editorconfig_space_before_colon = false 25 | ij_editorconfig_space_before_comma = false 26 | ij_editorconfig_spaces_around_assignment_operators = true 27 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto encoding=UTF-8 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | *.cs diff=csharp text 14 | *.vb text 15 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @Blackburn29 @Zero1UP 2 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: nuget 4 | directory: "/src/Fragment.NetSlum.Console" 5 | schedule: 6 | interval: weekly 7 | open-pull-requests-limit: 5 8 | - package-ecosystem: nuget 9 | directory: "/src/Fragment.NetSlum.Server" 10 | schedule: 11 | interval: weekly 12 | open-pull-requests-limit: 5 13 | -------------------------------------------------------------------------------- /.github/workflows/test-build.yml: -------------------------------------------------------------------------------- 1 | name: Docker Image CI 2 | 3 | on: 4 | push: 5 | branches: [ "master" ] 6 | pull_request: 7 | branches: [ "master" ] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v3 14 | - name: Build image and run tests 15 | run: docker build . --file Dockerfile --target testrunner --tag fragment-netslum:${{ github.ref_name }}-${{github.run_number}} 16 | -------------------------------------------------------------------------------- /.run/Fragment.NetSlum.Server.run.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 20 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/dotnet/aspnet:8.0-bookworm-slim AS base 2 | WORKDIR /app 3 | EXPOSE 80 4 | 5 | FROM mcr.microsoft.com/dotnet/sdk:8.0-bookworm-slim AS build 6 | WORKDIR /srv 7 | COPY Fragment.NetSlum.sln . 8 | COPY src/. src/. 9 | 10 | RUN dotnet restore src/Fragment.NetSlum.Server 11 | 12 | FROM build as testrunner 13 | COPY test/. test/. 14 | RUN dotnet test -c Release --filter "Category=Unit" /p:CollectCoverage=true /p:ExcludeByFile="**/Migrations/*.cs" /p:CoverletOutput='/test/build/' /p:CoverletOutputFormat='json%2ccobertura' /p:MergeWith='/test/build/coverage.json' 15 | 16 | FROM build AS publish 17 | WORKDIR /srv/src/Fragment.NetSlum.Server 18 | 19 | RUN dotnet publish Fragment.NetSlum.Server.csproj -c Release --runtime linux-x64 -o /app --self-contained 20 | 21 | WORKDIR /srv/src/Fragment.NetSlum.Console 22 | RUN dotnet publish Fragment.NetSlum.Console.csproj -c Release --runtime linux-x64 -o /app/console --self-contained 23 | 24 | FROM base AS final 25 | EXPOSE 49000 26 | 27 | WORKDIR /app 28 | COPY --from=publish /app . 29 | CMD ["./Fragment.NetSlum.Server"] 30 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | # Example docker-compose setup for running Fragment.NetSlum in a containerized environment. 2 | # 3 | # *The configuration defined here is for testing purposes only and should not be used in 4 | # a production environment. 5 | # 6 | # For more information, see: 7 | # https://docs.docker.com/compose/yml/ 8 | version: '3.4' 9 | services: 10 | fragment_server: 11 | image: psrewired/fragment-netslum 12 | build: 13 | context: . 14 | target: final 15 | ports: 16 | - '49000:49000' #Game Server 17 | - '5000:5000' #API 18 | environment: 19 | - ASPNETCORE_URLS=http://+:5000 20 | - ConnectionStrings__Database=server=fragment_mysql;port=3306;database=fragment_redux;username=root;password=d3ve10pm3nt; 21 | - Serilog__MinimumLevel__Default=Information 22 | depends_on: 23 | - fragment_mysql 24 | 25 | fragment_mysql: 26 | image: 'mysql:8' 27 | ports: 28 | - '3308:3306' 29 | environment: 30 | MYSQL_ROOT_PASSWORD: 'd3ve10pm3nt' 31 | restart: always 32 | -------------------------------------------------------------------------------- /docs/about/contributing.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | ___ 3 | ## Reporting issues 4 | We appreciate contributions of any kind, including bug reports. Please use the issue 5 | tracker [Here](http://github.com/PSRewired/FragmentServer/issues) 6 | to report any issues or concerns you may have. 7 | 8 | ### Issue formatting 9 | When filing an issue, please try and be as descriptive as possible. It is heavily appreciated if you are 10 | able to provide us with the steps used in order to reproduce the problem. You may also file issues to 11 | track new features that you which to see implemented or plan to implement yourself. 12 | 13 | Issues filed for the following reasons will be ignored/closed: 14 | - Generalized questions including (but not limited to) software support, installation support 15 | - Off Topic discussions that are not related to this repository or the information within it 16 | 17 | ## Contributing Code or Documentation Changes 18 | All contributions are accepted for review and must be submitted as Pull-Requests for the 19 | [CODEOWNERS](/.github/CODEOWNERS) to review. It is never a guarantee that your code will be merged 20 | and you should be receptive to feedback at any time. 21 | 22 | For what we expect in contributions, please review our [Coding Guidelines](coding-style.md) 23 | -------------------------------------------------------------------------------- /docs/about/license.md: -------------------------------------------------------------------------------- 1 | # License 2 | FragmentServer is licensed under GPLv3. For more information please view the included license in the 3 | project which can be found [Here](https://github.com/PSRewired/FragmentServer/LICENSE) 4 | -------------------------------------------------------------------------------- /docs/about/project-overview.md: -------------------------------------------------------------------------------- 1 | # Project Overview 2 | --- 3 | 4 | ## Application Hierarchy 5 | ![Project Structure](../static/project_diagram.png) 6 | 7 | ## Project Structure 8 | This application strives to keep application code separated using the principles of 9 | [Clean Architecture](https://learn.microsoft.com/en-us/dotnet/architecture/modern-web-apps-azure/common-web-application-architectures#clean-architectureI) 10 | 11 | The TL;DR of this is: 12 | - Separate code by concern. (Ex: database models do not belong in the Networking project) 13 | - Attempt to stick to SOLID principles by making each function have **one** purpose only. Split logic into private singular functions 14 | if necessary 15 | - Project structure should closely resemble an "onion" by separating logic into new projects/libraries as deemed necessary 16 | - Follow the [Rule of Three](https://en.wikipedia.org/wiki/Rule_of_three_(computer_programming)) when creating abstractions 17 | -------------------------------------------------------------------------------- /docs/hosting/area-server-hosting.md: -------------------------------------------------------------------------------- 1 | # Hosting an Area Server 2 | 3 | ## Patching the Area Server Executable 4 | - Download the latest release of the [Fragment Patcher](https://github.com/Zero1UP/dot-Hack-Fragment-Patcher/releases/latest) 5 | - Open the AreaServer executable in the patcher and update the IP address to the server you wish to connect to 6 | - Click Patch. 7 | - No prompt will be given, but you may now close the patcher tool. 8 | 9 | ## Assigning your server to a specific category 10 | By design, the lobby server support the use of multiple defined AreaServer categories. By default, area servers will 11 | be assigned to the "Main" category unless the following format is used in the server's name. `|` (Ex: Test|MyAreaServer) 12 | 13 | Using the above format will instruct the lobby server to assign your AreaServer to the specified category within the game. 14 | If the category does not exist, the full name of your AreaServer will be used and assigned to the "Main" category. 15 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | # .hack//Frägment Technical Overview and Documentation 2 | ___ 3 | 4 | ## Table of Contents 5 | 1. [Networking and Messaging](networking/index.md) 6 | 2. [Project Design Overview](about/project-overview.md) 7 | 3. [Contributing to the project](about/contributing.md) 8 | 4. [License](about/license.md) 9 | 5. [Hosting an Area Server](hosting/area-server-hosting.md) 10 | -------------------------------------------------------------------------------- /docs/networking/encoding.md: -------------------------------------------------------------------------------- 1 | # Fragment Binary Message Framing 2 | ___ 3 | 4 | ## Endianness 5 | - Primitive types (int,short, etc) are represented in big-endian notation. 6 | 7 | ## Text Encoding 8 | - Initially it was thought that the game was encoding using Shift-JIS strings, however during the development of this project, 9 | it was determined to be partially incorrect. The game, since it supports control characters, uses [MS/CP932](https://en.wikipedia.org/wiki/Code_page_932) 10 | for its encoding and expect all strings to be null-terminated. 11 | 12 | ## Image Encoding 13 | Images in Fragment are encoded in [TGA/TARGA](http://www.paulbourke.net/dataformats/tga/) format using 32-bit color depth, RGB colorspace, and Top-Left orientation. 14 | 15 | ### Known Image Usage 16 | - News posts require an image size of 128x128px 17 | 18 | -------------------------------------------------------------------------------- /docs/networking/index.md: -------------------------------------------------------------------------------- 1 | # Networking and Message Framing 2 | Documentation for Fragment's networking infrastructure and messaging architecture 3 | ___ 4 | 5 | ## Table of Contents 6 | 1. [Message Framing](framing.md) 7 | 1. [Message Encoding](encoding.md) 8 | -------------------------------------------------------------------------------- /docs/static/fragment.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PSRewired/FragmentServer/7276b8216d3b188fe65b5e2d3fd22944341b60d0/docs/static/fragment.jpg -------------------------------------------------------------------------------- /docs/static/project_diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PSRewired/FragmentServer/7276b8216d3b188fe65b5e2d3fd22944341b60d0/docs/static/project_diagram.png -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: FragmentServer 2 | site_url: https://www.mkdocs.org/ 3 | site_description: A emulated server for the game .hack//Frägment 4 | site_author: PSRewired 5 | 6 | repo_url: https://github.com/PSRewired/FragmentServer/ 7 | edit_uri: blob/master/docs/ 8 | 9 | theme: 10 | name: mkdocs 11 | locale: en 12 | 13 | nav: 14 | - Home: index.md 15 | - Networking and Messaging: networking/ 16 | - About: 17 | - Contributing: about/contributing.md 18 | - License: about/license.md 19 | 20 | markdown_extensions: 21 | - toc: 22 | permalink:  23 | 24 | copyright: Copyright © 2023 PSRewired 25 | 26 | plugins: 27 | - search 28 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Console/DependencyInjection/TypeRegistrar.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.Extensions.DependencyInjection; 3 | using Spectre.Console.Cli; 4 | 5 | namespace Fragment.NetSlum.Console.DependencyInjection; 6 | 7 | public sealed class TypeRegistrar : ITypeRegistrar 8 | { 9 | private readonly IServiceCollection _builder; 10 | 11 | public TypeRegistrar(IServiceCollection builder) 12 | { 13 | _builder = builder; 14 | } 15 | 16 | public ITypeResolver Build() 17 | { 18 | return new TypeResolver(_builder.BuildServiceProvider()); 19 | } 20 | 21 | public void Register(Type service, Type implementation) 22 | { 23 | _builder.AddSingleton(service, implementation); 24 | } 25 | 26 | public void RegisterInstance(Type service, object implementation) 27 | { 28 | _builder.AddSingleton(service, implementation); 29 | } 30 | 31 | public void RegisterLazy(Type service, Func func) 32 | { 33 | if (func is null) 34 | { 35 | throw new ArgumentNullException(nameof(func)); 36 | } 37 | 38 | _builder.AddSingleton(service, (provider) => func()); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Console/DependencyInjection/TypeResolver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Spectre.Console.Cli; 3 | 4 | namespace Fragment.NetSlum.Console.DependencyInjection; 5 | 6 | public sealed class TypeResolver : ITypeResolver, IDisposable 7 | { 8 | private readonly IServiceProvider _provider; 9 | 10 | public TypeResolver(IServiceProvider provider) 11 | { 12 | _provider = provider ?? throw new ArgumentNullException(nameof(provider)); 13 | } 14 | 15 | public object? Resolve(Type? type) 16 | { 17 | return type == null ? null : _provider.GetService(type); 18 | } 19 | 20 | public void Dispose() 21 | { 22 | if (_provider is IDisposable disposable) 23 | { 24 | disposable.Dispose(); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Console/Fragment.NetSlum.Console.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | CS0618 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Core/CommandBus/Contracts/Commands/CommandHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | using Mediator; 4 | 5 | namespace Fragment.NetSlum.Core.CommandBus.Contracts.Commands; 6 | 7 | /// 8 | /// Abstract class used as an intermediary implementation, thus avoiding a vendor-lock on a third-party command bus library 9 | /// Currently both our implementation and MediatR use the same function declaration, so the integration is seamless. 10 | /// 11 | /// 12 | /// 13 | public abstract class CommandHandler : ICommandHandler, IRequestHandler 14 | where TCommand : ICommand 15 | { 16 | public abstract ValueTask Handle(TCommand command, CancellationToken cancellationToken); 17 | } 18 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Core/CommandBus/Contracts/Commands/ICommand.cs: -------------------------------------------------------------------------------- 1 | using Mediator; 2 | 3 | namespace Fragment.NetSlum.Core.CommandBus.Contracts.Commands; 4 | 5 | public interface ICommand : IRequest { } 6 | 7 | public interface ICommand : ICommand, IRequest { } 8 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Core/CommandBus/Contracts/Commands/ICommandHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | using Mediator; 4 | 5 | namespace Fragment.NetSlum.Core.CommandBus.Contracts.Commands; 6 | 7 | public interface ICommandHandler where TCommand : ICommand 8 | { 9 | public ValueTask Handle(TCommand command, CancellationToken cancellationToken); 10 | } 11 | 12 | public interface ICommandHandler : ICommandHandler where TCommand : ICommand {} 13 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Core/CommandBus/Contracts/Events/EventHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | using Mediator; 4 | 5 | namespace Fragment.NetSlum.Core.CommandBus.Contracts.Events; 6 | 7 | /// 8 | /// Abstract class used as an intermediary implementation, thus avoiding a vendor-lock on a third-party command bus library. 9 | /// Currently both our implementation and MediatR use the same function declaration, so the integration is seamless. 10 | /// 11 | /// 12 | public abstract class EventHandler : IEventHandler, INotificationHandler 13 | where TEvent : IEvent 14 | { 15 | public abstract ValueTask Handle(TEvent eventInfo, CancellationToken cancellationToken); 16 | } 17 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Core/CommandBus/Contracts/Events/IEvent.cs: -------------------------------------------------------------------------------- 1 | using Mediator; 2 | 3 | namespace Fragment.NetSlum.Core.CommandBus.Contracts.Events; 4 | 5 | public interface IEvent : INotification { } 6 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Core/CommandBus/Contracts/Events/IEventHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | 4 | namespace Fragment.NetSlum.Core.CommandBus.Contracts.Events; 5 | 6 | internal interface IEventHandler where TEvent : IEvent 7 | { 8 | public ValueTask Handle(TEvent eventInfo, CancellationToken cancellationToken); 9 | } 10 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Core/CommandBus/Contracts/Queries/IQuery.cs: -------------------------------------------------------------------------------- 1 | using Mediator; 2 | 3 | namespace Fragment.NetSlum.Core.CommandBus.Contracts.Queries; 4 | 5 | public interface IQuery : IRequest { } 6 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Core/CommandBus/Contracts/Queries/IQueryHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | 4 | namespace Fragment.NetSlum.Core.CommandBus.Contracts.Queries; 5 | 6 | public interface IQueryHandler where TQuery : IQuery 7 | { 8 | public ValueTask Handle(TQuery command, CancellationToken cancellationToken); 9 | } 10 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Core/CommandBus/Contracts/Queries/QueryHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | using Mediator; 4 | 5 | namespace Fragment.NetSlum.Core.CommandBus.Contracts.Queries; 6 | 7 | /// 8 | /// Abstract class used as an intermediary implementation, thus avoiding a vendor-lock on a third-party command bus library. 9 | /// Currently both our implementation and MediatR use the same function declaration, so the integration is seamless. 10 | /// 11 | /// 12 | /// 13 | public abstract class QueryHandler : IQueryHandler, IRequestHandler 14 | where TCommand : IQuery 15 | { 16 | public abstract ValueTask Handle(TCommand command, CancellationToken cancellationToken); 17 | } 18 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Core/CommandBus/ICommandBus.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | using Fragment.NetSlum.Core.CommandBus.Contracts.Commands; 4 | using Fragment.NetSlum.Core.CommandBus.Contracts.Events; 5 | using Fragment.NetSlum.Core.CommandBus.Contracts.Queries; 6 | 7 | namespace Fragment.NetSlum.Core.CommandBus; 8 | 9 | /// 10 | /// Represents a command bus implementation. Note, if your extension does not support dependency injection scopes, you will 11 | /// need to implement that yourself. 12 | /// 13 | public interface ICommandBus 14 | { 15 | Task Notify(TEvent eventInfo, CancellationToken cancellationToken = default) where TEvent : IEvent; 16 | Task GetResult(IQuery query, CancellationToken cancellationToken = default); 17 | Task Execute(ICommand command, CancellationToken cancellationToken = default); 18 | } 19 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Core/CommandBus/MediatorCommandBus.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | using Fragment.NetSlum.Core.CommandBus.Contracts.Events; 4 | using Mediator; 5 | 6 | namespace Fragment.NetSlum.Core.CommandBus; 7 | 8 | /// 9 | /// MediatR shim for the command bus 10 | /// 11 | public class MediatorCommandBus : ICommandBus 12 | { 13 | private readonly IMediator _mediator; 14 | 15 | public MediatorCommandBus(IMediator mediator) 16 | { 17 | _mediator = mediator; 18 | } 19 | 20 | public async Task Notify(TEvent eventInfo, CancellationToken cancellationToken = default) where TEvent : IEvent 21 | { 22 | await _mediator.Publish(eventInfo, cancellationToken); 23 | } 24 | 25 | public async Task GetResult(Contracts.Queries.IQuery query, CancellationToken cancellationToken = default) 26 | { 27 | return await _mediator.Send(query, cancellationToken); 28 | } 29 | 30 | public async Task Execute(Contracts.Commands.ICommand command, CancellationToken cancellationToken = default) 31 | { 32 | return await _mediator.Send(command, cancellationToken); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Core/Constants/CharacterClass.cs: -------------------------------------------------------------------------------- 1 | namespace Fragment.NetSlum.Core.Constants; 2 | 3 | public enum CharacterClass : byte 4 | { 5 | TwinBlade, 6 | BladeMaster, 7 | HeavyBlade, 8 | AxeHeavy, 9 | LongArm, 10 | WaveMaster, 11 | } 12 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Core/Constants/CharacterColor.cs: -------------------------------------------------------------------------------- 1 | namespace Fragment.NetSlum.Core.Constants; 2 | 3 | public enum CharacterColor : byte 4 | { 5 | Red, 6 | Blue, 7 | Yellow, 8 | Green, 9 | Brown, 10 | Pink, 11 | } 12 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Core/Constants/CharacterRanks.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | 3 | namespace Fragment.NetSlum.Core.Constants; 4 | 5 | public static partial class CharacterRanks 6 | { 7 | // ReSharper disable InconsistentNaming 8 | public enum RankCategory : byte 9 | { 10 | Level = 1, 11 | HP = 2, 12 | SP = 3, 13 | GP = 4, 14 | OnlineTreasures = 5, 15 | AverageFieldLevel = 6, 16 | GoldCoin = 7, 17 | SilverCoin = 8, 18 | BronzeCoin = 9, 19 | } 20 | // ReSharper enable InconsistentNaming 21 | 22 | public static string GetCategoryName(this RankCategory category) 23 | { 24 | return FormatRegex().Replace(StripCharsRegex().Replace(category.ToString(), "$1 $2"), "$1 $2"); 25 | } 26 | 27 | [GeneratedRegex("(\\p{Ll})(\\P{Ll})")] 28 | private static partial Regex FormatRegex(); 29 | 30 | [GeneratedRegex("(\\P{Ll})(\\P{Ll}\\p{Ll})")] 31 | private static partial Regex StripCharsRegex(); 32 | } 33 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Core/Constants/ChatLobbyStatus.cs: -------------------------------------------------------------------------------- 1 | namespace Fragment.NetSlum.Core.Constants; 2 | 3 | public enum ChatLobbyStatus : ushort 4 | { 5 | Closed = 0, 6 | Active = 4, 7 | } 8 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Core/Constants/ChatLobbyType.cs: -------------------------------------------------------------------------------- 1 | namespace Fragment.NetSlum.Core.Constants 2 | { 3 | public enum ChatLobbyType : ushort 4 | { 5 | Any = 0, 6 | Default = 0x7403, 7 | Chatroom = 0x7409, 8 | Guild = 0x7418, 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Core/Constants/GuildStatus.cs: -------------------------------------------------------------------------------- 1 | namespace Fragment.NetSlum.Core.Constants; 2 | 3 | public enum GuildStatus : byte 4 | { 5 | None = 0x0, 6 | GuildMaster = 0x1, 7 | Member = 0x2, 8 | } 9 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Core/DependencyInjection/IScopeable.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | 3 | namespace Fragment.NetSlum.Core.DependencyInjection; 4 | 5 | /// 6 | /// Designates that an object contains a service scope 7 | /// 8 | public interface IScopeable 9 | { 10 | public IServiceScope ServiceScope { get; } 11 | } -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Core/Extensions/CharacterExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Fragment.NetSlum.Core.Constants; 3 | 4 | namespace Fragment.NetSlum.Core.Extensions; 5 | 6 | public static class CharacterExtensions 7 | { 8 | public static string ToColorCode(this CharacterColor color) => color switch 9 | { 10 | CharacterColor.Red => "rd", 11 | CharacterColor.Blue => "bl", 12 | CharacterColor.Yellow => "yl", 13 | CharacterColor.Green => "gr", 14 | CharacterColor.Brown => "br", 15 | CharacterColor.Pink => "pp", 16 | _ => throw new ArgumentOutOfRangeException(nameof(color), color, "Invalid color specified") 17 | }; 18 | 19 | public static string GetClassName(this CharacterClass cls) => cls switch 20 | { 21 | CharacterClass.TwinBlade => "Twin Blade", 22 | CharacterClass.BladeMaster => "Blade Master", 23 | CharacterClass.HeavyBlade => "Heavy Blade", 24 | CharacterClass.AxeHeavy => "Heavy Axe", 25 | CharacterClass.LongArm => "Long Arm", 26 | CharacterClass.WaveMaster => "Wave Master", 27 | _ => throw new ArgumentOutOfRangeException(nameof(cls), cls, null) 28 | }; 29 | } 30 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Core/Extensions/DateExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Fragment.NetSlum.Core.Extensions; 4 | 5 | public static class DateExtensions 6 | { 7 | private static DateTime epoch = new DateTime(1970, 1, 1); 8 | 9 | public static ulong ToEpoch(this DateTime dt) 10 | { 11 | return (ulong) dt.Subtract(epoch).TotalSeconds; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Core/Extensions/IpAddressExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Net; 2 | 3 | namespace Fragment.NetSlum.Core.Extensions; 4 | 5 | public static class IpAddressExtensions 6 | { 7 | /// 8 | /// Private IP CIDR ranges defined by 9 | /// RFC1918 10 | /// 11 | private static readonly string[] _privateIpCidrs = 12 | [ 13 | "10.0.0.0/8", 14 | "172.16.0.0/12", 15 | "192.168.0.0/16" 16 | ]; 17 | 18 | /// 19 | /// Determines if the given is a private (LAN) IP 20 | /// by comparing it to the CIDR ranges defined in RFC1918 21 | /// 22 | /// 23 | /// 24 | public static bool IsPrivate(this IPAddress addr) 25 | { 26 | foreach (var cidr in _privateIpCidrs) 27 | { 28 | var network = IPNetwork.Parse(cidr); 29 | 30 | if (!network.Contains(addr)) 31 | { 32 | continue; 33 | } 34 | 35 | return true; 36 | } 37 | 38 | return false; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Core/Extensions/ServiceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.Extensions.DependencyInjection; 3 | 4 | namespace Fragment.NetSlum.Core.Extensions; 5 | 6 | public static class ServiceCollectionExtensions 7 | { 8 | /// 9 | /// Adds the command bus infrastructure to the service container. 10 | /// 11 | /// 12 | /// A type that exists inside of the project/assembly that contains handlers that can be registered 13 | /// 14 | public static IServiceCollection AddCommandBus(this IServiceCollection services, params Type[] types) 15 | { 16 | return services; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Core/Fragment.NetSlum.Core.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | true 7 | CS1591 8 | 9 | 10 | 11 | 12 | 13 | IPNetwork2 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Core/Models/ImageInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Fragment.NetSlum.Core.Models; 4 | 5 | public struct ImageInfo 6 | { 7 | public ImageInfo() 8 | { 9 | } 10 | 11 | public ushort ChunkCount => 1; 12 | public uint ImageSize => (uint)(ColorData.Length + ImageData.Length); 13 | 14 | public Memory ColorData { get; set; } = Array.Empty(); 15 | public Memory ImageData { get; set; } = Array.Empty(); 16 | } 17 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Attributes/FragmentPacket.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Fragment.NetSlum.Networking.Constants; 3 | 4 | namespace Fragment.NetSlum.Networking.Attributes; 5 | 6 | [AttributeUsage(AttributeTargets.Struct|AttributeTargets.Class, AllowMultiple = true)] 7 | public class FragmentPacket : Attribute 8 | { 9 | public readonly MessageType MessageType; 10 | public readonly OpCodes DataPacketType; 11 | 12 | public FragmentPacket(MessageType messageType) 13 | { 14 | MessageType = messageType; 15 | DataPacketType = OpCodes.None; 16 | } 17 | 18 | public FragmentPacket(MessageType messageType, OpCodes dataPacketType) 19 | { 20 | MessageType = messageType; 21 | DataPacketType = dataPacketType; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Commands/Accounts/RegisterPlayerAccountCommand.cs: -------------------------------------------------------------------------------- 1 | using Fragment.NetSlum.Core.CommandBus.Contracts.Commands; 2 | using Microsoft.EntityFrameworkCore; 3 | 4 | namespace Fragment.NetSlum.Networking.Commands.Accounts; 5 | 6 | /// 7 | /// Registers a new player account. Since player Save IDs must be unique, you will need to check for an existing account yourself, 8 | /// otherwise this command may throw an exception 9 | /// 10 | /// The account ID of the new player 11 | /// 12 | public class RegisterPlayerAccountCommand : ICommand 13 | { 14 | public string SaveId { get; set; } 15 | 16 | public RegisterPlayerAccountCommand(string saveId) 17 | { 18 | SaveId = saveId; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Commands/Characters/RegisterCharacterCommand.cs: -------------------------------------------------------------------------------- 1 | using Fragment.NetSlum.Core.CommandBus.Contracts.Commands; 2 | using Fragment.NetSlum.Core.Models; 3 | using Fragment.NetSlum.Persistence.Entities; 4 | 5 | namespace Fragment.NetSlum.Networking.Commands.Characters; 6 | 7 | public class RegisterCharacterCommand : ICommand 8 | { 9 | public CharacterInfo CharacterInfo { get; } 10 | 11 | public RegisterCharacterCommand(CharacterInfo characterInfo) 12 | { 13 | CharacterInfo = characterInfo; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Commands/News/MarkNewsArticleReadCommand.cs: -------------------------------------------------------------------------------- 1 | using Fragment.NetSlum.Core.CommandBus.Contracts.Commands; 2 | 3 | namespace Fragment.NetSlum.Networking.Commands.News; 4 | 5 | public class MarkNewsArticleReadCommand : ICommand 6 | { 7 | public int PlayerId { get; } 8 | public ushort ArticleId { get; } 9 | 10 | public MarkNewsArticleReadCommand(ushort articleId, int playerId) 11 | { 12 | ArticleId = articleId; 13 | PlayerId = playerId; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Constants/MessageType.cs: -------------------------------------------------------------------------------- 1 | namespace Fragment.NetSlum.Networking.Constants; 2 | 3 | public enum MessageType 4 | { 5 | None = 0x00, 6 | PingRequest = 0x02, 7 | 8 | Data = 0x30, 9 | KeyExchangeRequest = 0x34, 10 | KeyExchangeResponse = 0x35, 11 | KeyExchangeAcknowledgmentRequest = 0x36, 12 | } 13 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Crypto/CryptoHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Buffers.Binary; 3 | 4 | namespace Fragment.NetSlum.Networking.Crypto; 5 | 6 | public class CryptoHandler 7 | { 8 | public BlowfishProvider ClientCipher { get; set; } = new BlowfishProvider(); 9 | public BlowfishProvider ServerCipher { get; internal set; } = new BlowfishProvider(); 10 | 11 | public bool TryEncrypt(byte[] data, out byte[] encrypted) 12 | { 13 | if (ServerCipher == null) 14 | { 15 | encrypted = data; 16 | return false; 17 | } 18 | 19 | encrypted = ServerCipher.Encrypt(data); 20 | 21 | return true; 22 | } 23 | 24 | public bool TryDecrypt(byte[] encrypted, out byte[] decrypted) 25 | { 26 | decrypted = ClientCipher.Decrypt(encrypted); 27 | 28 | var receivedChecksum = BinaryPrimitives.ReadUInt16BigEndian(decrypted.AsSpan()[..2]); 29 | var decryptedChecksum = BlowfishProvider.Checksum(decrypted[2..]); 30 | 31 | decrypted = decrypted[2..]; 32 | 33 | return receivedChecksum == decryptedChecksum; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Entrypoint.cs: -------------------------------------------------------------------------------- 1 | namespace Fragment.NetSlum.Networking; 2 | 3 | public class Entrypoint 4 | { 5 | //noop 6 | } 7 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Events/CharacterLoggedInEvent.cs: -------------------------------------------------------------------------------- 1 | using Fragment.NetSlum.Core.CommandBus.Contracts.Events; 2 | 3 | namespace Fragment.NetSlum.Networking.Events; 4 | 5 | /// 6 | /// Event that is fired when a character is selected and active and/or registered with the server 7 | /// 8 | public class CharacterLoggedInEvent : IEvent 9 | { 10 | public int CharacterId { get; set; } 11 | public string IpAddress { get; set; } 12 | 13 | public CharacterLoggedInEvent(int characterId, string ipAddress) 14 | { 15 | CharacterId = characterId; 16 | IpAddress = ipAddress; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Fragment.NetSlum.Networking.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | true 7 | CS1591 8 | CS1998 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Messaging/IPacketHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using Fragment.NetSlum.Core.DependencyInjection; 4 | 5 | namespace Fragment.NetSlum.Networking.Messaging; 6 | 7 | public interface IPacketHandler 8 | { 9 | public ValueTask> CreateResponse(TSession session, TRequest o) where TSession : IScopeable; 10 | } 11 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Request/AreaServer/AreaServerDateTimeRequest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using Fragment.NetSlum.Networking.Attributes; 4 | using Fragment.NetSlum.Networking.Constants; 5 | using Fragment.NetSlum.Networking.Objects; 6 | using Fragment.NetSlum.Networking.Packets.Response; 7 | using Fragment.NetSlum.Networking.Sessions; 8 | using Microsoft.Extensions.Logging; 9 | using Fragment.NetSlum.Networking.Packets.Response.AreaServer; 10 | 11 | namespace Fragment.NetSlum.Networking.Packets.Request.AreaServer; 12 | 13 | [FragmentPacket(MessageType.Data, OpCodes.Data_AreaServerDateTimeRequest)] 14 | public class AreaServerDateTimeRequest : BaseRequest 15 | { 16 | private readonly ILogger _logger; 17 | 18 | public AreaServerDateTimeRequest(ILogger logger) 19 | { 20 | _logger = logger; 21 | } 22 | 23 | public override ValueTask> GetResponse(FragmentTcpSession session, FragmentMessage request) 24 | { 25 | BaseResponse response = new AreaServerDateTimeResponse(); 26 | return SingleMessage(response.Build()); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Request/AreaServer/AreaServerPublishRequest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using Fragment.NetSlum.Networking.Attributes; 4 | using Fragment.NetSlum.Networking.Constants; 5 | using Fragment.NetSlum.Networking.Objects; 6 | using Fragment.NetSlum.Networking.Packets.Response; 7 | using Fragment.NetSlum.Networking.Sessions; 8 | using Microsoft.Extensions.Logging; 9 | using Fragment.NetSlum.Networking.Packets.Response.AreaServer; 10 | 11 | namespace Fragment.NetSlum.Networking.Packets.Request.AreaServer; 12 | 13 | [FragmentPacket(MessageType.Data, OpCodes.Data_AreaServerPublishRequest)] 14 | public class AreaServerPublishRequest :BaseRequest 15 | { 16 | private readonly ILogger _logger; 17 | 18 | public AreaServerPublishRequest(ILogger logger) 19 | { 20 | _logger = logger; 21 | } 22 | 23 | public override ValueTask> GetResponse(FragmentTcpSession session, FragmentMessage request) 24 | { 25 | BaseResponse response = new AreaServerPublishResponse(); 26 | return SingleMessage(response.Build()); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Request/AreaServer/AreaServerUpdateUserCountRequest.cs: -------------------------------------------------------------------------------- 1 | using Fragment.NetSlum.Networking.Objects; 2 | using Fragment.NetSlum.Networking.Sessions; 3 | using Microsoft.Extensions.Logging; 4 | using System.Buffers.Binary; 5 | using System.Collections.Generic; 6 | using System.Threading.Tasks; 7 | using Fragment.NetSlum.Networking.Attributes; 8 | using Fragment.NetSlum.Networking.Constants; 9 | 10 | namespace Fragment.NetSlum.Networking.Packets.Request.AreaServer; 11 | 12 | [FragmentPacket(MessageType.Data, OpCodes.Data_AreaServerUpdateUserCountRequest)] 13 | public class AreaServerUpdateUserCountRequest :BaseRequest 14 | { 15 | private readonly ILogger _logger; 16 | 17 | public AreaServerUpdateUserCountRequest(ILogger logger) 18 | { 19 | _logger = logger; 20 | } 21 | 22 | public override ValueTask> GetResponse(FragmentTcpSession session, FragmentMessage request) 23 | { 24 | session.AreaServerInfo!.CurrentPlayerCount = BinaryPrimitives.ReadUInt16BigEndian(request.Data[2..4].ToArray()); 25 | return NoResponse(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Request/BBS/CheckCreateBBSThreadRequest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using Fragment.NetSlum.Networking.Attributes; 4 | using Fragment.NetSlum.Networking.Constants; 5 | using Fragment.NetSlum.Networking.Objects; 6 | using Fragment.NetSlum.Networking.Packets.Response.BBS; 7 | using Fragment.NetSlum.Networking.Sessions; 8 | 9 | namespace Fragment.NetSlum.Networking.Packets.Request.BBS; 10 | 11 | [FragmentPacket(MessageType.Data, OpCodes.DataBbsCheckThreadCreate)] 12 | public class CheckCreateBBSThreadRequest : BaseRequest 13 | { 14 | public override ValueTask> GetResponse(FragmentTcpSession session, FragmentMessage request) 15 | { 16 | return SingleMessage(new CheckCreateBBSThreadResponse().Build()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Request/BBS/GetBBSUpdatesRequest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using Fragment.NetSlum.Networking.Attributes; 4 | using Fragment.NetSlum.Networking.Constants; 5 | using Fragment.NetSlum.Networking.Objects; 6 | using Fragment.NetSlum.Networking.Packets.Response; 7 | using Fragment.NetSlum.Networking.Sessions; 8 | using Microsoft.Extensions.Logging; 9 | using Fragment.NetSlum.Networking.Packets.Response.BBS; 10 | 11 | namespace Fragment.NetSlum.Networking.Packets.Request.BBS; 12 | 13 | [FragmentPacket(MessageType.Data, OpCodes.DataBBSGetUpdatesRequestRequest)] 14 | public class GetBBSUpdatesRequest:BaseRequest 15 | { 16 | private readonly ILogger _logger; 17 | 18 | public GetBBSUpdatesRequest(ILogger logger) 19 | { 20 | _logger = logger; 21 | } 22 | 23 | public override ValueTask> GetResponse(FragmentTcpSession session, FragmentMessage request) 24 | { 25 | BaseResponse response = new GetBBSUpdatesResponse(); 26 | 27 | return SingleMessage(response.Build()); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Request/BaseRequest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading.Tasks; 4 | using Fragment.NetSlum.Networking.Objects; 5 | using Fragment.NetSlum.Networking.Sessions; 6 | using Serilog; 7 | 8 | namespace Fragment.NetSlum.Networking.Packets.Request; 9 | 10 | public abstract class BaseRequest 11 | { 12 | public ILogger Log => Serilog.Log.ForContext(GetType()); 13 | 14 | public abstract ValueTask> GetResponse(FragmentTcpSession session, FragmentMessage request); 15 | 16 | /// 17 | /// Helper method to return a single message from a request handler 18 | /// 19 | /// 20 | /// 21 | protected static ValueTask> SingleMessage(FragmentMessage response) => 22 | ValueTask.FromResult(SingleMessageAsync(response)); 23 | 24 | protected static ICollection SingleMessageAsync(FragmentMessage response) => 25 | new[] { response }; 26 | 27 | protected static ValueTask> NoResponse() => 28 | ValueTask.FromResult>(Array.Empty()); 29 | } 30 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Request/Character/Select2CharacterRequest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using Fragment.NetSlum.Networking.Attributes; 4 | using Fragment.NetSlum.Networking.Constants; 5 | using Fragment.NetSlum.Networking.Objects; 6 | using Fragment.NetSlum.Networking.Packets.Response.Character; 7 | using Fragment.NetSlum.Networking.Sessions; 8 | 9 | namespace Fragment.NetSlum.Networking.Packets.Request.Character; 10 | 11 | [FragmentPacket(MessageType.Data, OpCodes.DataSelect2CharRequest)] 12 | public class Select2CharacterRequest : BaseRequest 13 | { 14 | public override ValueTask> GetResponse(FragmentTcpSession session, FragmentMessage request) 15 | { 16 | return SingleMessage(new Select2CharacterResponse().Build()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Request/Character/SelectCharacterRequest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using Fragment.NetSlum.Networking.Attributes; 4 | using Fragment.NetSlum.Networking.Constants; 5 | using Fragment.NetSlum.Networking.Objects; 6 | using Fragment.NetSlum.Networking.Packets.Response.Character; 7 | using Fragment.NetSlum.Networking.Sessions; 8 | 9 | namespace Fragment.NetSlum.Networking.Packets.Request.Character; 10 | 11 | [FragmentPacket(MessageType.Data, OpCodes.DataSelectCharRequest)] 12 | public class SelectCharacterRequest : BaseRequest 13 | { 14 | public override ValueTask> GetResponse(FragmentTcpSession session, FragmentMessage request) 15 | { 16 | return SingleMessage(new SelectCharacterResponse().Build()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Request/Character/UnregisterCharacterRequest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using Fragment.NetSlum.Networking.Attributes; 4 | using Fragment.NetSlum.Networking.Constants; 5 | using Fragment.NetSlum.Networking.Objects; 6 | using Fragment.NetSlum.Networking.Packets.Response.Character; 7 | using Fragment.NetSlum.Networking.Sessions; 8 | 9 | namespace Fragment.NetSlum.Networking.Packets.Request.Character; 10 | 11 | [FragmentPacket(MessageType.Data, OpCodes.DataUnregisterCharRequest)] 12 | public class UnregisterCharacterRequest : BaseRequest 13 | { 14 | public override ValueTask> GetResponse(FragmentTcpSession session, FragmentMessage request) 15 | { 16 | return SingleMessage(new UnregisterCharacterResponse().Build()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Request/ChatLobby/GetLobbyServersExitRequest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using Fragment.NetSlum.Networking.Attributes; 4 | using Fragment.NetSlum.Networking.Constants; 5 | using Fragment.NetSlum.Networking.Objects; 6 | using Fragment.NetSlum.Networking.Packets.Response.ChatLobby; 7 | using Fragment.NetSlum.Networking.Sessions; 8 | 9 | namespace Fragment.NetSlum.Networking.Packets.Request.ChatLobby; 10 | 11 | [FragmentPacket(MessageType.Data, OpCodes.DataLobbyGetServersExit)] 12 | public class GetLobbyServersExitRequest : BaseRequest 13 | { 14 | public override ValueTask> GetResponse(FragmentTcpSession session, FragmentMessage request) 15 | { 16 | return SingleMessage(new LobbyGetServersExitResponse().Build()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Request/ChatLobby/GetLobbyServersRequest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using Fragment.NetSlum.Networking.Attributes; 4 | using Fragment.NetSlum.Networking.Constants; 5 | using Fragment.NetSlum.Networking.Objects; 6 | using Fragment.NetSlum.Networking.Packets.Response.ChatLobby; 7 | using Fragment.NetSlum.Networking.Sessions; 8 | 9 | namespace Fragment.NetSlum.Networking.Packets.Request.ChatLobby; 10 | 11 | [FragmentPacket(MessageType.Data, OpCodes.DataLobbyGetServers)] 12 | public class GetLobbyServersRequest : BaseRequest 13 | { 14 | public override ValueTask> GetResponse(FragmentTcpSession session, FragmentMessage request) 15 | { 16 | return SingleMessage(new LobbyGetServersResponse().Build()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Request/Guilds/DissolveGuildRequest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Threading.Tasks; 4 | using Fragment.NetSlum.Networking.Attributes; 5 | using Fragment.NetSlum.Networking.Constants; 6 | using Fragment.NetSlum.Networking.Objects; 7 | using Fragment.NetSlum.Networking.Packets.Response.Guilds; 8 | using Fragment.NetSlum.Networking.Sessions; 9 | using Fragment.NetSlum.Persistence; 10 | using Microsoft.EntityFrameworkCore; 11 | 12 | namespace Fragment.NetSlum.Networking.Packets.Request.Guilds; 13 | 14 | [FragmentPacket(MessageType.Data, OpCodes.DataDissolveGuild)] 15 | public class DissolveGuildRequest : BaseRequest 16 | { 17 | private readonly FragmentContext _database; 18 | 19 | public DissolveGuildRequest(FragmentContext database) 20 | { 21 | _database = database; 22 | } 23 | 24 | public override async ValueTask> GetResponse(FragmentTcpSession session, FragmentMessage request) 25 | { 26 | await _database.Guilds 27 | .Where(g => g.LeaderId == session.CharacterId) 28 | .ExecuteDeleteAsync(); 29 | 30 | return new[] { new DissolveGuildResponse().Build() }; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Request/Login/AreaServerDiskAuthorizationRequest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using Fragment.NetSlum.Networking.Attributes; 4 | using Fragment.NetSlum.Networking.Constants; 5 | using Fragment.NetSlum.Networking.Objects; 6 | using Fragment.NetSlum.Networking.Packets.Response.Login; 7 | using Fragment.NetSlum.Networking.Packets.Response; 8 | using Fragment.NetSlum.Networking.Sessions; 9 | using Microsoft.Extensions.Logging; 10 | 11 | namespace Fragment.NetSlum.Networking.Packets.Request.Login; 12 | 13 | [FragmentPacket(MessageType.Data, OpCodes.Data_AreaServerDiskAuthorizationRequest)] 14 | public class AreaServerDiskAuthorizationRequset : BaseRequest 15 | { 16 | private readonly ILogger _logger; 17 | 18 | public AreaServerDiskAuthorizationRequset(ILogger logger) 19 | { 20 | _logger = logger; 21 | } 22 | 23 | public override ValueTask> GetResponse(FragmentTcpSession session, FragmentMessage request) 24 | { 25 | BaseResponse response = new AreaServerDiskAuthorizationResponse(); 26 | return SingleMessage(response.Build()); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Request/Login/AreaServerShutdownRequest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using Fragment.NetSlum.Networking.Attributes; 4 | using Fragment.NetSlum.Networking.Constants; 5 | using Fragment.NetSlum.Networking.Objects; 6 | using Fragment.NetSlum.Networking.Packets.Response; 7 | using Fragment.NetSlum.Networking.Packets.Response.Login; 8 | using Fragment.NetSlum.Networking.Sessions; 9 | using Microsoft.Extensions.Logging; 10 | 11 | namespace Fragment.NetSlum.Networking.Packets.Request.Login; 12 | 13 | [FragmentPacket(MessageType.Data, OpCodes.AreaServerShutdownRequest)] 14 | public class AreaServerShutdownRequest : BaseRequest 15 | { 16 | private readonly ILogger _logger; 17 | 18 | public AreaServerShutdownRequest(ILogger logger) 19 | { 20 | _logger = logger; 21 | } 22 | 23 | public override ValueTask> GetResponse(FragmentTcpSession session, FragmentMessage request) 24 | { 25 | BaseResponse response = new AreaServerShutdownResponse(); 26 | 27 | return SingleMessage(response.Build()); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Request/Login/DiskAuthorizationRequest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using Fragment.NetSlum.Networking.Attributes; 4 | using Fragment.NetSlum.Networking.Constants; 5 | using Fragment.NetSlum.Networking.Objects; 6 | using Fragment.NetSlum.Networking.Packets.Response.Login; 7 | using Fragment.NetSlum.Networking.Packets.Response; 8 | using Fragment.NetSlum.Networking.Sessions; 9 | using Microsoft.Extensions.Logging; 10 | 11 | namespace Fragment.NetSlum.Networking.Packets.Request.Login; 12 | 13 | [FragmentPacket(MessageType.Data, OpCodes.DataDiskAuthorizationRequest)] 14 | public class DiskAuthorizationRequest : BaseRequest 15 | { 16 | private readonly ILogger _logger; 17 | 18 | public DiskAuthorizationRequest(ILogger logger) 19 | { 20 | _logger = logger; 21 | } 22 | 23 | public override ValueTask> GetResponse(FragmentTcpSession session, FragmentMessage request) 24 | { 25 | BaseResponse response = new DiskAuthorizationResponse(); 26 | 27 | return SingleMessage(response.Build()); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Request/Login/LogonRepeatRequest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using Fragment.NetSlum.Networking.Attributes; 4 | using Fragment.NetSlum.Networking.Constants; 5 | using Fragment.NetSlum.Networking.Objects; 6 | using Fragment.NetSlum.Networking.Packets.Response.Login; 7 | using Fragment.NetSlum.Networking.Packets.Response; 8 | using Fragment.NetSlum.Networking.Sessions; 9 | using Microsoft.Extensions.Logging; 10 | 11 | namespace Fragment.NetSlum.Networking.Packets.Request.Login; 12 | 13 | [FragmentPacket(MessageType.Data, OpCodes.DataLogonRepeatRequest)] 14 | public class LogonRepeatRequest :BaseRequest 15 | { 16 | private readonly ILogger _logger; 17 | 18 | public LogonRepeatRequest(ILogger logger) 19 | { 20 | _logger = logger; 21 | } 22 | 23 | public override ValueTask> GetResponse(FragmentTcpSession session, FragmentMessage request) 24 | { 25 | BaseResponse response = new LogonRepeatResponse(); 26 | 27 | return SingleMessage(response.Build()); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Request/Mail/SendGuildMailRequest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using Fragment.NetSlum.Networking.Attributes; 4 | using Fragment.NetSlum.Networking.Constants; 5 | using Fragment.NetSlum.Networking.Objects; 6 | using Fragment.NetSlum.Networking.Packets.Response.Mail; 7 | using Fragment.NetSlum.Networking.Sessions; 8 | using OpCodes = Fragment.NetSlum.Networking.Constants.OpCodes; 9 | 10 | namespace Fragment.NetSlum.Networking.Packets.Request.Mail; 11 | 12 | [FragmentPacket(MessageType.Data, OpCodes.DataGuildMailSend)] 13 | public class SendGuildMailRequest : BaseRequest 14 | { 15 | public override ValueTask> GetResponse(FragmentTcpSession session, FragmentMessage request) 16 | { 17 | return SingleMessage(new SendMailResponse().SetStatusCode(OpCodes.DataGuildMailSendOk).Build()); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Request/Misc/DataComRequest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using Fragment.NetSlum.Networking.Attributes; 4 | using Fragment.NetSlum.Networking.Constants; 5 | using Fragment.NetSlum.Networking.Objects; 6 | using Fragment.NetSlum.Networking.Packets.Response.Misc; 7 | using Fragment.NetSlum.Networking.Sessions; 8 | 9 | namespace Fragment.NetSlum.Networking.Packets.Request.Misc; 10 | 11 | [FragmentPacket(MessageType.Data, OpCodes.DataComRequest)] 12 | public class DataComRequest : BaseRequest 13 | { 14 | public override ValueTask> GetResponse(FragmentTcpSession session, FragmentMessage request) 15 | { 16 | return SingleMessage(new DataComResponse().Build()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Request/Misc/PingRequest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading.Tasks; 4 | using Fragment.NetSlum.Networking.Attributes; 5 | using Fragment.NetSlum.Networking.Constants; 6 | using Fragment.NetSlum.Networking.Objects; 7 | using Fragment.NetSlum.Networking.Packets.Response; 8 | using Fragment.NetSlum.Networking.Packets.Response.Misc; 9 | using Fragment.NetSlum.Networking.Sessions; 10 | 11 | namespace Fragment.NetSlum.Networking.Packets.Request.Misc; 12 | 13 | [FragmentPacket(MessageType.PingRequest)] 14 | [FragmentPacket(MessageType.Data, OpCodes.DataPing)] 15 | public class PingRequest : BaseRequest 16 | { 17 | public override ValueTask> GetResponse(FragmentTcpSession session, FragmentMessage request) 18 | { 19 | session.LastContacted = DateTime.UtcNow; 20 | 21 | BaseResponse response = new PingResponse(); 22 | 23 | return SingleMessage(response.Build()); 24 | 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Request/Misc/ReturnToDesktopRequest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using Fragment.NetSlum.Networking.Attributes; 4 | using Fragment.NetSlum.Networking.Constants; 5 | using Fragment.NetSlum.Networking.Objects; 6 | using Fragment.NetSlum.Networking.Packets.Response.Misc; 7 | using Fragment.NetSlum.Networking.Sessions; 8 | 9 | namespace Fragment.NetSlum.Networking.Packets.Request.Misc; 10 | 11 | [FragmentPacket(MessageType.Data, OpCodes.DataReturnToDesktop)] 12 | public class ReturnToDesktopRequest : BaseRequest 13 | { 14 | public override ValueTask> GetResponse(FragmentTcpSession session, FragmentMessage request) 15 | { 16 | return SingleMessage(new ReturnToDesktopResponse().Build()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Request/Misc/Unknown787ERequest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using Fragment.NetSlum.Networking.Attributes; 4 | using Fragment.NetSlum.Networking.Constants; 5 | using Fragment.NetSlum.Networking.Objects; 6 | using Fragment.NetSlum.Networking.Packets.Response.Misc; 7 | using Fragment.NetSlum.Networking.Sessions; 8 | 9 | namespace Fragment.NetSlum.Networking.Packets.Request.Misc; 10 | 11 | [FragmentPacket(MessageType.Data, OpCodes.DataUnknown787e)] 12 | public class Unknown787ERequest : BaseRequest 13 | { 14 | public override ValueTask> GetResponse(FragmentTcpSession session, FragmentMessage request) 15 | { 16 | return SingleMessage(new UnknownResponse(OpCodes.DataUnknown787fResponse).Build()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Request/Security/KeyExchangeAcknowledgementRequest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using Fragment.NetSlum.Networking.Attributes; 4 | using Fragment.NetSlum.Networking.Constants; 5 | using Fragment.NetSlum.Networking.Crypto; 6 | using Fragment.NetSlum.Networking.Objects; 7 | using Fragment.NetSlum.Networking.Sessions; 8 | 9 | namespace Fragment.NetSlum.Networking.Packets.Request.Security; 10 | 11 | [FragmentPacket(MessageType.KeyExchangeAcknowledgmentRequest)] 12 | public class KeyExchangeAcknowledgementRequest : BaseRequest 13 | { 14 | private readonly CryptoHandler _cryptoHandler; 15 | 16 | public KeyExchangeAcknowledgementRequest(CryptoHandler cryptoHandler) 17 | { 18 | _cryptoHandler = cryptoHandler; 19 | } 20 | 21 | public override ValueTask> GetResponse(FragmentTcpSession session, FragmentMessage request) 22 | { 23 | _cryptoHandler.ClientCipher.Initialize(); 24 | _cryptoHandler.ServerCipher.Initialize(); 25 | 26 | return NoResponse(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/AreaServer/AreaServerDateTimeResponse.cs: -------------------------------------------------------------------------------- 1 | using Fragment.NetSlum.Core.Buffers; 2 | using Fragment.NetSlum.Core.Extensions; 3 | using Fragment.NetSlum.Networking.Constants; 4 | using Fragment.NetSlum.Networking.Objects; 5 | using System; 6 | 7 | namespace Fragment.NetSlum.Networking.Packets.Response.AreaServer; 8 | 9 | public class AreaServerDateTimeResponse : BaseResponse 10 | { 11 | public override FragmentMessage Build() 12 | { 13 | var writer = new MemoryWriter(8); 14 | writer.Write((uint)0); 15 | writer.Write((uint)DateTime.UtcNow.ToEpoch()); 16 | 17 | return new FragmentMessage 18 | { 19 | MessageType = MessageType.Data, 20 | DataPacketType = OpCodes.Data_AreaServerDateTimeSuccess, 21 | Data = writer.Buffer, 22 | }; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/AreaServer/AreaServerFavoritesCountResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Buffers.Binary; 3 | using Fragment.NetSlum.Networking.Constants; 4 | using Fragment.NetSlum.Networking.Objects; 5 | 6 | namespace Fragment.NetSlum.Networking.Packets.Response.AreaServer; 7 | 8 | public class AreaServerFavoritesCountResponse : BaseResponse 9 | { 10 | private ushort _count { get; set; } 11 | 12 | public AreaServerFavoritesCountResponse(ushort count) 13 | { 14 | _count = count; 15 | } 16 | 17 | public override FragmentMessage Build() 18 | { 19 | var buffer = new Memory(new byte[2]); 20 | BinaryPrimitives.WriteUInt16BigEndian(buffer.Span, _count); 21 | 22 | return new FragmentMessage 23 | { 24 | MessageType = MessageType.Data, 25 | DataPacketType = OpCodes.DataLobbyFavoritesAsCount, 26 | Data = buffer, 27 | }; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/AreaServer/AreaServerIPAddressPortResponse.cs: -------------------------------------------------------------------------------- 1 | using Fragment.NetSlum.Networking.Constants; 2 | using Fragment.NetSlum.Networking.Objects; 3 | 4 | namespace Fragment.NetSlum.Networking.Packets.Response.AreaServer; 5 | 6 | public class AreaServerIPAddressPortResponse : BaseResponse 7 | { 8 | public override FragmentMessage Build() 9 | { 10 | return new FragmentMessage 11 | { 12 | MessageType = MessageType.Data, 13 | DataPacketType = OpCodes.Data_AreaServerIpPortSuccess, 14 | Data = new byte[] { 0x00, 0x00 }, 15 | }; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/AreaServer/AreaServerPublishDetailsResponse.cs: -------------------------------------------------------------------------------- 1 | using Fragment.NetSlum.Networking.Constants; 2 | using Fragment.NetSlum.Networking.Objects; 3 | 4 | 5 | namespace Fragment.NetSlum.Networking.Packets.Response.AreaServer; 6 | 7 | public class AreaServerPublishDetailsResponse :BaseResponse 8 | { 9 | public OpCodes PacketType { get; set; } 10 | public byte[] Data { get; set; } = []; 11 | 12 | public override FragmentMessage Build() 13 | { 14 | return new FragmentMessage 15 | { 16 | MessageType = MessageType.Data, 17 | DataPacketType = PacketType, 18 | Data = Data, 19 | }; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/AreaServer/AreaServerPublishResponse.cs: -------------------------------------------------------------------------------- 1 | using Fragment.NetSlum.Networking.Constants; 2 | using Fragment.NetSlum.Networking.Objects; 3 | 4 | namespace Fragment.NetSlum.Networking.Packets.Response.AreaServer; 5 | 6 | public class AreaServerPublishResponse :BaseResponse 7 | { 8 | public override FragmentMessage Build() 9 | { 10 | return new FragmentMessage 11 | { 12 | MessageType = MessageType.Data, 13 | DataPacketType = OpCodes.Data_AreaServerPublishSuccess, 14 | Data = new byte[] { 0x00, 0x09 }, 15 | }; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Articles/ArticleCheckResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Buffers.Binary; 3 | using Fragment.NetSlum.Networking.Constants; 4 | using Fragment.NetSlum.Networking.Objects; 5 | 6 | namespace Fragment.NetSlum.Networking.Packets.Response.Articles; 7 | 8 | public class ArticleCheckResponse : BaseResponse 9 | { 10 | private bool _articlesAvailable; 11 | 12 | public ArticleCheckResponse ArticlesAvailable(bool available) 13 | { 14 | _articlesAvailable = available; 15 | 16 | return this; 17 | } 18 | 19 | public override FragmentMessage Build() 20 | { 21 | var buffer = new Memory(new byte[2]); 22 | BinaryPrimitives.WriteUInt16BigEndian(buffer.Span, (ushort)(_articlesAvailable ? 0x01 : 0x00)); 23 | 24 | return new FragmentMessage 25 | { 26 | MessageType = MessageType.Data, 27 | DataPacketType = OpCodes.DataNewCheckSuccess, 28 | Data = buffer, 29 | }; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Articles/GetNewsPostErrorResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Fragment.NetSlum.Networking.Constants; 3 | using Fragment.NetSlum.Networking.Objects; 4 | 5 | namespace Fragment.NetSlum.Networking.Packets.Response.Articles; 6 | 7 | public class GetNewsPostErrorResponse : BaseResponse 8 | { 9 | public override FragmentMessage Build() 10 | { 11 | return new FragmentMessage 12 | { 13 | MessageType = MessageType.Data, 14 | DataPacketType = OpCodes.DataNewsPostErrorResponse, 15 | Data = new Memory(new byte[2]), 16 | }; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Articles/NewsArticleCountResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Buffers.Binary; 3 | using Fragment.NetSlum.Networking.Constants; 4 | using Fragment.NetSlum.Networking.Objects; 5 | 6 | namespace Fragment.NetSlum.Networking.Packets.Response.Articles; 7 | 8 | public class NewsArticleCountResponse : BaseResponse 9 | { 10 | private readonly ushort _count; 11 | 12 | public NewsArticleCountResponse(ushort count) 13 | { 14 | _count = count; 15 | } 16 | 17 | public override FragmentMessage Build() 18 | { 19 | var buffer = new Memory(new byte[2]); 20 | BinaryPrimitives.WriteUInt16BigEndian(buffer.Span, _count); 21 | 22 | return new FragmentMessage 23 | { 24 | MessageType = MessageType.Data, 25 | DataPacketType = OpCodes.DataNewsArticleList, 26 | Data = buffer, 27 | }; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Articles/NewsCategoryCountResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Buffers.Binary; 3 | using Fragment.NetSlum.Networking.Constants; 4 | using Fragment.NetSlum.Networking.Objects; 5 | 6 | namespace Fragment.NetSlum.Networking.Packets.Response.Articles; 7 | 8 | public class NewsCategoryCountResponse : BaseResponse 9 | { 10 | private readonly ushort _count; 11 | 12 | public NewsCategoryCountResponse(ushort count) 13 | { 14 | _count = count; 15 | } 16 | 17 | public override FragmentMessage Build() 18 | { 19 | var buffer = new Memory(new byte[2]); 20 | BinaryPrimitives.WriteUInt16BigEndian(buffer.Span, _count); 21 | 22 | return new FragmentMessage 23 | { 24 | MessageType = MessageType.Data, 25 | DataPacketType = OpCodes.DataNewsCategoryList, 26 | Data = buffer, 27 | }; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Articles/NewsPostImageSizeResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Buffers.Binary; 3 | using Fragment.NetSlum.Networking.Constants; 4 | using Fragment.NetSlum.Networking.Objects; 5 | 6 | namespace Fragment.NetSlum.Networking.Packets.Response.Articles; 7 | 8 | public class NewsPostImageSizeResponse : BaseResponse 9 | { 10 | private readonly uint _imageSize; 11 | private readonly ushort _chunkSize; 12 | 13 | public NewsPostImageSizeResponse(uint imageSize, ushort chunkSize) 14 | { 15 | _imageSize = imageSize; 16 | _chunkSize = chunkSize; 17 | } 18 | 19 | public override FragmentMessage Build() 20 | { 21 | var buffer = new Memory(new byte[sizeof(uint) + sizeof(ushort)]); 22 | var bufferSpan = buffer.Span; 23 | 24 | BinaryPrimitives.WriteUInt32BigEndian(bufferSpan, _imageSize); 25 | BinaryPrimitives.WriteUInt16BigEndian(bufferSpan[4..], _chunkSize); 26 | 27 | return new FragmentMessage 28 | { 29 | MessageType = MessageType.Data, 30 | DataPacketType = OpCodes.DataNewsPostSizeInfoResponse, 31 | Data = buffer 32 | }; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/BBS/BbsCategoryCountResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Buffers.Binary; 3 | using Fragment.NetSlum.Networking.Constants; 4 | using Fragment.NetSlum.Networking.Objects; 5 | 6 | namespace Fragment.NetSlum.Networking.Packets.Response.BBS; 7 | 8 | public class BbsCategoryCountResponse : BaseResponse 9 | { 10 | private readonly ushort _numEntries; 11 | 12 | public BbsCategoryCountResponse(ushort numEntries) 13 | { 14 | _numEntries = numEntries; 15 | } 16 | 17 | public override FragmentMessage Build() 18 | { 19 | var buffer = new Memory(new byte[2]); 20 | BinaryPrimitives.WriteUInt16BigEndian(buffer.Span, _numEntries); 21 | 22 | return new FragmentMessage 23 | { 24 | MessageType = MessageType.Data, 25 | DataPacketType = OpCodes.DataBbsCategoryCountResponse, 26 | Data = buffer, 27 | }; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/BBS/BbsCategoryEntryResponse.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | using Fragment.NetSlum.Core.Buffers; 3 | using Fragment.NetSlum.Core.Extensions; 4 | using Fragment.NetSlum.Networking.Constants; 5 | using Fragment.NetSlum.Networking.Objects; 6 | 7 | namespace Fragment.NetSlum.Networking.Packets.Response.BBS; 8 | 9 | public class BbsCategoryEntryResponse : BaseResponse 10 | { 11 | private ushort _categoryId; 12 | private string _categoryTitle = ""; 13 | 14 | public BbsCategoryEntryResponse SetCategoryId(ushort id) 15 | { 16 | _categoryId = id; 17 | 18 | return this; 19 | } 20 | 21 | public BbsCategoryEntryResponse SetCategoryTitle(string title) 22 | { 23 | _categoryTitle = title; 24 | 25 | return this; 26 | } 27 | 28 | public override FragmentMessage Build() 29 | { 30 | var titleBytes = _categoryTitle.ToShiftJis(); 31 | 32 | var writer = new MemoryWriter(titleBytes.Length + Marshal.SizeOf(_categoryId)); 33 | writer.Write(_categoryId); 34 | writer.Write(titleBytes); 35 | 36 | return new FragmentMessage 37 | { 38 | MessageType = MessageType.Data, 39 | DataPacketType = OpCodes.DataBbsEntryCategory, 40 | Data = writer.Buffer, 41 | }; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/BBS/BbsPostContentResponse.cs: -------------------------------------------------------------------------------- 1 | using Fragment.NetSlum.Core.Buffers; 2 | using Fragment.NetSlum.Core.Extensions; 3 | using Fragment.NetSlum.Networking.Constants; 4 | using Fragment.NetSlum.Networking.Objects; 5 | 6 | namespace Fragment.NetSlum.Networking.Packets.Response.BBS; 7 | 8 | public class BbsPostContentResponse : BaseResponse 9 | { 10 | private int _postId; 11 | private string _postContent = null!; 12 | 13 | public BbsPostContentResponse SetPostId(int id) 14 | { 15 | _postId = id; 16 | 17 | return this; 18 | } 19 | 20 | public BbsPostContentResponse SetContent(string content) 21 | { 22 | _postContent = content; 23 | 24 | return this; 25 | } 26 | 27 | public override FragmentMessage Build() 28 | { 29 | var contentBytes = _postContent.ToShiftJis(); 30 | 31 | var writer = new MemoryWriter(contentBytes.Length + sizeof(int)); 32 | 33 | writer.Write(_postId); 34 | writer.Write(contentBytes); 35 | 36 | return new FragmentMessage 37 | { 38 | MessageType = MessageType.Data, 39 | DataPacketType = OpCodes.DataBbsPostContentResponse, 40 | Data = writer.Buffer, 41 | }; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/BBS/BbsThreadCountResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Buffers.Binary; 3 | using Fragment.NetSlum.Networking.Constants; 4 | using Fragment.NetSlum.Networking.Objects; 5 | 6 | namespace Fragment.NetSlum.Networking.Packets.Response.BBS; 7 | 8 | public class BbsThreadCountResponse : BaseResponse 9 | { 10 | private readonly ushort _numEntries; 11 | 12 | public BbsThreadCountResponse(ushort numEntries) 13 | { 14 | _numEntries = numEntries; 15 | } 16 | 17 | public override FragmentMessage Build() 18 | { 19 | var buffer = new Memory(new byte[2]); 20 | BinaryPrimitives.WriteUInt16BigEndian(buffer.Span, _numEntries); 21 | 22 | return new FragmentMessage 23 | { 24 | MessageType = MessageType.Data, 25 | DataPacketType = OpCodes.DataBbsThreadCountResponse, 26 | Data = buffer, 27 | }; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/BBS/BbsThreadEntryResponse.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | using Fragment.NetSlum.Core.Buffers; 3 | using Fragment.NetSlum.Core.Extensions; 4 | using Fragment.NetSlum.Networking.Constants; 5 | using Fragment.NetSlum.Networking.Objects; 6 | 7 | namespace Fragment.NetSlum.Networking.Packets.Response.BBS; 8 | 9 | public class BbsThreadEntryResponse : BaseResponse 10 | { 11 | private int _threadId; 12 | private string _threadTitle = ""; 13 | 14 | public BbsThreadEntryResponse SetThreadId(int id) 15 | { 16 | _threadId = id; 17 | 18 | return this; 19 | } 20 | 21 | public BbsThreadEntryResponse SetThreadTitle(string title) 22 | { 23 | _threadTitle = title; 24 | 25 | return this; 26 | } 27 | 28 | public override FragmentMessage Build() 29 | { 30 | var titleBytes = _threadTitle.ToShiftJis(); 31 | 32 | var writer = new MemoryWriter(titleBytes.Length + Marshal.SizeOf(_threadId)); 33 | writer.Write(_threadId); 34 | writer.Write(titleBytes); 35 | 36 | return new FragmentMessage 37 | { 38 | MessageType = MessageType.Data, 39 | DataPacketType = OpCodes.DataBbsEntryThread, 40 | Data = writer.Buffer, 41 | }; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/BBS/BbsThreadPostCountResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Buffers.Binary; 3 | using Fragment.NetSlum.Networking.Constants; 4 | using Fragment.NetSlum.Networking.Objects; 5 | 6 | namespace Fragment.NetSlum.Networking.Packets.Response.BBS; 7 | 8 | public class BbsThreadPostCountResponse : BaseResponse 9 | { 10 | private readonly uint _numEntries; 11 | 12 | public BbsThreadPostCountResponse(uint numEntries) 13 | { 14 | _numEntries = numEntries; 15 | } 16 | 17 | public override FragmentMessage Build() 18 | { 19 | var buffer = new Memory(new byte[4]); 20 | BinaryPrimitives.WriteUInt32BigEndian(buffer.Span, _numEntries); 21 | 22 | return new FragmentMessage 23 | { 24 | MessageType = MessageType.Data, 25 | DataPacketType = OpCodes.DataBbsThreadPostCountResponse, 26 | Data = buffer, 27 | }; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/BBS/CheckCreateBBSThreadResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Buffers.Binary; 3 | using Fragment.NetSlum.Networking.Constants; 4 | using Fragment.NetSlum.Networking.Objects; 5 | 6 | namespace Fragment.NetSlum.Networking.Packets.Response.BBS; 7 | 8 | public class CheckCreateBBSThreadResponse : BaseResponse 9 | { 10 | public override FragmentMessage Build() 11 | { 12 | var buffer = new Memory(new byte[2]); 13 | BinaryPrimitives.WriteUInt16BigEndian(buffer.Span, 0x0192); 14 | 15 | return new FragmentMessage 16 | { 17 | MessageType = MessageType.Data, 18 | DataPacketType = OpCodes.DataBbsCheckThreadCreateResponse, 19 | Data = buffer, 20 | }; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/BBS/CreateBBSPostResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Fragment.NetSlum.Networking.Constants; 3 | using Fragment.NetSlum.Networking.Objects; 4 | 5 | namespace Fragment.NetSlum.Networking.Packets.Response.BBS; 6 | 7 | public class CreateBBSPostResponse : BaseResponse 8 | { 9 | public override FragmentMessage Build() => new FragmentMessage 10 | { 11 | MessageType = MessageType.Data, 12 | DataPacketType = OpCodes.DataBbsCreatePostResponse, 13 | Data = new Memory(new byte[2]), 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/BBS/GetBBSUpdatesResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Fragment.NetSlum.Networking.Constants; 3 | using Fragment.NetSlum.Networking.Objects; 4 | 5 | namespace Fragment.NetSlum.Networking.Packets.Response.BBS; 6 | 7 | public class GetBBSUpdatesResponse:BaseResponse 8 | { 9 | public override FragmentMessage Build() 10 | { 11 | return new FragmentMessage 12 | { 13 | MessageType = MessageType.Data, 14 | DataPacketType = OpCodes.DataBBSGetUpdatesSuccess, 15 | Data = new Memory([0x00, 0x00]), 16 | }; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/BaseResponse.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | using Fragment.NetSlum.Networking.Constants; 3 | using Fragment.NetSlum.Networking.Objects; 4 | using Serilog; 5 | 6 | namespace Fragment.NetSlum.Networking.Packets.Response; 7 | 8 | public abstract class BaseResponse 9 | { 10 | public ILogger Log => Serilog.Log.ForContext(GetType()); 11 | 12 | public abstract FragmentMessage Build(); 13 | 14 | [MethodImpl(MethodImplOptions.AggressiveOptimization)] 15 | public FragmentMessage Build(MessageType type, byte[] payload) 16 | { 17 | return new FragmentMessage 18 | { 19 | Data = payload, 20 | MessageType = type, 21 | }; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Character/RegisterCharacterResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Buffers.Binary; 3 | using Fragment.NetSlum.Core.Constants; 4 | using Fragment.NetSlum.Networking.Constants; 5 | using Fragment.NetSlum.Networking.Objects; 6 | 7 | namespace Fragment.NetSlum.Networking.Packets.Response.Character; 8 | 9 | public class RegisterCharacterResponse : BaseResponse 10 | { 11 | private GuildStatus _guildStatus = GuildStatus.None; 12 | private ushort _guildId; 13 | 14 | public RegisterCharacterResponse SetGuildStatus(GuildStatus status) 15 | { 16 | _guildStatus = status; 17 | 18 | return this; 19 | } 20 | 21 | public RegisterCharacterResponse SetGuildId(ushort gid) 22 | { 23 | _guildId = gid; 24 | 25 | return this; 26 | } 27 | 28 | public override FragmentMessage Build() 29 | { 30 | var buffer = new Memory(new byte[3]); 31 | var bufferSpan = buffer.Span; 32 | 33 | bufferSpan[0] = (byte)_guildStatus; 34 | BinaryPrimitives.WriteUInt16BigEndian(bufferSpan[1..], _guildId); 35 | 36 | return new FragmentMessage 37 | { 38 | MessageType = MessageType.Data, 39 | DataPacketType = OpCodes.DataRegisterCharSuccess, 40 | Data = buffer, 41 | }; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Character/Select2CharacterResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Fragment.NetSlum.Networking.Constants; 3 | using Fragment.NetSlum.Networking.Objects; 4 | 5 | namespace Fragment.NetSlum.Networking.Packets.Response.Character; 6 | 7 | public class Select2CharacterResponse : BaseResponse 8 | { 9 | public override FragmentMessage Build() 10 | { 11 | return new FragmentMessage 12 | { 13 | MessageType = MessageType.Data, 14 | DataPacketType = OpCodes.Data_Select2_CharacterSuccess, 15 | Data = new Memory([0x30, 0x30, 0x30, 0x30]), // Apparently represents "0000" literally 16 | }; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Character/SelectCharacterResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Fragment.NetSlum.Networking.Constants; 3 | using Fragment.NetSlum.Networking.Objects; 4 | 5 | namespace Fragment.NetSlum.Networking.Packets.Response.Character; 6 | 7 | public class SelectCharacterResponse : BaseResponse 8 | { 9 | public override FragmentMessage Build() 10 | { 11 | return new FragmentMessage 12 | { 13 | MessageType = MessageType.Data, 14 | DataPacketType = OpCodes.DataSelectCharSuccess, 15 | Data = new Memory(new byte[2]), 16 | }; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Character/UnregisterCharacterResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Fragment.NetSlum.Networking.Constants; 3 | using Fragment.NetSlum.Networking.Objects; 4 | 5 | namespace Fragment.NetSlum.Networking.Packets.Response.Character; 6 | 7 | public class UnregisterCharacterResponse : BaseResponse 8 | { 9 | public override FragmentMessage Build() 10 | { 11 | return new FragmentMessage 12 | { 13 | MessageType = MessageType.Data, 14 | DataPacketType = OpCodes.DataUnregisterCharSuccess, 15 | Data = new Memory(new byte[2]), 16 | }; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/ChatLobby/ChatLobbyCountResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Fragment.NetSlum.Networking.Constants; 3 | using Fragment.NetSlum.Networking.Objects; 4 | using System.Buffers.Binary; 5 | 6 | namespace Fragment.NetSlum.Networking.Packets.Response.ChatLobby; 7 | 8 | public class ChatLobbyCountResponse:BaseResponse 9 | { 10 | private ushort _chatLobbyCount; 11 | public ChatLobbyCountResponse SetChatLobbyCount(ushort count) 12 | { 13 | _chatLobbyCount = count; 14 | 15 | return this; 16 | } 17 | 18 | 19 | public override FragmentMessage Build() 20 | { 21 | var buffer = new Memory(new byte[2]); 22 | var bufferSpan = buffer.Span; 23 | 24 | BinaryPrimitives.WriteUInt16BigEndian(bufferSpan[0..], _chatLobbyCount); 25 | return new FragmentMessage 26 | { 27 | MessageType = MessageType.Data, 28 | DataPacketType = OpCodes.DataLobbyLobbyList, 29 | Data =buffer, 30 | }; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/ChatLobby/ChatLobbyEnterRoomResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Fragment.NetSlum.Networking.Constants; 3 | using Fragment.NetSlum.Networking.Objects; 4 | using System.Buffers.Binary; 5 | 6 | namespace Fragment.NetSlum.Networking.Packets.Response.ChatLobby; 7 | 8 | public class ChatLobbyEnterRoomResponse:BaseResponse 9 | { 10 | private ushort _clientCount { get; set; } 11 | public ChatLobbyEnterRoomResponse SetClientCount(ushort count) 12 | { 13 | _clientCount = count; 14 | return this; 15 | } 16 | 17 | public override FragmentMessage Build() 18 | { 19 | 20 | var bufferMemory = new Memory(new byte[2]); 21 | var buffer = bufferMemory.Span; 22 | 23 | BinaryPrimitives.WriteUInt16BigEndian(buffer, _clientCount); 24 | 25 | return new FragmentMessage 26 | { 27 | MessageType = MessageType.Data, 28 | DataPacketType = OpCodes.DataLobbyEnterRoomSuccess, 29 | Data = bufferMemory, 30 | }; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/ChatLobby/ChatLobbyStatusUpdateResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Fragment.NetSlum.Core.Buffers; 3 | using Fragment.NetSlum.Networking.Constants; 4 | using Fragment.NetSlum.Networking.Objects; 5 | 6 | namespace Fragment.NetSlum.Networking.Packets.Response.ChatLobby; 7 | 8 | public class ChatLobbyStatusUpdateResponse:BaseResponse 9 | { 10 | private ushort _playerIndex; 11 | private Memory _lastStatus = Array.Empty(); 12 | 13 | public ChatLobbyStatusUpdateResponse SetPlayerIndex(ushort playerIndex) 14 | { 15 | _playerIndex = playerIndex; 16 | 17 | return this; 18 | } 19 | 20 | public ChatLobbyStatusUpdateResponse SetLastStatus(Memory status) 21 | { 22 | _lastStatus = status; 23 | return this; 24 | } 25 | 26 | public override FragmentMessage Build() 27 | { 28 | var writer = new MemoryWriter(sizeof(ushort) * 2 + _lastStatus.Length); 29 | writer.Write(_playerIndex); 30 | writer.Write((ushort)_lastStatus.Length); 31 | writer.Write(_lastStatus); 32 | 33 | return new FragmentMessage 34 | { 35 | MessageType = MessageType.Data, 36 | DataPacketType = OpCodes.DataLobbyStatusUpdate, 37 | Data = writer.Buffer, 38 | }; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/ChatLobby/ClientLeftChatLobbyResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Buffers.Binary; 3 | using Fragment.NetSlum.Networking.Constants; 4 | using Fragment.NetSlum.Networking.Objects; 5 | 6 | namespace Fragment.NetSlum.Networking.Packets.Response.ChatLobby; 7 | 8 | public class ClientLeftChatLobbyResponse : BaseResponse 9 | { 10 | private readonly ushort _clientIdx; 11 | 12 | public ClientLeftChatLobbyResponse(ushort clientIdx) 13 | { 14 | _clientIdx = clientIdx; 15 | } 16 | 17 | public override FragmentMessage Build() 18 | { 19 | var buffer = new Memory(new byte[2]); 20 | BinaryPrimitives.WriteUInt16BigEndian(buffer.Span, _clientIdx); 21 | 22 | return new FragmentMessage 23 | { 24 | MessageType = MessageType.Data, 25 | DataPacketType = OpCodes.ClientLeavingLobby, 26 | Data = buffer, 27 | }; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/ChatLobby/CreateLobbyChatroomResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Buffers.Binary; 3 | using Fragment.NetSlum.Networking.Constants; 4 | using Fragment.NetSlum.Networking.Objects; 5 | 6 | namespace Fragment.NetSlum.Networking.Packets.Response.ChatLobby; 7 | 8 | public class CreateLobbyChatroomResponse : BaseResponse 9 | { 10 | private readonly ushort _lobbyId; 11 | 12 | public CreateLobbyChatroomResponse(ushort lobbyId) 13 | { 14 | _lobbyId = lobbyId; 15 | } 16 | 17 | public override FragmentMessage Build() 18 | { 19 | var buffer = new Memory(new byte[2]); 20 | BinaryPrimitives.WriteUInt16BigEndian(buffer.Span, _lobbyId); 21 | 22 | return new FragmentMessage 23 | { 24 | MessageType = MessageType.Data, 25 | DataPacketType = OpCodes.DataLobbyChatroomCreateOk, 26 | Data = buffer, 27 | }; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/ChatLobby/LobbyChatroomCategoryCountResponse.cs: -------------------------------------------------------------------------------- 1 | using Fragment.NetSlum.Core.Buffers; 2 | using Fragment.NetSlum.Networking.Constants; 3 | using Fragment.NetSlum.Networking.Objects; 4 | 5 | namespace Fragment.NetSlum.Networking.Packets.Response.ChatLobby; 6 | 7 | public class LobbyChatroomCategoryCountResponse : BaseResponse 8 | { 9 | private readonly ushort _numLobbies; 10 | 11 | public LobbyChatroomCategoryCountResponse(ushort numLobbies) 12 | { 13 | _numLobbies = numLobbies; 14 | } 15 | 16 | public override FragmentMessage Build() 17 | { 18 | var writer = new MemoryWriter(sizeof(ushort)*6); 19 | writer.Write((ushort)1); 20 | writer.Write(_numLobbies); 21 | writer.Write((ushort)1); 22 | writer.Write((ushort)1); 23 | writer.Write((ushort)1); 24 | 25 | return new FragmentMessage 26 | { 27 | MessageType = MessageType.Data, 28 | DataPacketType = OpCodes.DataLobbyChatroomCategory, 29 | Data = writer.Buffer, 30 | }; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/ChatLobby/LobbyExitResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Fragment.NetSlum.Networking.Constants; 3 | using Fragment.NetSlum.Networking.Objects; 4 | 5 | namespace Fragment.NetSlum.Networking.Packets.Response.ChatLobby 6 | { 7 | public class LobbyExitResponse:BaseResponse 8 | { 9 | public override FragmentMessage Build() 10 | { 11 | return new FragmentMessage 12 | { 13 | MessageType = MessageType.Data, 14 | DataPacketType = OpCodes.DataLobbyExitRoomOk, 15 | Data = new Memory(new byte[2]), 16 | }; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/ChatLobby/LobbyGetServersExitResponse.cs: -------------------------------------------------------------------------------- 1 | using Fragment.NetSlum.Networking.Constants; 2 | using Fragment.NetSlum.Networking.Objects; 3 | 4 | namespace Fragment.NetSlum.Networking.Packets.Response.ChatLobby; 5 | 6 | public class LobbyGetServersExitResponse : BaseResponse 7 | { 8 | public override FragmentMessage Build() 9 | { 10 | return new FragmentMessage 11 | { 12 | MessageType = MessageType.Data, 13 | DataPacketType = OpCodes.DataLobbyGetServersExitOk, 14 | Data = new byte[2], 15 | }; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/ChatLobby/LobbyGetServersResponse.cs: -------------------------------------------------------------------------------- 1 | using Fragment.NetSlum.Networking.Constants; 2 | using Fragment.NetSlum.Networking.Objects; 3 | 4 | namespace Fragment.NetSlum.Networking.Packets.Response.ChatLobby; 5 | 6 | public class LobbyGetServersResponse : BaseResponse 7 | { 8 | public override FragmentMessage Build() 9 | { 10 | return new FragmentMessage 11 | { 12 | MessageType = MessageType.Data, 13 | DataPacketType = OpCodes.DataLobbyGetServersOk, 14 | Data = new byte[2] 15 | }; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/ChatLobby/LobbyServerCategoryCountResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Buffers.Binary; 3 | using Fragment.NetSlum.Networking.Constants; 4 | using Fragment.NetSlum.Networking.Objects; 5 | 6 | namespace Fragment.NetSlum.Networking.Packets.Response.ChatLobby; 7 | 8 | public class LobbyServerCategoryCountResponse : BaseResponse 9 | { 10 | private readonly ushort _count; 11 | 12 | public LobbyServerCategoryCountResponse(ushort count) 13 | { 14 | _count = count; 15 | } 16 | 17 | public override FragmentMessage Build() 18 | { 19 | var buffer = new Memory(new byte[2]); 20 | BinaryPrimitives.WriteUInt16BigEndian(buffer.Span, _count); 21 | 22 | return new FragmentMessage 23 | { 24 | MessageType = MessageType.Data, 25 | DataPacketType = OpCodes.DataLobbyGetServersCategoryList, 26 | Data = buffer, 27 | }; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/ChatLobby/LobbyServerCategoryEntryResponse.cs: -------------------------------------------------------------------------------- 1 | using Fragment.NetSlum.Core.Buffers; 2 | using Fragment.NetSlum.Core.Extensions; 3 | using Fragment.NetSlum.Networking.Constants; 4 | using Fragment.NetSlum.Networking.Objects; 5 | 6 | namespace Fragment.NetSlum.Networking.Packets.Response.ChatLobby; 7 | 8 | public class LobbyServerCategoryEntryResponse : BaseResponse 9 | { 10 | private ushort _id; 11 | private string _name = ""; 12 | 13 | public LobbyServerCategoryEntryResponse SetCategoryId(ushort id) 14 | { 15 | _id = id; 16 | 17 | return this; 18 | } 19 | 20 | public LobbyServerCategoryEntryResponse SetCategoryName(string name) 21 | { 22 | _name = name; 23 | 24 | return this; 25 | } 26 | 27 | public override FragmentMessage Build() 28 | { 29 | 30 | var nameBytes = _name.ToShiftJis(); 31 | var writer = new MemoryWriter(nameBytes.Length + sizeof(ushort)); 32 | writer.Write(_id); 33 | writer.Write(nameBytes); 34 | 35 | return new FragmentMessage 36 | { 37 | MessageType = MessageType.Data, 38 | DataPacketType = OpCodes.DataLobbyGetServersEntryCategory, 39 | Data = writer.Buffer, 40 | }; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/ChatLobby/LobbyServerEntryCountResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Buffers.Binary; 3 | using Fragment.NetSlum.Networking.Constants; 4 | using Fragment.NetSlum.Networking.Objects; 5 | 6 | namespace Fragment.NetSlum.Networking.Packets.Response.ChatLobby; 7 | 8 | public class LobbyServerEntryCountResponse : BaseResponse 9 | { 10 | private readonly ushort _serverCount; 11 | 12 | public LobbyServerEntryCountResponse(ushort serverCount) 13 | { 14 | _serverCount = serverCount; 15 | } 16 | 17 | public override FragmentMessage Build() 18 | { 19 | var buffer = new Memory(new byte[2]); 20 | BinaryPrimitives.WriteUInt16BigEndian(buffer.Span, _serverCount); 21 | 22 | return new FragmentMessage 23 | { 24 | MessageType = MessageType.Data, 25 | DataPacketType = OpCodes.DataLobbyGetServersServerList, 26 | Data = buffer, 27 | }; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Guilds/CreateGuildResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Buffers.Binary; 3 | using Fragment.NetSlum.Networking.Constants; 4 | using Fragment.NetSlum.Networking.Objects; 5 | 6 | namespace Fragment.NetSlum.Networking.Packets.Response.Guilds; 7 | 8 | public class CreateGuildResponse : BaseResponse 9 | { 10 | private readonly ushort _guildId; 11 | 12 | public CreateGuildResponse(ushort guildId) 13 | { 14 | _guildId = guildId; 15 | } 16 | 17 | public override FragmentMessage Build() 18 | { 19 | var buffer = new Memory(new byte[2]); 20 | BinaryPrimitives.WriteUInt16BigEndian(buffer.Span, _guildId); 21 | 22 | return new FragmentMessage 23 | { 24 | MessageType = MessageType.Data, 25 | DataPacketType = OpCodes.DataCreateGuildSuccessResponse, 26 | Data = buffer, 27 | }; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Guilds/DissolveGuildResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Fragment.NetSlum.Networking.Constants; 3 | using Fragment.NetSlum.Networking.Objects; 4 | 5 | namespace Fragment.NetSlum.Networking.Packets.Response.Guilds; 6 | 7 | public class DissolveGuildResponse : BaseResponse 8 | { 9 | public override FragmentMessage Build() 10 | { 11 | return new FragmentMessage 12 | { 13 | MessageType = MessageType.Data, 14 | DataPacketType = OpCodes.DataDissolveGuildResponse, 15 | Data = new Memory(new byte[2]), 16 | }; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Guilds/DonateCoinsToGuildResponse.cs: -------------------------------------------------------------------------------- 1 | using Fragment.NetSlum.Core.Buffers; 2 | using Fragment.NetSlum.Networking.Constants; 3 | using Fragment.NetSlum.Networking.Objects; 4 | 5 | namespace Fragment.NetSlum.Networking.Packets.Response.Guilds; 6 | 7 | public class DonateCoinsToGuildResponse : BaseResponse 8 | { 9 | private ushort _goldDonated; 10 | private ushort _silverDonated; 11 | private ushort _bronzeDonated; 12 | 13 | public DonateCoinsToGuildResponse(ushort gold = 0, ushort silver = 0, ushort bronze = 0) 14 | { 15 | _goldDonated = gold; 16 | _silverDonated = silver; 17 | _bronzeDonated = bronze; 18 | } 19 | 20 | public override FragmentMessage Build() 21 | { 22 | var writer = new MemoryWriter(sizeof(ushort) * 3); 23 | writer.Write(_goldDonated); 24 | writer.Write(_silverDonated); 25 | writer.Write(_bronzeDonated); 26 | 27 | return new FragmentMessage 28 | { 29 | MessageType = MessageType.Data, 30 | DataPacketType = OpCodes.DataDonateCoinsToGuildResponse, 31 | Data = writer.Buffer, 32 | }; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Guilds/GuildInvitationResultConfirmationResponse.cs: -------------------------------------------------------------------------------- 1 | using Fragment.NetSlum.Core.Buffers; 2 | using Fragment.NetSlum.Networking.Constants; 3 | using Fragment.NetSlum.Networking.Objects; 4 | 5 | namespace Fragment.NetSlum.Networking.Packets.Response.Guilds; 6 | 7 | public class GuildInvitationResultConfirmationResponse : BaseResponse 8 | { 9 | private readonly ushort _responseCode; 10 | 11 | public GuildInvitationResultConfirmationResponse(ushort responseCode) 12 | { 13 | _responseCode = responseCode; 14 | } 15 | public override FragmentMessage Build() 16 | { 17 | var writer = new MemoryWriter(sizeof(ushort)); 18 | writer.Write(_responseCode); 19 | 20 | return new FragmentMessage 21 | { 22 | MessageType = MessageType.Data, 23 | DataPacketType = OpCodes.DataGuildInvitationConfirmationResponse, 24 | Data = writer.Buffer, 25 | }; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Guilds/GuildItemListCountResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Buffers.Binary; 3 | using Fragment.NetSlum.Networking.Constants; 4 | using Fragment.NetSlum.Networking.Objects; 5 | 6 | namespace Fragment.NetSlum.Networking.Packets.Response.Guilds; 7 | 8 | public class GuildItemListCountResponse : BaseResponse 9 | { 10 | private readonly ushort _numItems; 11 | 12 | public GuildItemListCountResponse(ushort numItems) 13 | { 14 | _numItems = numItems; 15 | } 16 | 17 | public override FragmentMessage Build() 18 | { 19 | var buffer = new Memory(new byte[2]); 20 | BinaryPrimitives.WriteUInt16BigEndian(buffer.Span, _numItems); 21 | 22 | return new FragmentMessage 23 | { 24 | MessageType = MessageType.Data, 25 | DataPacketType = OpCodes.DataGuildItemListCountResponse, 26 | Data = buffer, 27 | }; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Guilds/GuildListEntryCountResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Buffers.Binary; 3 | using Fragment.NetSlum.Networking.Constants; 4 | using Fragment.NetSlum.Networking.Objects; 5 | 6 | namespace Fragment.NetSlum.Networking.Packets.Response.Guilds; 7 | 8 | public class GuildListEntryCountResponse : BaseResponse 9 | { 10 | private readonly ushort _numEntries; 11 | 12 | public GuildListEntryCountResponse(ushort numEntries) 13 | { 14 | _numEntries = numEntries; 15 | } 16 | 17 | public override FragmentMessage Build() 18 | { 19 | var buffer = new Memory(new byte[2]); 20 | BinaryPrimitives.WriteUInt16BigEndian(buffer.Span, _numEntries); 21 | 22 | return new FragmentMessage 23 | { 24 | MessageType = MessageType.Data, 25 | DataPacketType = OpCodes.Data_GuildListEntryCountResponse, 26 | Data = buffer, 27 | }; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Guilds/GuildMemberListCategoryCountResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Buffers.Binary; 3 | using Fragment.NetSlum.Networking.Constants; 4 | using Fragment.NetSlum.Networking.Objects; 5 | 6 | namespace Fragment.NetSlum.Networking.Packets.Response.Guilds; 7 | 8 | public class GuildMemberListCategoryCountResponse : BaseResponse 9 | { 10 | private readonly ushort _numEntries; 11 | 12 | public GuildMemberListCategoryCountResponse(ushort numEntries) 13 | { 14 | _numEntries = numEntries; 15 | } 16 | 17 | public override FragmentMessage Build() 18 | { 19 | var buffer = new Memory(new byte[2]); 20 | BinaryPrimitives.WriteUInt16BigEndian(buffer.Span, _numEntries); 21 | 22 | return new FragmentMessage 23 | { 24 | MessageType = MessageType.Data, 25 | DataPacketType = OpCodes.DataGuildMemberListCategoryCountResponse, 26 | Data = buffer, 27 | }; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Guilds/GuildMemberListCategoryEntryResponse.cs: -------------------------------------------------------------------------------- 1 | using Fragment.NetSlum.Core.Buffers; 2 | using Fragment.NetSlum.Core.Extensions; 3 | using Fragment.NetSlum.Networking.Constants; 4 | using Fragment.NetSlum.Networking.Objects; 5 | 6 | namespace Fragment.NetSlum.Networking.Packets.Response.Guilds; 7 | 8 | public class GuildMemberListCategoryEntryResponse : BaseResponse 9 | { 10 | private ushort _categoryId; 11 | private string _categoryName = null!; 12 | 13 | public GuildMemberListCategoryEntryResponse SetCategoryId(ushort id) 14 | { 15 | _categoryId = id; 16 | 17 | return this; 18 | } 19 | 20 | public GuildMemberListCategoryEntryResponse SetCategoryName(string name) 21 | { 22 | _categoryName = name; 23 | 24 | return this; 25 | } 26 | 27 | 28 | public override FragmentMessage Build() 29 | { 30 | var nameBytes = _categoryName.ToShiftJis(); 31 | 32 | var writer = new MemoryWriter(nameBytes.Length + sizeof(ushort) + 1); 33 | writer.Write(_categoryId); 34 | writer.Write(nameBytes); 35 | 36 | return new FragmentMessage 37 | { 38 | MessageType = MessageType.Data, 39 | DataPacketType = OpCodes.DataGuildMemberListCategoryEntryResponse, 40 | Data = writer.Buffer, 41 | }; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Guilds/GuildMemberListEntryCountResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Buffers.Binary; 3 | using Fragment.NetSlum.Networking.Constants; 4 | using Fragment.NetSlum.Networking.Objects; 5 | 6 | namespace Fragment.NetSlum.Networking.Packets.Response.Guilds; 7 | 8 | public class GuildMemberListEntryCountResponse : BaseResponse 9 | { 10 | private readonly ushort _numEntries; 11 | 12 | public GuildMemberListEntryCountResponse(ushort numEntries) 13 | { 14 | _numEntries = numEntries; 15 | } 16 | 17 | public override FragmentMessage Build() 18 | { 19 | var buffer = new Memory(new byte[2]); 20 | BinaryPrimitives.WriteUInt16BigEndian(buffer.Span, _numEntries); 21 | 22 | return new FragmentMessage 23 | { 24 | MessageType = MessageType.Data, 25 | DataPacketType = OpCodes.DataGuildMemberListEntryCountResponse, 26 | Data = buffer, 27 | }; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Guilds/GuildMenuCategoryCountResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Buffers.Binary; 3 | using Fragment.NetSlum.Networking.Constants; 4 | using Fragment.NetSlum.Networking.Objects; 5 | 6 | namespace Fragment.NetSlum.Networking.Packets.Response.Guilds; 7 | 8 | public class GuildMenuCategoryCountResponse : BaseResponse 9 | { 10 | private readonly ushort _numCategories; 11 | 12 | public GuildMenuCategoryCountResponse(ushort numCategories) 13 | { 14 | _numCategories = numCategories; 15 | } 16 | 17 | public override FragmentMessage Build() 18 | { 19 | var buffer = new Memory(new byte[2]); 20 | BinaryPrimitives.WriteUInt16BigEndian(buffer.Span, _numCategories); 21 | 22 | return new FragmentMessage 23 | { 24 | MessageType = MessageType.Data, 25 | DataPacketType = OpCodes.Data_GuildCategoryEntryCountResponse, 26 | Data = buffer, 27 | }; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Guilds/GuildMenuCategoryResponse.cs: -------------------------------------------------------------------------------- 1 | using Fragment.NetSlum.Core.Buffers; 2 | using Fragment.NetSlum.Core.Extensions; 3 | using Fragment.NetSlum.Networking.Constants; 4 | using Fragment.NetSlum.Networking.Objects; 5 | 6 | namespace Fragment.NetSlum.Networking.Packets.Response.Guilds; 7 | 8 | public class GuildMenuCategoryResponse : BaseResponse 9 | { 10 | private ushort _categoryId; 11 | private string _categoryName = null!; 12 | 13 | public GuildMenuCategoryResponse SetCategoryId(ushort id) 14 | { 15 | _categoryId = id; 16 | 17 | return this; 18 | } 19 | 20 | public GuildMenuCategoryResponse SetCategoryName(string name) 21 | { 22 | _categoryName = name; 23 | 24 | return this; 25 | } 26 | 27 | 28 | public override FragmentMessage Build() 29 | { 30 | var nameBytes = _categoryName.ToShiftJis(); 31 | 32 | var writer = new MemoryWriter(nameBytes.Length + sizeof(ushort) + 1); 33 | writer.Write(_categoryId); 34 | writer.Write(nameBytes); 35 | 36 | return new FragmentMessage 37 | { 38 | MessageType = MessageType.Data, 39 | DataPacketType = OpCodes.Data_GuildCategoryListItemResponse, 40 | Data = writer.Buffer, 41 | }; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Guilds/GuildMenuListEntryResponse.cs: -------------------------------------------------------------------------------- 1 | using Fragment.NetSlum.Core.Buffers; 2 | using Fragment.NetSlum.Core.Extensions; 3 | using Fragment.NetSlum.Networking.Constants; 4 | using Fragment.NetSlum.Networking.Objects; 5 | 6 | namespace Fragment.NetSlum.Networking.Packets.Response.Guilds; 7 | 8 | public class GuildMenuListEntryResponse : BaseResponse 9 | { 10 | private ushort _guildId; 11 | private string _guildName = null!; 12 | 13 | public GuildMenuListEntryResponse SetGuildId(ushort id) 14 | { 15 | _guildId = id; 16 | 17 | return this; 18 | } 19 | 20 | public GuildMenuListEntryResponse SetGuildName(string name) 21 | { 22 | _guildName = name; 23 | 24 | return this; 25 | } 26 | 27 | 28 | public override FragmentMessage Build() 29 | { 30 | var nameBytes = _guildName.ToShiftJis(); 31 | 32 | var writer = new MemoryWriter(nameBytes.Length + sizeof(ushort) + 1); 33 | writer.Write(_guildId); 34 | writer.Write(nameBytes); 35 | 36 | return new FragmentMessage 37 | { 38 | MessageType = MessageType.Data, 39 | DataPacketType = OpCodes.Data_GuildListItemResponse, 40 | Data = writer.Buffer, 41 | }; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Guilds/GuildShopEntryCountResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Buffers.Binary; 3 | using Fragment.NetSlum.Networking.Constants; 4 | using Fragment.NetSlum.Networking.Objects; 5 | 6 | namespace Fragment.NetSlum.Networking.Packets.Response.Guilds; 7 | 8 | public class GuildShopEntryCountResponse : BaseResponse 9 | { 10 | private readonly ushort _numEntries; 11 | 12 | public GuildShopEntryCountResponse(ushort numEntries) 13 | { 14 | _numEntries = numEntries; 15 | } 16 | 17 | public override FragmentMessage Build() 18 | { 19 | var buffer = new Memory(new byte[2]); 20 | BinaryPrimitives.WriteUInt16BigEndian(buffer.Span, _numEntries); 21 | 22 | return new FragmentMessage 23 | { 24 | MessageType = MessageType.Data, 25 | DataPacketType = OpCodes.DataGuildShopEntryCountResponse, 26 | Data = buffer, 27 | }; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Guilds/GuildShopEntryResponse.cs: -------------------------------------------------------------------------------- 1 | using Fragment.NetSlum.Core.Buffers; 2 | using Fragment.NetSlum.Core.Extensions; 3 | using Fragment.NetSlum.Networking.Constants; 4 | using Fragment.NetSlum.Networking.Objects; 5 | 6 | namespace Fragment.NetSlum.Networking.Packets.Response.Guilds; 7 | 8 | public class GuildShopEntryResponse : BaseResponse 9 | { 10 | private ushort _guildId; 11 | private string _guildName = null!; 12 | 13 | public GuildShopEntryResponse SetGuildId(ushort id) 14 | { 15 | _guildId = id; 16 | 17 | return this; 18 | } 19 | 20 | public GuildShopEntryResponse SetGuildName(string name) 21 | { 22 | _guildName = name; 23 | 24 | return this; 25 | } 26 | 27 | 28 | public override FragmentMessage Build() 29 | { 30 | var nameBytes = _guildName.ToShiftJis(); 31 | 32 | var writer = new MemoryWriter(nameBytes.Length + sizeof(ushort) + 1); 33 | writer.Write(_guildId); 34 | writer.Write(nameBytes); 35 | 36 | return new FragmentMessage 37 | { 38 | MessageType = MessageType.Data, 39 | DataPacketType = OpCodes.DataGuildShopEntryResponse, 40 | Data = writer.Buffer, 41 | }; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Guilds/GuildShopItemCountResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Buffers.Binary; 3 | using Fragment.NetSlum.Networking.Constants; 4 | using Fragment.NetSlum.Networking.Objects; 5 | 6 | namespace Fragment.NetSlum.Networking.Packets.Response.Guilds; 7 | 8 | public class GuildShopItemCountResponse : BaseResponse 9 | { 10 | private readonly ushort _numItems; 11 | 12 | public GuildShopItemCountResponse(ushort numItems) 13 | { 14 | _numItems = numItems; 15 | } 16 | 17 | public override FragmentMessage Build() 18 | { 19 | var buffer = new Memory(new byte[2]); 20 | BinaryPrimitives.WriteUInt16BigEndian(buffer.Span, _numItems); 21 | 22 | return new FragmentMessage 23 | { 24 | MessageType = MessageType.Data, 25 | DataPacketType = OpCodes.DataGetShopItemCountResponse, 26 | Data = buffer, 27 | }; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Guilds/GuildShopItemEntryResponse.cs: -------------------------------------------------------------------------------- 1 | using Fragment.NetSlum.Core.Buffers; 2 | using Fragment.NetSlum.Networking.Constants; 3 | using Fragment.NetSlum.Networking.Objects; 4 | 5 | namespace Fragment.NetSlum.Networking.Packets.Response.Guilds; 6 | 7 | public class GuildShopItemEntryResponse : BaseResponse 8 | { 9 | private uint _itemId; 10 | private ushort _quantity; 11 | private uint _price; 12 | 13 | public GuildShopItemEntryResponse SetItemId(uint id) 14 | { 15 | _itemId = id; 16 | 17 | return this; 18 | } 19 | 20 | public GuildShopItemEntryResponse SetQuantity(ushort quantity) 21 | { 22 | _quantity = quantity; 23 | 24 | return this; 25 | } 26 | 27 | public GuildShopItemEntryResponse SetPrice(uint price) 28 | { 29 | _price = price; 30 | 31 | return this; 32 | } 33 | 34 | public override FragmentMessage Build() 35 | { 36 | var writer = new MemoryWriter(sizeof(uint) * 2 + sizeof(ushort)); 37 | writer.Write(_itemId); 38 | writer.Write(_quantity); 39 | writer.Write(_price); 40 | 41 | return new FragmentMessage 42 | { 43 | MessageType = MessageType.Data, 44 | DataPacketType = OpCodes.DataGuildShopItemEntryResponse, 45 | Data = writer.Buffer, 46 | }; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Guilds/InvitePlayerToGuildResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Buffers.Binary; 3 | using Fragment.NetSlum.Networking.Constants; 4 | using Fragment.NetSlum.Networking.Objects; 5 | 6 | namespace Fragment.NetSlum.Networking.Packets.Response.Guilds; 7 | 8 | public class InvitePlayerToGuildResponse : BaseResponse 9 | { 10 | private readonly ushort _playerIndex; 11 | 12 | public InvitePlayerToGuildResponse(ushort playerIndex) 13 | { 14 | _playerIndex = playerIndex; 15 | } 16 | 17 | public override FragmentMessage Build() 18 | { 19 | var buffer = new Memory(new byte[2]); 20 | BinaryPrimitives.WriteUInt16BigEndian(buffer.Span[..2], _playerIndex); 21 | 22 | return new FragmentMessage 23 | { 24 | MessageType = MessageType.Data, 25 | DataPacketType = OpCodes.DataInvitePlayerToGuildResponse, 26 | Data = buffer, 27 | }; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Guilds/KickPlayerFromGuildResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Fragment.NetSlum.Networking.Constants; 3 | using Fragment.NetSlum.Networking.Objects; 4 | 5 | namespace Fragment.NetSlum.Networking.Packets.Response.Guilds; 6 | 7 | public class KickPlayerFromGuildResponse : BaseResponse 8 | { 9 | public override FragmentMessage Build() 10 | { 11 | return new FragmentMessage 12 | { 13 | MessageType = MessageType.Data, 14 | DataPacketType = OpCodes.DataKickPlayerFromGuildResponse, 15 | Data = new Memory(new byte[2]), 16 | }; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Guilds/LeaveGuildResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Fragment.NetSlum.Networking.Constants; 3 | using Fragment.NetSlum.Networking.Objects; 4 | 5 | namespace Fragment.NetSlum.Networking.Packets.Response.Guilds; 6 | 7 | public class LeaveGuildResponse : BaseResponse 8 | { 9 | public override FragmentMessage Build() 10 | { 11 | return new FragmentMessage 12 | { 13 | MessageType = MessageType.Data, 14 | DataPacketType = OpCodes.DataGuildLeaveResponse, 15 | Data = new Memory(new byte[2]), 16 | }; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Guilds/PurchaseGuildShopItemResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Buffers.Binary; 3 | using Fragment.NetSlum.Networking.Constants; 4 | using Fragment.NetSlum.Networking.Objects; 5 | 6 | namespace Fragment.NetSlum.Networking.Packets.Response.Guilds; 7 | 8 | public class PurchaseGuildShopItemResponse : BaseResponse 9 | { 10 | private readonly ushort _quantityPurchased; 11 | 12 | public PurchaseGuildShopItemResponse(ushort quantityPurchased) 13 | { 14 | _quantityPurchased = quantityPurchased; 15 | } 16 | 17 | public override FragmentMessage Build() 18 | { 19 | var buffer = new Memory(new byte[2]); 20 | BinaryPrimitives.WriteUInt16BigEndian(buffer.Span, _quantityPurchased); 21 | 22 | return new FragmentMessage 23 | { 24 | MessageType = MessageType.Data, 25 | DataPacketType = OpCodes.DataPurchaseGuildShopItemResponse, 26 | Data = buffer, 27 | }; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Guilds/ReassignGuildMasterResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Fragment.NetSlum.Networking.Constants; 3 | using Fragment.NetSlum.Networking.Objects; 4 | 5 | namespace Fragment.NetSlum.Networking.Packets.Response.Guilds; 6 | 7 | public class ReassignGuildMasterResponse : BaseResponse 8 | { 9 | public override FragmentMessage Build() 10 | { 11 | return new FragmentMessage 12 | { 13 | MessageType = MessageType.Data, 14 | DataPacketType = OpCodes.DataGuildReassignMasterResponse, 15 | Data = new Memory(new byte[2]), 16 | }; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Guilds/ShoppableGuildEntryCountResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Buffers.Binary; 3 | using Fragment.NetSlum.Networking.Constants; 4 | using Fragment.NetSlum.Networking.Objects; 5 | 6 | namespace Fragment.NetSlum.Networking.Packets.Response.Guilds; 7 | 8 | public class ShoppableGuildEntryCountResponse : BaseResponse 9 | { 10 | private readonly ushort _numCategories; 11 | 12 | public ShoppableGuildEntryCountResponse(ushort numCategories) 13 | { 14 | _numCategories = numCategories; 15 | } 16 | 17 | public override FragmentMessage Build() 18 | { 19 | var buffer = new Memory(new byte[2]); 20 | BinaryPrimitives.WriteUInt16BigEndian(buffer.Span, _numCategories); 21 | 22 | return new FragmentMessage 23 | { 24 | MessageType = MessageType.Data, 25 | DataPacketType = OpCodes.ShoppableGuildEntryCountResponse, 26 | Data = buffer, 27 | }; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Guilds/ShoppableGuildEntryResponse.cs: -------------------------------------------------------------------------------- 1 | using Fragment.NetSlum.Core.Buffers; 2 | using Fragment.NetSlum.Core.Extensions; 3 | using Fragment.NetSlum.Networking.Constants; 4 | using Fragment.NetSlum.Networking.Objects; 5 | 6 | namespace Fragment.NetSlum.Networking.Packets.Response.Guilds; 7 | 8 | public class ShoppableGuildEntryResponse : BaseResponse 9 | { 10 | private ushort _categoryId; 11 | private string _categoryName = null!; 12 | 13 | public ShoppableGuildEntryResponse SetCategoryId(ushort id) 14 | { 15 | _categoryId = id; 16 | 17 | return this; 18 | } 19 | 20 | public ShoppableGuildEntryResponse SetCategoryName(string name) 21 | { 22 | _categoryName = name; 23 | 24 | return this; 25 | } 26 | 27 | 28 | public override FragmentMessage Build() 29 | { 30 | var nameBytes = _categoryName.ToShiftJis(); 31 | 32 | var writer = new MemoryWriter(nameBytes.Length + sizeof(ushort) + 1); 33 | writer.Write(_categoryId); 34 | writer.Write(nameBytes); 35 | 36 | return new FragmentMessage 37 | { 38 | MessageType = MessageType.Data, 39 | DataPacketType = OpCodes.DataShoppableGuildEntryResponse, 40 | Data = writer.Buffer, 41 | }; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Guilds/TakeGuildShopItemResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Buffers.Binary; 3 | using Fragment.NetSlum.Networking.Constants; 4 | using Fragment.NetSlum.Networking.Objects; 5 | 6 | namespace Fragment.NetSlum.Networking.Packets.Response.Guilds; 7 | 8 | public class TakeGuildShopItemResponse : BaseResponse 9 | { 10 | private readonly ushort _quantityTaken; 11 | 12 | public TakeGuildShopItemResponse(ushort quantityTaken) 13 | { 14 | _quantityTaken = quantityTaken; 15 | } 16 | 17 | public override FragmentMessage Build() 18 | { 19 | var buffer = new Memory(new byte[2]); 20 | BinaryPrimitives.WriteUInt16BigEndian(buffer.Span, _quantityTaken); 21 | 22 | return new FragmentMessage 23 | { 24 | MessageType = MessageType.Data, 25 | DataPacketType = OpCodes.DataTakeGuildShopItemResponse, 26 | Data = buffer, 27 | }; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Guilds/UpdateGuildDetailsResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Fragment.NetSlum.Networking.Constants; 3 | using Fragment.NetSlum.Networking.Objects; 4 | 5 | namespace Fragment.NetSlum.Networking.Packets.Response.Guilds; 6 | 7 | public class UpdateGuildDetailsResponse : BaseResponse 8 | { 9 | public override FragmentMessage Build() 10 | { 11 | return new FragmentMessage 12 | { 13 | MessageType = MessageType.Data, 14 | DataPacketType = OpCodes.DataGuildUpdateDetailsResponse, 15 | Data = new Memory(new byte[2]), 16 | }; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Guilds/UpdateGuildShopItemResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Fragment.NetSlum.Networking.Constants; 3 | using Fragment.NetSlum.Networking.Objects; 4 | 5 | namespace Fragment.NetSlum.Networking.Packets.Response.Guilds; 6 | 7 | public class UpdateGuildShopItemResponse : BaseResponse 8 | { 9 | public override FragmentMessage Build() 10 | { 11 | return new FragmentMessage 12 | { 13 | MessageType = MessageType.Data, 14 | DataPacketType = OpCodes.DataUpdateGuildShopItemResponse, 15 | Data = new Memory(new byte[2]), 16 | }; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Login/AreaServerDiskAuthorizationResponse.cs: -------------------------------------------------------------------------------- 1 | using Fragment.NetSlum.Networking.Constants; 2 | using Fragment.NetSlum.Networking.Objects; 3 | 4 | namespace Fragment.NetSlum.Networking.Packets.Response.Login; 5 | 6 | public class AreaServerDiskAuthorizationResponse : BaseResponse 7 | { 8 | public override FragmentMessage Build() 9 | { 10 | return new FragmentMessage 11 | { 12 | MessageType = MessageType.Data, 13 | DataPacketType = OpCodes.Data_AreaServerDiskAuthorizationSuccess, 14 | Data = new byte[] { 0x00, 0x00 }, 15 | }; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Login/AreaServerLogonResponse.cs: -------------------------------------------------------------------------------- 1 | using Fragment.NetSlum.Networking.Constants; 2 | using Fragment.NetSlum.Networking.Objects; 3 | 4 | namespace Fragment.NetSlum.Networking.Packets.Response.Login; 5 | 6 | public class AreaServerLogonResponse : BaseResponse 7 | { 8 | public override FragmentMessage Build() 9 | { 10 | return new FragmentMessage 11 | { 12 | MessageType = MessageType.Data, 13 | DataPacketType = OpCodes.DataAreaServerSuccess, 14 | Data = new byte[] { 0xde, 0xad }, 15 | }; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Login/AreaServerShutdownResponse.cs: -------------------------------------------------------------------------------- 1 | using Fragment.NetSlum.Networking.Constants; 2 | using Fragment.NetSlum.Networking.Objects; 3 | 4 | namespace Fragment.NetSlum.Networking.Packets.Response.Login; 5 | 6 | public class AreaServerShutdownResponse : BaseResponse 7 | { 8 | public override FragmentMessage Build() 9 | { 10 | return new FragmentMessage 11 | { 12 | MessageType = MessageType.Data, 13 | DataPacketType = OpCodes.AreaServerShutdownResponse, 14 | Data = new byte[] { 0x02, 0x11 }, 15 | }; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Login/DiskAuthorizationResponse.cs: -------------------------------------------------------------------------------- 1 | using Fragment.NetSlum.Networking.Constants; 2 | using Fragment.NetSlum.Networking.Objects; 3 | 4 | namespace Fragment.NetSlum.Networking.Packets.Response.Login; 5 | 6 | public class DiskAuthorizationResponse :BaseResponse 7 | { 8 | public override FragmentMessage Build() 9 | { 10 | return new FragmentMessage 11 | { 12 | MessageType = MessageType.Data, 13 | DataPacketType = OpCodes.DataDiskAuthorizationSuccess, 14 | Data = new byte[] { 0x78, 0x94 }, 15 | }; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Login/LogonRepeatResponse.cs: -------------------------------------------------------------------------------- 1 | using Fragment.NetSlum.Networking.Constants; 2 | using Fragment.NetSlum.Networking.Objects; 3 | 4 | namespace Fragment.NetSlum.Networking.Packets.Response.Login; 5 | 6 | public class LogonRepeatResponse : BaseResponse 7 | { 8 | public override FragmentMessage Build() 9 | { 10 | return new FragmentMessage 11 | { 12 | MessageType = MessageType.Data, 13 | DataPacketType = OpCodes.DataLogonResponse, 14 | Data = new byte[] { 0x02, 0x10 } 15 | }; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Login/LogonResponse.cs: -------------------------------------------------------------------------------- 1 | using Fragment.NetSlum.Networking.Constants; 2 | using Fragment.NetSlum.Networking.Objects; 3 | 4 | namespace Fragment.NetSlum.Networking.Packets.Response.Login; 5 | 6 | public class LogonResponse : BaseResponse 7 | { 8 | public override FragmentMessage Build() 9 | { 10 | return new FragmentMessage 11 | { 12 | MessageType = MessageType.Data, 13 | DataPacketType = OpCodes.DataLogonResponse, 14 | Data = new byte[] { 0x74, 0x32 } // Represents "t2" in UTF8? 15 | }; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Mail/MailListCountResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Buffers.Binary; 3 | using Fragment.NetSlum.Networking.Constants; 4 | using Fragment.NetSlum.Networking.Objects; 5 | 6 | namespace Fragment.NetSlum.Networking.Packets.Response.Mail; 7 | 8 | public class MailListCountResponse : BaseResponse 9 | { 10 | private readonly uint _numMailEntries; 11 | 12 | public MailListCountResponse(uint numMailEntries) 13 | { 14 | _numMailEntries = numMailEntries; 15 | } 16 | 17 | public override FragmentMessage Build() 18 | { 19 | var buffer = new Memory(new byte[4]); 20 | BinaryPrimitives.WriteUInt32BigEndian(buffer.Span, _numMailEntries); 21 | 22 | return new FragmentMessage 23 | { 24 | MessageType = MessageType.Data, 25 | DataPacketType = OpCodes.DataMailCountResponse, 26 | Data = buffer, 27 | }; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Mail/SendMailResponse.cs: -------------------------------------------------------------------------------- 1 | using Fragment.NetSlum.Networking.Constants; 2 | using Fragment.NetSlum.Networking.Objects; 3 | using System; 4 | using OpCodes = Fragment.NetSlum.Networking.Constants.OpCodes; 5 | 6 | namespace Fragment.NetSlum.Networking.Packets.Response.Mail 7 | { 8 | public class SendMailResponse :BaseResponse 9 | { 10 | private OpCodes _responseCode; 11 | 12 | public SendMailResponse SetStatusCode(OpCodes responseCode) 13 | { 14 | _responseCode = responseCode; 15 | return this; 16 | } 17 | public override FragmentMessage Build() 18 | { 19 | return new FragmentMessage 20 | { 21 | MessageType = MessageType.Data, 22 | DataPacketType = _responseCode, 23 | Data = new Memory(new byte[2]), 24 | }; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Misc/DataComResponse.cs: -------------------------------------------------------------------------------- 1 | using Fragment.NetSlum.Networking.Constants; 2 | using Fragment.NetSlum.Networking.Objects; 3 | 4 | namespace Fragment.NetSlum.Networking.Packets.Response.Misc; 5 | 6 | public class DataComResponse : BaseResponse 7 | { 8 | public override FragmentMessage Build() 9 | { 10 | return new FragmentMessage 11 | { 12 | MessageType = MessageType.Data, 13 | DataPacketType = OpCodes.DataComSuccess, 14 | Data = new byte[] {0xde, 0xad} 15 | }; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Misc/PingResponse.cs: -------------------------------------------------------------------------------- 1 | using Fragment.NetSlum.Networking.Constants; 2 | using Fragment.NetSlum.Networking.Objects; 3 | 4 | namespace Fragment.NetSlum.Networking.Packets.Response.Misc; 5 | 6 | public class PingResponse : BaseResponse 7 | { 8 | public override FragmentMessage Build() 9 | { 10 | return new FragmentMessage 11 | { 12 | MessageType = MessageType.Data, 13 | DataPacketType = OpCodes.DataPing, 14 | Data = new byte[] {0x00} 15 | }; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Misc/ReturnToDesktopResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Fragment.NetSlum.Networking.Constants; 3 | using Fragment.NetSlum.Networking.Objects; 4 | 5 | namespace Fragment.NetSlum.Networking.Packets.Response.Misc; 6 | 7 | public class ReturnToDesktopResponse : BaseResponse 8 | { 9 | public override FragmentMessage Build() 10 | { 11 | return new FragmentMessage 12 | { 13 | MessageType = MessageType.Data, 14 | DataPacketType = OpCodes.DataReturnToDesktopResponse, 15 | Data = new Memory(new byte[2]), 16 | }; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Misc/UnknownResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Fragment.NetSlum.Networking.Constants; 3 | using Fragment.NetSlum.Networking.Objects; 4 | 5 | namespace Fragment.NetSlum.Networking.Packets.Response.Misc; 6 | 7 | public class UnknownResponse : BaseResponse 8 | { 9 | private readonly OpCodes _packetType; 10 | private Memory _data = new Memory(new byte[2]); 11 | 12 | public UnknownResponse(OpCodes packetType) 13 | { 14 | _packetType = packetType; 15 | } 16 | 17 | public UnknownResponse SetData(Memory data) 18 | { 19 | _data = data; 20 | 21 | return this; 22 | } 23 | 24 | public override FragmentMessage Build() 25 | { 26 | return new FragmentMessage 27 | { 28 | MessageType = MessageType.Data, 29 | DataPacketType = _packetType, 30 | Data = _data, 31 | }; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Ranking/RankingLeaderboardCategoryCountResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Buffers.Binary; 3 | using Fragment.NetSlum.Networking.Constants; 4 | using Fragment.NetSlum.Networking.Objects; 5 | 6 | namespace Fragment.NetSlum.Networking.Packets.Response.Ranking; 7 | 8 | public class RankingLeaderboardCategoryCountResponse : BaseResponse 9 | { 10 | private readonly ushort _numEntries; 11 | 12 | public RankingLeaderboardCategoryCountResponse(ushort numEntries) 13 | { 14 | _numEntries = numEntries; 15 | } 16 | 17 | public override FragmentMessage Build() 18 | { 19 | var buffer = new Memory(new byte[2]); 20 | BinaryPrimitives.WriteUInt16BigEndian(buffer.Span, _numEntries); 21 | 22 | return new FragmentMessage 23 | { 24 | MessageType = MessageType.Data, 25 | DataPacketType = OpCodes.RankingLeaderboardCategoryCountResponse, 26 | Data = buffer, 27 | }; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Ranking/RankingLeaderboardCategoryEntryResponse.cs: -------------------------------------------------------------------------------- 1 | using Fragment.NetSlum.Core.Buffers; 2 | using Fragment.NetSlum.Core.Extensions; 3 | using Fragment.NetSlum.Networking.Constants; 4 | using Fragment.NetSlum.Networking.Objects; 5 | 6 | namespace Fragment.NetSlum.Networking.Packets.Response.Ranking; 7 | 8 | public class RankingLeaderboardCategoryEntryResponse : BaseResponse 9 | { 10 | private ushort _categoryId; 11 | private string _categoryName = ""; 12 | 13 | public RankingLeaderboardCategoryEntryResponse SetCategoryId(ushort id) 14 | { 15 | _categoryId = id; 16 | 17 | return this; 18 | } 19 | 20 | public RankingLeaderboardCategoryEntryResponse SetCategoryName(string name) 21 | { 22 | _categoryName = name; 23 | 24 | return this; 25 | } 26 | 27 | public override FragmentMessage Build() 28 | { 29 | var nameBytes = _categoryName.ToShiftJis(); 30 | 31 | var writer = new MemoryWriter(nameBytes.Length + sizeof(ushort)); 32 | writer.Write(_categoryId); 33 | writer.Write(nameBytes); 34 | 35 | return new FragmentMessage 36 | { 37 | MessageType = MessageType.Data, 38 | DataPacketType = OpCodes.RankingLeaderboardCategoryEntryResponse, 39 | Data = writer.Buffer, 40 | }; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Ranking/RankingLeaderboardPlayerCountResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Buffers.Binary; 3 | using Fragment.NetSlum.Networking.Constants; 4 | using Fragment.NetSlum.Networking.Objects; 5 | 6 | namespace Fragment.NetSlum.Networking.Packets.Response.Ranking; 7 | 8 | public class RankingLeaderboardPlayerCountResponse : BaseResponse 9 | { 10 | private readonly uint _numEntries; 11 | 12 | public RankingLeaderboardPlayerCountResponse(uint numEntries) 13 | { 14 | _numEntries = numEntries; 15 | } 16 | 17 | public override FragmentMessage Build() 18 | { 19 | var buffer = new Memory(new byte[4]); 20 | BinaryPrimitives.WriteUInt32BigEndian(buffer.Span, _numEntries); 21 | 22 | return new FragmentMessage 23 | { 24 | MessageType = MessageType.Data, 25 | DataPacketType = OpCodes.RankingLeaderboardPlayerCountResponse, 26 | Data = buffer, 27 | }; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Ranking/RankingLeaderboardPlayerEntryResponse.cs: -------------------------------------------------------------------------------- 1 | using Fragment.NetSlum.Core.Buffers; 2 | using Fragment.NetSlum.Core.Extensions; 3 | using Fragment.NetSlum.Networking.Constants; 4 | using Fragment.NetSlum.Networking.Objects; 5 | 6 | namespace Fragment.NetSlum.Networking.Packets.Response.Ranking; 7 | 8 | public class RankingLeaderboardPlayerEntryResponse : BaseResponse 9 | { 10 | private uint _playerId; 11 | private string _playerName = ""; 12 | 13 | public RankingLeaderboardPlayerEntryResponse SetPlayerId(uint id) 14 | { 15 | _playerId = id; 16 | 17 | return this; 18 | } 19 | 20 | public RankingLeaderboardPlayerEntryResponse SetPlayerName(string name) 21 | { 22 | _playerName = name; 23 | 24 | return this; 25 | } 26 | 27 | public override FragmentMessage Build() 28 | { 29 | var nameBytes = _playerName.ToShiftJis(); 30 | 31 | var writer = new MemoryWriter(nameBytes.Length + sizeof(uint)); 32 | writer.Write(nameBytes); 33 | writer.Write(_playerId); 34 | 35 | return new FragmentMessage 36 | { 37 | MessageType = MessageType.Data, 38 | DataPacketType = OpCodes.RankingLeaderboardPlayerEntryResponse, 39 | Data = writer.Buffer, 40 | }; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Packets/Response/Security/KeyExchangeResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using Fragment.NetSlum.Networking.Constants; 4 | using Fragment.NetSlum.Networking.Extensions; 5 | using Fragment.NetSlum.Networking.Objects; 6 | 7 | namespace Fragment.NetSlum.Networking.Packets.Response.Security; 8 | 9 | public class KeyExchangeResponse : BaseResponse 10 | { 11 | private readonly Memory _clientKey = new byte[16]; 12 | private readonly Memory _serverKey = new byte[16]; 13 | 14 | public KeyExchangeResponse SetClientKey(Memory key) 15 | { 16 | _clientKey.Replace(key); 17 | 18 | return this; 19 | } 20 | 21 | public KeyExchangeResponse SetServerKey(Memory key) 22 | { 23 | _serverKey.Replace(key); 24 | 25 | return this; 26 | } 27 | 28 | public override FragmentMessage Build() 29 | { 30 | using var buffer = new MemoryStream(); 31 | 32 | buffer.WriteByte(0); 33 | buffer.WriteByte(0x10); 34 | buffer.Write(_clientKey.Span); 35 | buffer.WriteByte(0); 36 | buffer.WriteByte(0x10); 37 | buffer.Write(_serverKey.Span); 38 | buffer.Write(new byte[] { 0, 0, 0, 0xe, 0, 0, 0, 0, 0, 0 }); 39 | 40 | return base.Build(MessageType.KeyExchangeResponse, buffer.ToArray()); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Pipeline/Builder/PacketPipelineBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | using Fragment.NetSlum.Networking.Messaging; 2 | using Microsoft.Extensions.DependencyInjection; 3 | using Microsoft.Extensions.DependencyInjection.Extensions; 4 | 5 | namespace Fragment.NetSlum.Networking.Pipeline.Builder; 6 | 7 | public static class PacketPipelineBuilderExtensions 8 | { 9 | public static PacketPipelineBuilder AddPacketPipeline(this IServiceCollection services) 10 | { 11 | services.TryAddScoped(); 12 | 13 | var builder = new PacketPipelineBuilder(services); 14 | 15 | return builder; 16 | } 17 | } -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Pipeline/Decoders/IPacketDecoder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Fragment.NetSlum.Networking.Objects; 4 | 5 | namespace Fragment.NetSlum.Networking.Pipeline.Decoders; 6 | 7 | public interface IPacketDecoder 8 | { 9 | public int Decode(Memory data, List messages); 10 | } -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Pipeline/Encoders/DataTypeEnvelopeEncoder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Buffers.Binary; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using Fragment.NetSlum.Networking.Constants; 6 | using Fragment.NetSlum.Networking.Objects; 7 | 8 | namespace Fragment.NetSlum.Networking.Pipeline.Encoders; 9 | 10 | public class DataTypeEnvelopeEncoder : IMessageEncoder 11 | { 12 | private uint sequenceNumber = 0xe; 13 | public void Encode(List responseObjects, MemoryStream memoryStream) 14 | { 15 | foreach (var response in responseObjects) 16 | { 17 | if (response.MessageType != MessageType.Data) 18 | { 19 | continue; 20 | } 21 | var bufferMemory = new Memory(new byte[response.Data.Length + 8]); 22 | var bufferSpan = bufferMemory.Span; 23 | 24 | BinaryPrimitives.WriteUInt32BigEndian(bufferSpan[..4], sequenceNumber++); 25 | BinaryPrimitives.WriteUInt16BigEndian(bufferSpan[4..6], (ushort) (response.Data.Length + 2)); 26 | BinaryPrimitives.WriteUInt16BigEndian(bufferSpan[6..8], (ushort) response.DataPacketType); 27 | response.Data.CopyTo(bufferMemory[8..]); 28 | response.Data = bufferMemory; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Pipeline/Encoders/IMessageEncoder.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.IO; 3 | using Fragment.NetSlum.Networking.Objects; 4 | 5 | namespace Fragment.NetSlum.Networking.Pipeline.Encoders; 6 | 7 | public interface IMessageEncoder 8 | { 9 | /// 10 | /// Executed in order of registration and after message response handlers, an encoder allows the pipeline to modify 11 | /// or write messages to the output buffer 12 | /// 13 | /// 14 | /// 15 | public void Encode(List responseObjects, MemoryStream memoryStream); 16 | } 17 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Queries/Images/GetImageInfoQuery.cs: -------------------------------------------------------------------------------- 1 | using Fragment.NetSlum.Core.CommandBus.Contracts.Queries; 2 | using Fragment.NetSlum.Core.Models; 3 | 4 | namespace Fragment.NetSlum.Networking.Queries.Images; 5 | 6 | public class GetImageInfoQuery : IQuery 7 | { 8 | public byte[] ImageData { get; } 9 | 10 | public GetImageInfoQuery(byte[] imageData) 11 | { 12 | ImageData = imageData; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Queries/Infrastructure/IsIpAddressBannedQuery.cs: -------------------------------------------------------------------------------- 1 | using Fragment.NetSlum.Core.CommandBus.Contracts.Queries; 2 | 3 | namespace Fragment.NetSlum.Networking.Queries.Infrastructure; 4 | 5 | public class IsIpAddressBannedQuery : IQuery 6 | { 7 | public string IpAddress { get; set; } 8 | 9 | public IsIpAddressBannedQuery(string ipAddress) 10 | { 11 | IpAddress = ipAddress; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Networking/Queries/News/HasPlayerReadNewsArticle.cs: -------------------------------------------------------------------------------- 1 | using Fragment.NetSlum.Core.CommandBus.Contracts.Queries; 2 | 3 | namespace Fragment.NetSlum.Networking.Queries.News; 4 | 5 | public class HasPlayerReadNewsArticle : IQuery 6 | { 7 | public int PlayerId { get; } 8 | public ushort ArticleId { get; } 9 | 10 | public HasPlayerReadNewsArticle(int playerId, ushort articleId) 11 | { 12 | PlayerId = playerId; 13 | ArticleId = articleId; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Persistence/Attributes/TimestampableAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.EntityFrameworkCore; 3 | 4 | namespace Fragment.NetSlum.Persistence.Attributes; 5 | 6 | /// 7 | /// Denotes a DateTime property that should be updated on an entity state change 8 | /// 9 | [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)] 10 | public class TimestampableAttribute : Attribute 11 | { 12 | public EntityState[] States { get; } 13 | 14 | /// 15 | /// By default, the property will be updated on Added and Modified states 16 | /// 17 | public TimestampableAttribute() 18 | { 19 | States = [EntityState.Added, EntityState.Modified]; 20 | } 21 | 22 | /// 23 | /// Explicitly set the states of when to modify this property's value 24 | /// 25 | /// 26 | /// The list of states to listen for 27 | /// 28 | public TimestampableAttribute(params EntityState[] states) 29 | { 30 | States = states; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Persistence/Builders/EntityListenerBuilder.cs: -------------------------------------------------------------------------------- 1 | using Fragment.NetSlum.Persistence.Listeners; 2 | using Microsoft.Extensions.DependencyInjection; 3 | 4 | namespace Fragment.NetSlum.Persistence.Builders; 5 | 6 | public class EntityListenerBuilder 7 | { 8 | public IServiceCollection Services { get; } 9 | 10 | public EntityListenerBuilder(IServiceCollection services) 11 | { 12 | Services = services; 13 | } 14 | 15 | public EntityListenerBuilder AddListener() 16 | { 17 | Services.AddScoped(typeof(IEntityChangeListener), typeof(TEntityListener)); 18 | 19 | return this; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Persistence/Entities/AreaServerCategory.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using System.ComponentModel.DataAnnotations.Schema; 3 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 4 | 5 | namespace Fragment.NetSlum.Persistence.Entities; 6 | 7 | public class AreaServerCategory : IConfigurableEntity 8 | { 9 | [Key] 10 | [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 11 | public ushort Id { get; set; } 12 | 13 | public required string CategoryName { get; set; } 14 | 15 | public void Configure(EntityTypeBuilder entityBuilder) 16 | { 17 | entityBuilder.HasData(new AreaServerCategory 18 | { 19 | Id = 1, 20 | CategoryName = "Main", 21 | }); 22 | entityBuilder.HasData(new AreaServerCategory 23 | { 24 | Id = 2, 25 | CategoryName = "Test", 26 | }); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Persistence/Entities/AreaServerIpMapping.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations.Schema; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | 5 | namespace Fragment.NetSlum.Persistence.Entities 6 | { 7 | public class AreaServerIpMapping 8 | { 9 | [Key] 10 | [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 11 | public int Id { get; set; } 12 | public required ulong DiscordUserId { get; set; } 13 | public required string PublicIp { get;set; } 14 | public required string LocalIp { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Persistence/Entities/BannedIp.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | using Microsoft.EntityFrameworkCore; 5 | 6 | namespace Fragment.NetSlum.Persistence.Entities; 7 | 8 | [Index(nameof(IpAddress))] 9 | [Index(nameof(CreatedAt))] 10 | public class BannedIp 11 | { 12 | [Key] 13 | [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 14 | public int Id { get; set; } 15 | public required string IpAddress { get; set; } 16 | public DateTime CreatedAt { get; set; } = DateTime.UtcNow; 17 | } 18 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Persistence/Entities/BbsCategory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.ComponentModel.DataAnnotations.Schema; 5 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 6 | 7 | namespace Fragment.NetSlum.Persistence.Entities; 8 | 9 | public class BbsCategory : IConfigurableEntity 10 | { 11 | [Key] 12 | [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 13 | public ushort Id { get; set; } 14 | 15 | public required string CategoryName { get; set; } 16 | 17 | public ICollection Threads = new List(); 18 | 19 | public DateTime CreatedAt { get; set; } = DateTime.UtcNow; 20 | 21 | public void Configure(EntityTypeBuilder entityBuilder) 22 | { 23 | entityBuilder.HasData(new BbsCategory 24 | { 25 | Id = 1, 26 | CategoryName = "GENERAL", 27 | CreatedAt = DateTime.MinValue, 28 | }); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Persistence/Entities/BbsPost.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 5 | 6 | namespace Fragment.NetSlum.Persistence.Entities; 7 | 8 | public class BbsPost : IConfigurableEntity 9 | { 10 | [Key] 11 | [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 12 | public int Id { get; set; } 13 | 14 | public int ThreadId { get; set; } 15 | public BbsThread Thread { get; set; } = default!; 16 | 17 | public int PostedById { get; set; } 18 | public Character PostedBy { get; set; } = default!; 19 | 20 | public required string Title { get; set; } 21 | 22 | public BbsPostContent? PostContent { get; set; } 23 | 24 | public DateTime CreatedAt { get; set; } = DateTime.UtcNow; 25 | 26 | public void Configure(EntityTypeBuilder entityBuilder) 27 | { 28 | entityBuilder 29 | .HasOne(p => p.PostContent) 30 | .WithOne(c => c.Post) 31 | .HasForeignKey(c => c.PostId) 32 | .IsRequired(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Persistence/Entities/BbsPostContent.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using System.ComponentModel.DataAnnotations.Schema; 3 | 4 | namespace Fragment.NetSlum.Persistence.Entities; 5 | 6 | public class BbsPostContent 7 | { 8 | [Key] 9 | [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 10 | public int Id { get; set; } 11 | 12 | public int PostId { get; set; } 13 | public BbsPost Post { get; set; } = null!; 14 | 15 | public string Content { get; set; } = ""; 16 | } 17 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Persistence/Entities/BbsThread.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.ComponentModel.DataAnnotations.Schema; 5 | 6 | namespace Fragment.NetSlum.Persistence.Entities; 7 | 8 | public class BbsThread 9 | { 10 | [Key] 11 | [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 12 | public int Id { get; set; } 13 | 14 | public ushort CategoryId { get; set; } 15 | public BbsCategory Category { get; set; } = default!; 16 | 17 | public required string Title { get; set; } 18 | 19 | public ICollection Posts { get; set; } = new List(); 20 | public DateTime CreatedAt { get; set; } = DateTime.UtcNow; 21 | } 22 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Persistence/Entities/CharacterIpLog.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | using Microsoft.EntityFrameworkCore; 5 | 6 | namespace Fragment.NetSlum.Persistence.Entities; 7 | 8 | [Index(nameof(IpAddress))] 9 | [Index(nameof(CreatedAt))] 10 | public class CharacterIpLog 11 | { 12 | [Key] 13 | [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 14 | public int Id { get; set; } 15 | public int CharacterId { get; set; } 16 | public required string IpAddress { get; set; } 17 | public DateTime CreatedAt { get; set; } = DateTime.UtcNow; 18 | } 19 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Persistence/Entities/CharacterStats.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | using Fragment.NetSlum.Persistence.Attributes; 5 | using Microsoft.EntityFrameworkCore; 6 | 7 | namespace Fragment.NetSlum.Persistence.Entities; 8 | 9 | [Index(nameof(UpdatedAt))] 10 | public class CharacterStats 11 | { 12 | [Key] 13 | [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 14 | public int Id { get; set; } 15 | 16 | public int CharacterId { get; set; } 17 | public Character? Character { get; set; } 18 | 19 | public int CurrentHp { get; set; } 20 | public int CurrentSp { get; set; } 21 | public uint CurrentGp { get; set; } 22 | public int OnlineTreasures { get; set; } 23 | public int AverageFieldLevel { get; set; } 24 | 25 | public int GoldAmount { get; set; } 26 | public int SilverAmount { get; set; } 27 | public int BronzeAmount { get; set; } 28 | 29 | public DateTime CreatedAt { get; set; } = DateTime.UtcNow; 30 | 31 | [Timestampable(EntityState.Modified)] 32 | public DateTime? UpdatedAt { get; set; } 33 | } 34 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Persistence/Entities/Deprecated/BbsCategory.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | using Microsoft.EntityFrameworkCore; 5 | 6 | namespace Fragment.NetSlum.Persistence.Entities.Deprecated; 7 | 8 | [Table("bbs_category")] 9 | [Index("CategoryId", Name = "BBS_Category_categoryID_uindex", IsUnique = true)] 10 | [MySqlCharSet("cp932")] 11 | [MySqlCollation("cp932_japanese_ci")] 12 | public class BbsCategory 13 | { 14 | [Key] 15 | [Column("categoryID")] 16 | public int CategoryId { get; set; } 17 | 18 | [Column("categoryName")] 19 | [StringLength(33)] 20 | [MySqlCharSet("utf8mb4")] 21 | [MySqlCollation("utf8mb4_0900_ai_ci")] 22 | public string CategoryName { get; set; } = null!; 23 | 24 | [InverseProperty("Category")] 25 | public virtual ICollection BbsThreads { get; set; } = new List(); 26 | } 27 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Persistence/Entities/Deprecated/BbsPostBody.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using System.ComponentModel.DataAnnotations.Schema; 3 | using Microsoft.EntityFrameworkCore; 4 | 5 | namespace Fragment.NetSlum.Persistence.Entities.Deprecated; 6 | 7 | [Table("bbs_post_body")] 8 | [Index("PostId", Name = "BBS_Post_Body_BBS_Post_Meta_postID_fk")] 9 | [Index("PostBodyId", Name = "BBS_Post_Body_postBodyID_uindex", IsUnique = true)] 10 | [MySqlCharSet("cp932")] 11 | [MySqlCollation("cp932_japanese_ci")] 12 | public class BbsPostBody 13 | { 14 | [Key] 15 | [Column("postBodyID")] 16 | public int PostBodyId { get; set; } 17 | 18 | [Column("postBody", TypeName = "blob")] 19 | public byte[] PostBody { get; set; } = null!; 20 | 21 | [Column("postID")] 22 | public int PostId { get; set; } 23 | 24 | [ForeignKey("PostId")] 25 | [InverseProperty("BbsPostBodies")] 26 | public virtual BbsPostMetum Post { get; set; } = null!; 27 | } 28 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Persistence/Entities/Deprecated/BbsThread.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | using Microsoft.EntityFrameworkCore; 5 | 6 | namespace Fragment.NetSlum.Persistence.Entities.Deprecated; 7 | 8 | [Table("bbs_threads")] 9 | [Index("CategoryId", Name = "BBS_Threads_BBS_Category_categoryID_fk")] 10 | [Index("ThreadId", Name = "BBS_Threads_threadID_uindex", IsUnique = true)] 11 | [MySqlCharSet("cp932")] 12 | [MySqlCollation("cp932_japanese_ci")] 13 | public class BbsThread 14 | { 15 | [Key] 16 | [Column("threadID")] 17 | public int ThreadId { get; set; } 18 | 19 | [Column("threadTitle", TypeName = "blob")] 20 | public byte[] ThreadTitle { get; set; } = null!; 21 | 22 | [Column("categoryID")] 23 | public int CategoryId { get; set; } 24 | 25 | [InverseProperty("Thread")] 26 | public virtual ICollection BbsPostMeta { get; set; } = new List(); 27 | 28 | [ForeignKey("CategoryId")] 29 | [InverseProperty("BbsThreads")] 30 | public virtual BbsCategory Category { get; set; } = null!; 31 | } 32 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Persistence/Entities/Deprecated/FailedJob.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations.Schema; 3 | using Microsoft.EntityFrameworkCore; 4 | 5 | namespace Fragment.NetSlum.Persistence.Entities.Deprecated; 6 | 7 | [Keyless] 8 | [Table("failed_jobs")] 9 | public class FailedJob 10 | { 11 | [Column("id")] 12 | public ulong? Id { get; set; } 13 | 14 | [Column("connection", TypeName = "text")] 15 | public string Connection { get; set; } = null!; 16 | 17 | [Column("queue", TypeName = "text")] 18 | public string Queue { get; set; } = null!; 19 | 20 | [Column("payload")] 21 | public string Payload { get; set; } = null!; 22 | 23 | [Column("exception")] 24 | public string Exception { get; set; } = null!; 25 | 26 | [Column("failed_at", TypeName = "timestamp")] 27 | public DateTime FailedAt { get; set; } 28 | } 29 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Persistence/Entities/Deprecated/Guilditemshop.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using System.ComponentModel.DataAnnotations.Schema; 3 | 4 | namespace Fragment.NetSlum.Persistence.Entities.Deprecated; 5 | 6 | [Table("guilditemshop")] 7 | public class Guilditemshop 8 | { 9 | [Key] 10 | [Column("itemShopID")] 11 | public int ItemShopId { get; set; } 12 | 13 | [Column("guildID")] 14 | public int? GuildId { get; set; } 15 | 16 | [Column("itemID")] 17 | public int? ItemId { get; set; } 18 | 19 | [Column("quantity")] 20 | public int? Quantity { get; set; } 21 | 22 | [Column("generalPrice")] 23 | public int? GeneralPrice { get; set; } 24 | 25 | [Column("memberPrice")] 26 | public int? MemberPrice { get; set; } 27 | 28 | [Column("availableForGeneral")] 29 | public bool? AvailableForGeneral { get; set; } 30 | 31 | [Column("availableForMember")] 32 | public bool? AvailableForMember { get; set; } 33 | } 34 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Persistence/Entities/Deprecated/Guildrepository.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using System.ComponentModel.DataAnnotations.Schema; 3 | using Microsoft.EntityFrameworkCore; 4 | 5 | namespace Fragment.NetSlum.Persistence.Entities.Deprecated; 6 | 7 | [Table("guildrepository")] 8 | [MySqlCharSet("cp932")] 9 | [MySqlCollation("cp932_japanese_ci")] 10 | public class Guildrepository 11 | { 12 | [Key] 13 | [Column("guildID")] 14 | public int GuildId { get; set; } 15 | 16 | [Column("guildName", TypeName = "blob")] 17 | public byte[]? GuildName { get; set; } 18 | 19 | [Column("guildEmblem", TypeName = "blob")] 20 | public byte[]? GuildEmblem { get; set; } 21 | 22 | [Column("guildComment", TypeName = "blob")] 23 | public byte[]? GuildComment { get; set; } 24 | 25 | [Column("establishmentDate")] 26 | [StringLength(255)] 27 | public string? EstablishmentDate { get; set; } 28 | 29 | [Column("masterPlayerID")] 30 | public int? MasterPlayerId { get; set; } 31 | 32 | [Column("goldCoin")] 33 | public int? GoldCoin { get; set; } 34 | 35 | [Column("silverCoin")] 36 | public int? SilverCoin { get; set; } 37 | 38 | [Column("bronzeCoin")] 39 | public int? BronzeCoin { get; set; } 40 | 41 | [Column("gp")] 42 | public int? Gp { get; set; } 43 | } 44 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Persistence/Entities/Deprecated/MailBody.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using System.ComponentModel.DataAnnotations.Schema; 3 | using Microsoft.EntityFrameworkCore; 4 | 5 | namespace Fragment.NetSlum.Persistence.Entities.Deprecated; 6 | 7 | [Table("mail_body")] 8 | [Index("MailId", Name = "MAIL_BODY_MAIL_ID_uindex", IsUnique = true)] 9 | [MySqlCharSet("cp932")] 10 | [MySqlCollation("cp932_japanese_ci")] 11 | public class MailBody 12 | { 13 | [Key] 14 | [Column("MAIL_BODY_ID")] 15 | public int MailBodyId { get; set; } 16 | 17 | [Column("MAIL_ID")] 18 | public int MailId { get; set; } 19 | 20 | [Column("MAIL_BODY", TypeName = "blob")] 21 | public byte[]? MailBody1 { get; set; } 22 | 23 | [Column("FACE_ID")] 24 | [StringLength(30)] 25 | [MySqlCharSet("utf8mb4")] 26 | [MySqlCollation("utf8mb4_0900_ai_ci")] 27 | public string FaceId { get; set; } = null!; 28 | 29 | [ForeignKey("MailId")] 30 | [InverseProperty("MailBody")] 31 | public virtual MailMetum Mail { get; set; } = null!; 32 | } 33 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Persistence/Entities/Deprecated/MailMetum.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | using Microsoft.EntityFrameworkCore; 5 | 6 | namespace Fragment.NetSlum.Persistence.Entities.Deprecated; 7 | 8 | [Table("mail_meta")] 9 | [Index("MailId", Name = "MAIL_META_MAIL_ID_uindex", IsUnique = true)] 10 | [MySqlCharSet("cp932")] 11 | [MySqlCollation("cp932_japanese_ci")] 12 | public class MailMetum 13 | { 14 | [Key] 15 | [Column("MAIL_ID")] 16 | public int MailId { get; set; } 17 | 18 | [Column("RECEIVER_ACCOUNT_ID")] 19 | public int ReceiverAccountId { get; set; } 20 | 21 | [Column("DATE", TypeName = "datetime")] 22 | public DateTime Date { get; set; } 23 | 24 | [Column("SENDER_ACCOUNT_ID")] 25 | public int SenderAccountId { get; set; } 26 | 27 | [Column("SENDER_NAME", TypeName = "blob")] 28 | public byte[]? SenderName { get; set; } 29 | 30 | [Column("RECEIVER_NAME", TypeName = "blob")] 31 | public byte[] ReceiverName { get; set; } = null!; 32 | 33 | [Column("MAIL_SUBJECT", TypeName = "blob")] 34 | public byte[] MailSubject { get; set; } = null!; 35 | 36 | [Column("MAIL_DELIVERED")] 37 | public bool? MailDelivered { get; set; } 38 | 39 | [InverseProperty("Mail")] 40 | public virtual MailBody? MailBody { get; set; } 41 | } 42 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Persistence/Entities/Deprecated/Messageoftheday.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using System.ComponentModel.DataAnnotations.Schema; 3 | using Microsoft.EntityFrameworkCore; 4 | 5 | namespace Fragment.NetSlum.Persistence.Entities.Deprecated; 6 | 7 | [Table("messageoftheday")] 8 | [MySqlCharSet("cp932")] 9 | [MySqlCollation("cp932_japanese_ci")] 10 | public class Messageoftheday 11 | { 12 | [Key] 13 | [Column("ID")] 14 | public int Id { get; set; } 15 | 16 | [StringLength(500)] 17 | [MySqlCharSet("utf8mb4")] 18 | [MySqlCollation("utf8mb4_0900_ai_ci")] 19 | public string Message { get; set; } = null!; 20 | } 21 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Persistence/Entities/Deprecated/Migration.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using System.ComponentModel.DataAnnotations.Schema; 3 | using Microsoft.EntityFrameworkCore; 4 | 5 | namespace Fragment.NetSlum.Persistence.Entities.Deprecated; 6 | 7 | [Keyless] 8 | [Table("migrations")] 9 | public class Migration 10 | { 11 | [Column("id")] 12 | public uint? Id { get; set; } 13 | 14 | [Column("migration")] 15 | [StringLength(255)] 16 | public string? Migration1 { get; set; } 17 | 18 | [Column("batch")] 19 | public int? Batch { get; set; } 20 | } 21 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Persistence/Entities/Deprecated/News.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | 5 | namespace Fragment.NetSlum.Persistence.Entities.Deprecated; 6 | 7 | /// 8 | /// type: 9 | /// 1 = news 10 | /// 2 = current maint 11 | /// 3 = planned maint 12 | /// 4 = past maint 13 | /// 14 | [Table("news")] 15 | public class News 16 | { 17 | [Key] 18 | [Column("key")] 19 | public int Key { get; set; } 20 | 21 | [Column(TypeName = "timestamp")] 22 | public DateTime Date { get; set; } 23 | 24 | [Column(TypeName = "tinytext")] 25 | public string Title { get; set; } = null!; 26 | 27 | [Column("URL", TypeName = "tinytext")] 28 | public string? Url { get; set; } 29 | 30 | public sbyte Type { get; set; } 31 | } 32 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Persistence/Entities/Deprecated/NewsSection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | using Microsoft.EntityFrameworkCore; 5 | 6 | namespace Fragment.NetSlum.Persistence.Entities.Deprecated; 7 | 8 | [Table("news_section")] 9 | [Index("ArticleId", Name = "news_section_articleID_uindex", IsUnique = true)] 10 | public class NewsSection 11 | { 12 | [Key] 13 | [Column("articleID")] 14 | public ushort ArticleId { get; set; } 15 | 16 | [Column("articleTitle")] 17 | [StringLength(33)] 18 | public string ArticleTitle { get; set; } = null!; 19 | 20 | [Column("articleBody")] 21 | [StringLength(412)] 22 | public string ArticleBody { get; set; } = null!; 23 | 24 | [Column("articleDate", TypeName = "datetime")] 25 | public DateTime ArticleDate { get; set; } 26 | 27 | [Column("articleImage", TypeName = "blob")] 28 | public byte[]? ArticleImage { get; set; } 29 | } 30 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Persistence/Entities/Deprecated/NewsSectionLog.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using System.ComponentModel.DataAnnotations.Schema; 3 | using Microsoft.EntityFrameworkCore; 4 | 5 | namespace Fragment.NetSlum.Persistence.Entities.Deprecated; 6 | 7 | [Table("news_section_log")] 8 | [Index("Id", Name = "news_section_log_id_uindex", IsUnique = true)] 9 | [Index("SaveId", Name = "news_section_log_savedId_index")] 10 | public class NewsSectionLog 11 | { 12 | [Key] 13 | [Column("id")] 14 | public int Id { get; set; } 15 | 16 | [Column("saveId")] 17 | [StringLength(100)] 18 | public string SaveId { get; set; } = null!; 19 | 20 | [Column("articleId")] 21 | public ushort ArticleId { get; set; } 22 | } 23 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Persistence/Entities/Deprecated/PasswordReset.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | using Microsoft.EntityFrameworkCore; 5 | 6 | namespace Fragment.NetSlum.Persistence.Entities.Deprecated; 7 | 8 | [Keyless] 9 | [Table("password_resets")] 10 | public class PasswordReset 11 | { 12 | [Column("email")] 13 | [StringLength(255)] 14 | public string? Email { get; set; } 15 | 16 | [Column("token")] 17 | [StringLength(255)] 18 | public string? Token { get; set; } 19 | 20 | [Column("created_at", TypeName = "timestamp")] 21 | public DateTime? CreatedAt { get; set; } 22 | } 23 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Persistence/Entities/Deprecated/PlayerAccountId.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using System.ComponentModel.DataAnnotations.Schema; 3 | using Microsoft.EntityFrameworkCore; 4 | 5 | namespace Fragment.NetSlum.Persistence.Entities.Deprecated; 6 | 7 | [Table("player_account_id")] 8 | [Index("Saveid", Name = "PLAYER_ACCOUNT_ID_SAVEID_uindex", IsUnique = true)] 9 | [MySqlCharSet("cp932")] 10 | [MySqlCollation("cp932_japanese_ci")] 11 | public class PlayerAccountId 12 | { 13 | [Key] 14 | [Column("ID")] 15 | public int Id { get; set; } 16 | 17 | [Column("SAVEID")] 18 | [StringLength(100)] 19 | [MySqlCharSet("utf8mb4")] 20 | [MySqlCollation("utf8mb4_0900_ai_ci")] 21 | public string Saveid { get; set; } = null!; 22 | } 23 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Persistence/Entities/Deprecated/SaveFileIntegration.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | using Microsoft.EntityFrameworkCore; 5 | 6 | namespace Fragment.NetSlum.Persistence.Entities.Deprecated; 7 | 8 | [Keyless] 9 | [Table("save_file_integrations")] 10 | public class SaveFileIntegration 11 | { 12 | [Column("id")] 13 | public ulong? Id { get; set; } 14 | 15 | [Column("created_at", TypeName = "timestamp")] 16 | public DateTime? CreatedAt { get; set; } 17 | 18 | [Column("updated_at", TypeName = "timestamp")] 19 | public DateTime? UpdatedAt { get; set; } 20 | 21 | [Column("account")] 22 | [StringLength(255)] 23 | public string? Account { get; set; } 24 | 25 | [Column("saveid")] 26 | [StringLength(255)] 27 | public string? Saveid { get; set; } 28 | 29 | [Column("token")] 30 | [StringLength(255)] 31 | public string? Token { get; set; } 32 | 33 | [Column("tokenExpiry")] 34 | [StringLength(255)] 35 | public string? TokenExpiry { get; set; } 36 | } 37 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Persistence/Entities/GuildShopItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | using Fragment.NetSlum.Persistence.Attributes; 5 | using Microsoft.EntityFrameworkCore; 6 | 7 | namespace Fragment.NetSlum.Persistence.Entities; 8 | 9 | public class GuildShopItem 10 | { 11 | [Key] 12 | [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 13 | public int Id { get; set; } 14 | 15 | public ushort GuildId { get; set; } 16 | public Guild Guild { get; set; } = null!; 17 | 18 | public int ItemId { get; set; } 19 | public ushort Quantity { get; set; } 20 | public uint Price { get; set; } 21 | public uint MemberPrice { get; set; } 22 | public bool AvailableForMember { get; set; } 23 | public bool AvailableForGeneral { get; set; } 24 | public DateTime CreatedAt { get; set; } = DateTime.UtcNow; 25 | 26 | [Timestampable(EntityState.Modified)] 27 | public DateTime? UpdatedAt { get; set; } 28 | } 29 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Persistence/Entities/GuildStats.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | using Fragment.NetSlum.Persistence.Attributes; 5 | using Microsoft.EntityFrameworkCore; 6 | 7 | namespace Fragment.NetSlum.Persistence.Entities; 8 | 9 | public class GuildStats 10 | { 11 | [Key] 12 | [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 13 | public int Id { get; set; } 14 | 15 | public ushort GuildId { get; set; } 16 | public Guild? Guild { get; set; } 17 | 18 | public int GoldAmount { get; set; } 19 | public int SilverAmount { get; set; } 20 | public int BronzeAmount { get; set; } 21 | public int CurrentGp { get; set; } 22 | 23 | public DateTime CreatedAt { get; set; } = DateTime.UtcNow; 24 | 25 | [Timestampable(EntityState.Modified)] 26 | public DateTime? UpdatedAt { get; set; } 27 | } 28 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Persistence/Entities/IConfigurableEntity.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 2 | 3 | namespace Fragment.NetSlum.Persistence.Entities; 4 | 5 | /// 6 | /// Allows for extended entity configuration during the model creation phase of the context 7 | /// 8 | /// 9 | public interface IConfigurableEntity where TEntity : class 10 | { 11 | /// 12 | /// Allows for additional model configuration that may not be available via attributes. 13 | /// This method is executed during 14 | /// 15 | /// 16 | internal void Configure(EntityTypeBuilder entityBuilder); 17 | } 18 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Persistence/Entities/Mail.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | using Fragment.NetSlum.Persistence.Attributes; 5 | using Microsoft.EntityFrameworkCore; 6 | 7 | namespace Fragment.NetSlum.Persistence.Entities; 8 | 9 | public class Mail 10 | { 11 | [Key] 12 | [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 13 | public int Id { get; set; } 14 | 15 | public int? SenderId { get; set; } 16 | public PlayerAccount? Sender { get; set; } 17 | 18 | [MaxLength(32)] 19 | public string SenderName { get; set; } = ""; 20 | 21 | public int? RecipientId { get; set; } 22 | public PlayerAccount? Recipient { get; set; } 23 | 24 | [MaxLength(32)] 25 | public string RecipientName { get; set; } = ""; 26 | 27 | [MaxLength(128)] 28 | public string Subject { get; set; } = ""; 29 | 30 | [MaxLength(32)] 31 | public string AvatarId { get; set; } = ""; 32 | 33 | public MailContent? Content { get; set; } 34 | 35 | public bool Delivered { get; set; } 36 | public bool Read { get; set; } 37 | 38 | public DateTime CreatedAt { get; set; } = DateTime.UtcNow; 39 | 40 | [Timestampable(EntityState.Modified)] 41 | public DateTime? UpdatedAt { get; set; } 42 | } 43 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Persistence/Entities/MailContent.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using System.ComponentModel.DataAnnotations.Schema; 3 | 4 | namespace Fragment.NetSlum.Persistence.Entities; 5 | 6 | public class MailContent 7 | { 8 | [Key] 9 | [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 10 | public int Id { get; set; } 11 | 12 | public int MailId { get; set; } 13 | public Mail Mail { get; set; } = null!; 14 | 15 | [MaxLength(1200)] 16 | public string Content { get; set; } = ""; 17 | } 18 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Persistence/Entities/PlayerAccount.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | using Microsoft.EntityFrameworkCore; 5 | 6 | namespace Fragment.NetSlum.Persistence.Entities; 7 | 8 | [Index(nameof(SaveId), IsUnique = true)] 9 | public class PlayerAccount 10 | { 11 | [Key] 12 | [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 13 | public int Id { get; set; } 14 | 15 | [MaxLength(32)] 16 | public required string SaveId { get; set; } 17 | 18 | public DateTime CreatedAt { get; set; } = DateTime.UtcNow; 19 | } 20 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Persistence/Entities/ServerNews.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | using Microsoft.EntityFrameworkCore; 5 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 6 | 7 | namespace Fragment.NetSlum.Persistence.Entities; 8 | 9 | public class ServerNews : IConfigurableEntity 10 | { 11 | [Key] 12 | [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 13 | public int Id { get; set; } 14 | 15 | [MaxLength(500)] 16 | [MySqlCharSet("cp932")] 17 | [MySqlCollation("cp932_japanese_ci")] 18 | public string Content { get; set; } = null!; 19 | 20 | public DateTime CreatedAt { get; set; } = DateTime.UtcNow; 21 | 22 | public void Configure(EntityTypeBuilder entityBuilder) 23 | { 24 | var motd = @"Welcome to Netslum-Redux! 25 | Current Status: 26 | - Lobby #GOnline#W! 27 | - BBS #GOnline#W! 28 | - Mail #GOnline#W! 29 | - Guilds #GOnline#W! 30 | - Ranking #GOnline#W! 31 | - News #GOnline#W!"; 32 | 33 | entityBuilder.HasData(new ServerNews 34 | { 35 | Id = 1, 36 | Content = motd, 37 | CreatedAt = DateTime.MinValue, 38 | }); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Persistence/Entities/WebNewsArticle.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | using Microsoft.EntityFrameworkCore; 5 | 6 | namespace Fragment.NetSlum.Persistence.Entities; 7 | 8 | public class WebNewsArticle 9 | { 10 | [Key] 11 | [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 12 | public ushort Id { get; set; } 13 | 14 | public ushort? WebNewsCategoryId { get; set; } 15 | public WebNewsCategory? WebNewsCategory { get; set; } 16 | 17 | [MySqlCharSet("cp932")] 18 | [MySqlCollation("cp932_japanese_ci")] 19 | [MaxLength(33)] 20 | public required string Title { get; set; } 21 | 22 | [MySqlCharSet("cp932")] 23 | [MySqlCollation("cp932_japanese_ci")] 24 | [MaxLength(412)] 25 | public string Content { get; set; } = ""; 26 | 27 | public byte[]? Image { get; set; } 28 | 29 | public DateTime CreatedAt { get; set; } = DateTime.UtcNow; 30 | } 31 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Persistence/Entities/WebNewsCategory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | using Microsoft.EntityFrameworkCore; 5 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 6 | 7 | namespace Fragment.NetSlum.Persistence.Entities; 8 | 9 | public class WebNewsCategory : IConfigurableEntity 10 | { 11 | [Key] 12 | [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 13 | public ushort Id { get; set; } 14 | 15 | [MySqlCharSet("cp932")] 16 | [MySqlCollation("cp932_japanese_ci")] 17 | [MaxLength(64)] 18 | public required string CategoryName { get; set; } 19 | 20 | public DateTime CreatedAt { get; set; } = DateTime.UtcNow; 21 | 22 | public void Configure(EntityTypeBuilder entityBuilder) 23 | { 24 | entityBuilder.HasData(new WebNewsCategory 25 | { 26 | Id = 1, 27 | CategoryName = "Netslum News", 28 | CreatedAt = DateTime.MinValue, 29 | }); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Persistence/Entities/WebNewsReadLog.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | 5 | namespace Fragment.NetSlum.Persistence.Entities; 6 | 7 | public class WebNewsReadLog 8 | { 9 | [Key] 10 | [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 11 | public ushort Id { get; set; } 12 | 13 | public int PlayerAccountId { get; set; } 14 | public PlayerAccount PlayerAccount { get; set; } = null!; 15 | 16 | public ushort WebNewsArticleId { get; set; } 17 | public WebNewsArticle WebNewsArticle { get; set; } = null!; 18 | 19 | public DateTime CreatedAt { get; set; } = DateTime.UtcNow; 20 | } 21 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Persistence/Extensions/EntityListenerServerExtensions.cs: -------------------------------------------------------------------------------- 1 | using Fragment.NetSlum.Persistence.Builders; 2 | using Fragment.NetSlum.Persistence.Interceptors; 3 | using Microsoft.Extensions.DependencyInjection; 4 | 5 | namespace Fragment.NetSlum.Persistence.Extensions; 6 | 7 | public static class EntityListenerServerExtensions 8 | { 9 | public static EntityListenerBuilder UseEntityListener(this IServiceCollection services) 10 | { 11 | services.AddScoped(); 12 | 13 | return new EntityListenerBuilder(services); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Persistence/Extensions/QueryExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace Fragment.NetSlum.Persistence.Extensions; 5 | 6 | public static class QueryExtensions 7 | { 8 | public static IEnumerable Paginate(this IEnumerable query, int page, int pageSize) 9 | { 10 | return query 11 | .Skip((page < 1 ? 0 : page - 1) * pageSize) 12 | .Take(pageSize); 13 | } 14 | 15 | public static IQueryable Paginate(this IQueryable query, int page, int pageSize) 16 | { 17 | return query 18 | .Skip((page < 1 ? 0 : page - 1) * pageSize) 19 | .Take(pageSize); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Persistence/Extensions/ServiceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using Fragment.NetSlum.Persistence.Services; 2 | using Microsoft.EntityFrameworkCore; 3 | using Microsoft.Extensions.DependencyInjection; 4 | 5 | namespace Fragment.NetSlum.Persistence.Extensions; 6 | 7 | public static class ServiceCollectionExtensions 8 | { 9 | /// 10 | /// Adds automatic execution of EF context migrations at application boot so long as DOTNET_EF_AUTO_MIGRATE is not falsy. 11 | /// 12 | /// The to add services to. 13 | /// The used to analyze and execute pending migrations 14 | /// 15 | public static IServiceCollection AddAutoMigrations(this IServiceCollection services) where TContext : DbContext 16 | { 17 | services.AddHostedService>(); 18 | 19 | return services; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Persistence/Fragment.NetSlum.Persistence.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | true 7 | CS1591 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Persistence/Listeners/AbstractEntityChangeListener.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.EntityFrameworkCore.ChangeTracking; 5 | 6 | namespace Fragment.NetSlum.Persistence.Listeners; 7 | 8 | public abstract class AbstractEntityChangeListener : IEntityChangeListener where TEntity : class where TContext : DbContext 9 | { 10 | protected abstract Task OnEntityChanged(TContext context, EntityEntry entry); 11 | 12 | public Task EntityChanged(DbContext context, EntityEntry entry) 13 | { 14 | if (context is not TContext expectedContext) 15 | { 16 | throw new ArgumentException($"Invalid context {context.GetType()} encountered in {GetType().Name}. Expected {typeof(TContext).Name}"); 17 | } 18 | 19 | if (entry.Entity is not TEntity) 20 | { 21 | throw new ArgumentException($"Invalid entity {entry.Entity.GetType()} encountered in {GetType().Name}. Expected {typeof(TEntity).Name}"); 22 | } 23 | 24 | return OnEntityChanged(expectedContext, entry); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Persistence/Listeners/CharacterStatsChangeListener.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Fragment.NetSlum.Persistence.Entities; 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.EntityFrameworkCore.ChangeTracking; 5 | 6 | namespace Fragment.NetSlum.Persistence.Listeners; 7 | 8 | public class CharacterStatsChangeListener : AbstractEntityChangeListener 9 | { 10 | protected override Task OnEntityChanged(FragmentContext context, EntityEntry entry) 11 | { 12 | // If the player stats are deleted (which should never happen), we can ignore stats updates 13 | if (entry.State != EntityState.Modified) 14 | { 15 | return Task.CompletedTask; 16 | } 17 | 18 | context.CharacterStatHistory.Add(CharacterStatHistory.FromStats((CharacterStats)entry.OriginalValues.ToObject())); 19 | 20 | return Task.CompletedTask; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Persistence/Listeners/IEntityChangeListener.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Microsoft.EntityFrameworkCore; 3 | using Microsoft.EntityFrameworkCore.ChangeTracking; 4 | 5 | namespace Fragment.NetSlum.Persistence.Listeners; 6 | 7 | public interface IEntityChangeListener 8 | { 9 | public Task EntityChanged(DbContext context, EntityEntry entry); 10 | } 11 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Server/Api/Controllers/AreaServersController.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Fragment.NetSlum.Networking.Sessions; 3 | using Fragment.NetSlum.Server.Api.Models; 4 | using Fragment.NetSlum.Server.Mappings; 5 | using Fragment.NetSlum.TcpServer; 6 | using Microsoft.AspNetCore.Mvc; 7 | 8 | namespace Fragment.NetSlum.Server.Api.Controllers; 9 | 10 | [ApiController] 11 | [Route("api/[controller]")] 12 | public class AreaServersController : ControllerBase 13 | { 14 | private readonly ITcpServer _gameServer; 15 | 16 | public AreaServersController(ITcpServer gameServer) 17 | { 18 | _gameServer = gameServer; 19 | } 20 | 21 | /// 22 | /// Returns information on all online area servers 23 | /// 24 | /// 25 | [HttpGet] 26 | public IEnumerable GetOnlineAreaServers() 27 | { 28 | foreach (var client in _gameServer.Sessions) 29 | { 30 | if (client is not FragmentTcpSession { IsAreaServer: true } session) 31 | { 32 | continue; 33 | } 34 | 35 | if (session.AreaServerInfo == null) 36 | { 37 | continue; 38 | } 39 | 40 | yield return AreaServerMapper.Map(session.AreaServerInfo); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Server/Api/Controllers/LobbiesController.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Fragment.NetSlum.Networking.Stores; 3 | using Fragment.NetSlum.Server.Api.Models; 4 | using Fragment.NetSlum.Server.Mappings; 5 | using Microsoft.AspNetCore.Mvc; 6 | 7 | namespace Fragment.NetSlum.Server.Api.Controllers; 8 | 9 | [ApiController] 10 | [Route("api/[controller]")] 11 | public class LobbiesController : ControllerBase 12 | { 13 | private readonly ChatLobbyStore _lobbyStore; 14 | 15 | public LobbiesController(ChatLobbyStore lobbyStore) 16 | { 17 | _lobbyStore = lobbyStore; 18 | } 19 | 20 | /// 21 | /// Returns a list of all available lobbies and player metadata for each player within the lobby 22 | /// 23 | /// 24 | [HttpGet] 25 | public IEnumerable GetAllLobbies() 26 | { 27 | foreach (var lobby in _lobbyStore.ChatLobbies) 28 | { 29 | yield return LobbyMapper.Map(lobby); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Server/Api/Controllers/StatsController.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using Fragment.NetSlum.Persistence; 3 | using Fragment.NetSlum.Server.Api.Models; 4 | using Microsoft.AspNetCore.Mvc; 5 | 6 | namespace Fragment.NetSlum.Server.Api.Controllers; 7 | 8 | [ApiController] 9 | [Route("api/[controller]")] 10 | public class StatsController 11 | { 12 | private readonly FragmentContext _database; 13 | 14 | public StatsController(FragmentContext database) 15 | { 16 | _database = database; 17 | } 18 | 19 | /// 20 | /// Returns statistical data about this server instance 21 | /// 22 | /// 23 | [HttpGet] 24 | public ServerStats GetServerStats() 25 | { 26 | return new ServerStats 27 | { 28 | TotalBbsPosts = _database.BbsThreads.Count(), 29 | ActiveGuilds = _database.Guilds.Count(), 30 | RegisteredAccounts = _database.PlayerAccounts.Count(), 31 | RegisteredCharacters = _database.Characters.Count(), 32 | }; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Server/Api/Models/AreaServerStatus.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Fragment.NetSlum.Server.Api.Models; 4 | 5 | public class AreaServerStatus 6 | { 7 | public string Name { get; set; } = default!; 8 | public ushort Level { get; set; } 9 | public byte State { get; set; } 10 | public ushort CurrentPlayerCount { get;set; } 11 | public DateTime OnlineSince { get; set; } 12 | } 13 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Server/Api/Models/GuildInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Fragment.NetSlum.Server.Api.Models; 4 | 5 | public class GuildInfo 6 | { 7 | public string Name { get; set; } = default!; 8 | public string Comment { get; set; } = default!; 9 | public int LeaderId { get; set; } 10 | public int GoldAmount { get; set; } 11 | public int SilverAmount { get; set; } 12 | public int BronzeAmount { get; set; } 13 | public int CurrentGp { get; set; } 14 | public int MemberCount { get; set; } 15 | 16 | public DateTime CreatedAt { get; set; } 17 | public DateTime LastUpdatedAt { get; set; } 18 | } 19 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Server/Api/Models/Lobby.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Fragment.NetSlum.Core.Constants; 3 | 4 | namespace Fragment.NetSlum.Server.Api.Models; 5 | 6 | public class Lobby 7 | { 8 | public int Id { get; set; } 9 | public required string Name { get; set; } 10 | public ushort PlayerCount { get; set; } 11 | public ChatLobbyType Type { get; set; } 12 | public ICollection Players { get; set; } = new List(); 13 | } 14 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Server/Api/Models/LobbyPlayer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Fragment.NetSlum.Server.Api.Models; 4 | 5 | public class LobbyPlayer 6 | { 7 | public int CharacterId { get; set; } 8 | public string CharacterName { get; set; } = default!; 9 | public DateTime JoinedAt { get; set; } 10 | } 11 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Server/Api/Models/PagedResult.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Fragment.NetSlum.Server.Api.Models; 4 | 5 | public class PagedResult where T : class 6 | { 7 | public int Page { get; set; } 8 | public int TotalRecords { get; set; } 9 | public int PageSize { get; set; } 10 | public ICollection Data { get; set; } 11 | 12 | public PagedResult(int page, int pageSize, int totalRecords, ICollection data) 13 | { 14 | Page = page; 15 | PageSize = pageSize; 16 | TotalRecords = totalRecords; 17 | Data = data; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Server/Api/Models/PlayerInfo.cs: -------------------------------------------------------------------------------- 1 | using Fragment.NetSlum.Core.Constants; 2 | 3 | namespace Fragment.NetSlum.Server.Api.Models; 4 | 5 | public class PlayerInfo 6 | { 7 | public int Id { get; set; } 8 | public string CharacterName { get; set; } = default!; 9 | public CharacterClass Class { get; set; } 10 | public ushort? GuildId { get; set; } 11 | public ushort Level { get; set; } 12 | public string Greeting { get; set; } = default!; 13 | public ushort CurrentHp { get; set; } 14 | public ushort CurrentSp { get; set; } 15 | public uint CurrentGp { get; set; } 16 | public ushort OnlineTreasures { get; set; } 17 | public ushort AverageFieldLevel { get; set; } 18 | public ushort GoldCoinCount { get; set; } 19 | public ushort SilverCoinCount { get; set; } 20 | public ushort BronzeCoinCount { get; set; } 21 | public uint ModelId { get; set; } 22 | public string AvatarId { get; set; } = ""; 23 | public int AccountId { get; set; } 24 | } 25 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Server/Api/Models/PlayerStats.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Fragment.NetSlum.Server.Api.Models; 4 | 5 | public class PlayerStats 6 | { 7 | public ushort Level { get; set; } 8 | public ushort CurrentHp { get; set; } 9 | public ushort CurrentSp { get; set; } 10 | public uint CurrentGp { get; set; } 11 | public ushort OnlineTreasures { get; set; } 12 | public ushort AverageFieldLevel { get; set; } 13 | public ushort GoldCoinCount { get; set; } 14 | public ushort SilverCoinCount { get; set; } 15 | public ushort BronzeCoinCount { get; set; } 16 | public DateTime? UpdatedAt { get; set; } 17 | } 18 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Server/Api/Models/ServerStats.cs: -------------------------------------------------------------------------------- 1 | namespace Fragment.NetSlum.Server.Api.Models; 2 | 3 | public class ServerStats 4 | { 5 | public int RegisteredCharacters { get; set; } 6 | public int RegisteredAccounts { get; set; } 7 | public int ActiveGuilds { get; set; } 8 | public int TotalBbsPosts { get; set; } 9 | } 10 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Server/Handlers/Accounts/RegisterPlayerAccountCommandHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | using Fragment.NetSlum.Core.CommandBus.Contracts.Commands; 4 | using Fragment.NetSlum.Networking.Commands.Accounts; 5 | using Fragment.NetSlum.Persistence; 6 | using Fragment.NetSlum.Persistence.Entities; 7 | 8 | namespace Fragment.NetSlum.Server.Handlers.Accounts; 9 | 10 | public class RegisterPlayerAccountCommandHandler : CommandHandler 11 | { 12 | private readonly FragmentContext _database; 13 | 14 | public RegisterPlayerAccountCommandHandler(FragmentContext database) 15 | { 16 | _database = database; 17 | } 18 | 19 | public override async ValueTask Handle(RegisterPlayerAccountCommand command, CancellationToken cancellationToken) 20 | { 21 | var newAccount = new PlayerAccount 22 | { 23 | SaveId = command.SaveId, 24 | }; 25 | 26 | _database.PlayerAccounts.Add(newAccount); 27 | 28 | await _database.SaveChangesAsync(cancellationToken); 29 | 30 | return newAccount.Id; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Server/Handlers/Events/CharacterLoggedInEventHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | using Fragment.NetSlum.Core.CommandBus.Contracts.Events; 4 | using Fragment.NetSlum.Networking.Events; 5 | using Fragment.NetSlum.Persistence; 6 | using Fragment.NetSlum.Persistence.Entities; 7 | 8 | namespace Fragment.NetSlum.Server.Handlers.Events; 9 | 10 | public class CharacterLoggedInEventHandler : EventHandler 11 | { 12 | private readonly FragmentContext _database; 13 | 14 | public CharacterLoggedInEventHandler(FragmentContext database) 15 | { 16 | _database = database; 17 | } 18 | 19 | public override async ValueTask Handle(CharacterLoggedInEvent eventInfo, CancellationToken cancellationToken) 20 | { 21 | _database.CharacterIpLogs.Add(new CharacterIpLog 22 | { 23 | CharacterId = eventInfo.CharacterId, 24 | IpAddress = eventInfo.IpAddress 25 | }); 26 | 27 | await _database.SaveChangesAsync(cancellationToken); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Server/Handlers/Images/GetImageInfoQueryHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | using Fragment.NetSlum.Core.CommandBus.Contracts.Queries; 4 | using Fragment.NetSlum.Core.Models; 5 | using Fragment.NetSlum.Networking.Queries.Images; 6 | using Fragment.NetSlum.Server.Converters; 7 | 8 | namespace Fragment.NetSlum.Server.Handlers.Images; 9 | 10 | public class GetImageInfoQueryHandler : QueryHandler 11 | { 12 | private readonly ImageConverter _imageConverter; 13 | 14 | public GetImageInfoQueryHandler(ImageConverter imageConverter) 15 | { 16 | _imageConverter = imageConverter; 17 | } 18 | 19 | public override ValueTask Handle(GetImageInfoQuery command, CancellationToken cancellationToken) 20 | { 21 | return ValueTask.FromResult(_imageConverter.Convert(command.ImageData)); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Server/Handlers/Infrastructure/IsIpAddressBannedQueryHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | using Fragment.NetSlum.Core.CommandBus.Contracts.Queries; 5 | using Fragment.NetSlum.Networking.Queries.Infrastructure; 6 | using Fragment.NetSlum.Persistence; 7 | 8 | namespace Fragment.NetSlum.Server.Handlers.Infrastructure; 9 | 10 | public class IsIpAddressBannedQueryHandler : QueryHandler 11 | { 12 | private readonly FragmentContext _database; 13 | 14 | public IsIpAddressBannedQueryHandler(FragmentContext database) 15 | { 16 | _database = database; 17 | } 18 | 19 | public override ValueTask Handle(IsIpAddressBannedQuery command, CancellationToken cancellationToken) 20 | { 21 | return ValueTask.FromResult(_database.BannedIps.Any(log => log.IpAddress == command.IpAddress)); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Server/Handlers/News/HasPlayerReadNewsArticleQueryHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | using Fragment.NetSlum.Core.CommandBus.Contracts.Queries; 4 | using Fragment.NetSlum.Networking.Queries.News; 5 | using Fragment.NetSlum.Persistence; 6 | using Microsoft.EntityFrameworkCore; 7 | 8 | namespace Fragment.NetSlum.Server.Handlers.News; 9 | 10 | public class HasPlayerReadNewsArticleQueryHandler : QueryHandler 11 | { 12 | private readonly FragmentContext _database; 13 | 14 | public HasPlayerReadNewsArticleQueryHandler(FragmentContext database) 15 | { 16 | _database = database; 17 | } 18 | 19 | public override async ValueTask Handle(HasPlayerReadNewsArticle command, CancellationToken cancellationToken) 20 | { 21 | return await _database.WebNewsReadLogs.AnyAsync( 22 | wnl => wnl.PlayerAccountId == command.PlayerId && wnl.WebNewsArticleId == command.ArticleId, 23 | cancellationToken: cancellationToken); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Server/Mappings/AreaServerMapper.cs: -------------------------------------------------------------------------------- 1 | using Fragment.NetSlum.Networking.Models; 2 | using Fragment.NetSlum.Server.Api.Models; 3 | using Riok.Mapperly.Abstractions; 4 | 5 | namespace Fragment.NetSlum.Server.Mappings; 6 | 7 | [Mapper] 8 | public partial class AreaServerMapper 9 | { 10 | [MapProperty(nameof(AreaServerInformation.ServerName), nameof(AreaServerStatus.Name))] 11 | [MapProperty(nameof(AreaServerInformation.ActiveSince), nameof(AreaServerStatus.OnlineSince))] 12 | public static partial AreaServerStatus Map(AreaServerInformation input); 13 | } 14 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Server/Mappings/GuildMapper.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable RedundantVerbatimPrefix 2 | using Fragment.NetSlum.Persistence.Entities; 3 | using Fragment.NetSlum.Server.Api.Models; 4 | using Riok.Mapperly.Abstractions; 5 | 6 | namespace Fragment.NetSlum.Server.Mappings; 7 | 8 | [Mapper] 9 | public static partial class GuildMapper 10 | { 11 | [MapProperty(nameof(@Guild.Members.Count), nameof(GuildInfo.MemberCount))] 12 | [MapProperty(nameof(@Guild.Stats.GoldAmount), nameof(GuildInfo.GoldAmount))] 13 | [MapProperty(nameof(@Guild.Stats.SilverAmount), nameof(GuildInfo.SilverAmount))] 14 | [MapProperty(nameof(@Guild.Stats.BronzeAmount), nameof(GuildInfo.BronzeAmount))] 15 | [MapProperty(nameof(@Guild.Stats.CurrentGp), nameof(GuildInfo.CurrentGp))] 16 | [MapProperty(nameof(@Guild.Stats.UpdatedAt), nameof(GuildInfo.LastUpdatedAt))] 17 | public static partial GuildInfo Map(Guild guild); 18 | } 19 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Server/Mappings/LobbyMapper.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using Fragment.NetSlum.Networking.Models; 4 | using Fragment.NetSlum.Server.Api.Models; 5 | using Riok.Mapperly.Abstractions; 6 | 7 | namespace Fragment.NetSlum.Server.Mappings; 8 | 9 | [Mapper] 10 | public static partial class LobbyMapper 11 | { 12 | public static Lobby Map(ChatLobbyModel model) 13 | { 14 | var obj = MapLobby(model); 15 | 16 | obj.Players = Players(model); 17 | 18 | return obj; 19 | } 20 | 21 | [MapProperty(nameof(ChatLobbyModel.LobbyId), nameof(Lobby.Id))] 22 | [MapProperty(nameof(ChatLobbyModel.LobbyName), nameof(Lobby.Name))] 23 | [MapProperty(nameof(ChatLobbyModel.LobbyType), nameof(Lobby.Type))] 24 | [MapProperty(nameof(ChatLobbyModel.PlayerCount), nameof(Lobby.PlayerCount))] 25 | public static partial Lobby MapLobby(ChatLobbyModel lobby); 26 | 27 | [MapProperty(nameof(ChatLobbyPlayer.PlayerCharacterId), nameof(LobbyPlayer.CharacterId))] 28 | [MapProperty(nameof(ChatLobbyPlayer.PlayerName), nameof(LobbyPlayer.CharacterName))] 29 | public static partial LobbyPlayer MapPlayer(ChatLobbyPlayer player); 30 | 31 | private static ICollection Players(ChatLobbyModel model) => model.GetPlayers().Select(MapPlayer).ToArray(); 32 | } 33 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Server/Program.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using Fragment.NetSlum.Server; 3 | using Microsoft.AspNetCore.Hosting; 4 | using Microsoft.Extensions.Configuration; 5 | using Microsoft.Extensions.Hosting; 6 | using Serilog; 7 | 8 | var builder = Host.CreateDefaultBuilder(args) 9 | .ConfigureAppConfiguration((_, builder) => 10 | { 11 | var assemblyConfigurationAttribute = 12 | typeof(Program).Assembly.GetCustomAttribute(); 13 | var buildConfigurationName = assemblyConfigurationAttribute?.Configuration; 14 | 15 | builder.AddJsonFile("serverConfig.json", false, true); 16 | builder.AddJsonFile("serverConfig.Local.json", true, true); 17 | 18 | if (buildConfigurationName == "Release") 19 | { 20 | builder.AddJsonFile("serverConfig.Production.json", true, true); 21 | } 22 | 23 | builder.AddEnvironmentVariables() 24 | .AddCommandLine(args); 25 | }) 26 | .ConfigureWebHostDefaults(builder => 27 | { 28 | builder.UseStartup(); 29 | }) 30 | .UseSerilog((hostingContext, _, loggerConfig) => 31 | { 32 | loggerConfig.ReadFrom.Configuration(hostingContext.Configuration); 33 | }); 34 | 35 | 36 | var app = builder.Build(); 37 | 38 | await app.RunAsync(); 39 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Server/Servers/ServerConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Fragment.NetSlum.TcpServer.Options; 2 | 3 | namespace Fragment.NetSlum.Server.Servers; 4 | 5 | public class ServerConfiguration : TcpServerOptions 6 | { 7 | public new bool ManualMode { get; set; } = true; 8 | public int TickRate { get; set; } = 30; 9 | } 10 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Server/serverConfig.Production.json: -------------------------------------------------------------------------------- 1 | { 2 | 3 | } -------------------------------------------------------------------------------- /src/Fragment.NetSlum.Server/serverConfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "Serilog": { 3 | "Using": [ 4 | "Serilog.Sinks.Console" 5 | ], 6 | "MinimumLevel": { 7 | "Default": "Debug", 8 | "Override": { 9 | "Microsoft.AspNetCore": "Warning", 10 | "Microsoft.EntityFrameworkCore": "Debug" 11 | } 12 | }, 13 | "Enrich": [ 14 | "FromLogContext", 15 | "WithMachineName" 16 | ], 17 | "WriteTo": [ 18 | { 19 | "Name": "Console", 20 | "Args": { 21 | "outputTemplate": "[{Timestamp:HH:mm:ss.fff}] [{Application}] [{Level:u3}] [{RequestId}] [{SourceContext}]: {Message:lj}{NewLine}{Exception}" 22 | } 23 | } 24 | ], 25 | "Properties": { 26 | "Application": "Fragment.NetSlum.Server", 27 | "Environment": "local" 28 | } 29 | }, 30 | "ConnectionStrings": { 31 | "Database": "" 32 | }, 33 | "TcpServer": { 34 | "IpAddress": "0.0.0.0", 35 | "Port": 49000 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.TcpServer/Extensions/SocketExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Net.Sockets; 2 | 3 | namespace Fragment.NetSlum.TcpServer.Extensions; 4 | 5 | public static class SocketExtensions 6 | { 7 | /// 8 | /// Returns the IP Address of the connected client as a string 9 | /// 10 | /// 11 | /// If using a reverse proxy, this will return the address of the proxy instead 12 | /// 13 | public static string GetClientIp(this Socket socket) 14 | { 15 | return socket.RemoteEndPoint?.ToString() == null ? string.Empty : socket.RemoteEndPoint.ToString()!.Split(":")[0]; 16 | } 17 | 18 | /// 19 | /// Returns the IP address of the server. 20 | /// This will return the IP address that the server is bound to by the OS. This could contain a LAN IP if using v/LAN 21 | /// 22 | /// 23 | /// 24 | public static string GetServerIp(this Socket socket) 25 | { 26 | return socket.LocalEndPoint?.ToString() == null ? string.Empty : socket.LocalEndPoint.ToString()!.Split(":")[0]; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.TcpServer/Fragment.NetSlum.TcpServer.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | true 7 | CS1591 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.TcpServer/ITcpServer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Buffers; 3 | 4 | namespace Fragment.NetSlum.TcpServer; 5 | 6 | public interface ITcpServer 7 | { 8 | public int ReceiveTimeoutMs { get; } 9 | public int ReceiveBufferSize { get; set; } 10 | public int SendBufferSize { get; set; } 11 | public bool ManualMode { get; } 12 | protected internal ArrayPool BufferPool { get; } 13 | public TcpSession[] Sessions { get; } 14 | 15 | public TcpSession? FindSession(Guid id); 16 | public void OnSessionDisconnect(TcpSession session); 17 | public void Start(); 18 | public void Stop(); 19 | } 20 | -------------------------------------------------------------------------------- /src/Fragment.NetSlum.TcpServer/Options/TcpServerOptions.cs: -------------------------------------------------------------------------------- 1 | namespace Fragment.NetSlum.TcpServer.Options; 2 | 3 | public class TcpServerOptions 4 | { 5 | /// 6 | /// IP Address the server should attempt to bind 7 | /// 8 | public string IpAddress { get; set; } = "0.0.0.0"; 9 | 10 | /// 11 | /// The port the server should listen on 12 | /// 13 | public int Port { get; set; } = 49000; 14 | 15 | /// 16 | /// The number of seconds in which a session will be considered timed-out 17 | /// 18 | public int SessionTimeout { get; set; } = 60; 19 | 20 | /// 21 | /// Manual mode will cause all sessions to block sending data until their respective Flush() methods are called. 22 | /// Useful for synchronizing clients in a logic loop, or for packet aggregation 23 | /// 24 | public bool ManualMode { get; set; } = false; 25 | 26 | public int ReceiveBufferSize { get; set; } = 8192; 27 | public int SendBufferSize { get; set; } = 8192; 28 | } 29 | -------------------------------------------------------------------------------- /test/Fragment.NetSlum.Networking.Test/Fragment.NetSlum.Networking.Test.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | false 7 | 8 | 9 | 10 | 11 | 12 | 13 | runtime; build; native; contentfiles; analyzers; buildtransitive 14 | all 15 | 16 | 17 | runtime; build; native; contentfiles; analyzers; buildtransitive 18 | all 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /test/Fragment.NetSlum.Networking.Test/Pipeline/Decoders/FragmentFrameDecoderTest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Fragment.NetSlum.Core.Extensions; 3 | using Fragment.NetSlum.Networking.Crypto; 4 | using Fragment.NetSlum.Networking.Objects; 5 | using Fragment.NetSlum.Networking.Pipeline.Decoders; 6 | using Xunit; 7 | 8 | namespace Fragment.NetSlum.Networking.Test.Pipeline.Decoders; 9 | 10 | public class FragmentFrameDecoderTest 11 | { 12 | [Fact] 13 | public void DecoderCanSuccessfullyParseDataTypePackets() 14 | { 15 | var clientKey = "F26C30B852E4415E1D8B719B3803ECC3".StringToByteArray(); 16 | var data = "0012003057B9B5EA2691E3E229359DC28AAF0CEB".StringToByteArray(); 17 | 18 | var crypto = new BlowfishProvider(clientKey); 19 | crypto.Initialize(); 20 | 21 | var cryptoHandler = new CryptoHandler(); 22 | cryptoHandler.ClientCipher = crypto; 23 | 24 | var decoder = new FragmentFrameDecoder(cryptoHandler); 25 | 26 | var decodedMessages = new List(); 27 | decoder.Decode(data, decodedMessages); 28 | 29 | Assert.Single(decodedMessages); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /test/Fragment.NetSlum.Networking.Test/UnitTest1.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | 3 | namespace Fragment.NetSlum.Networking.Test; 4 | 5 | public class UnitTest1 6 | { 7 | [Fact] 8 | public void Test1() 9 | { 10 | } 11 | } 12 | --------------------------------------------------------------------------------