├── _config.yml ├── docs ├── api │ ├── index.md │ └── .gitignore ├── toc.yml ├── .gitignore ├── templates │ └── darkfx │ │ ├── styles │ │ └── toggle-theme.js │ │ └── partials │ │ ├── affix.tmpl.partial │ │ └── head.tmpl.partial ├── docfx.json └── index.md ├── .gitattributes ├── NetScape.Modules.Cache ├── Language.cs ├── BaseVarType.cs ├── Exceptions │ ├── DownloaderException.cs │ └── SoundtrackException.cs ├── CacheModule.cs ├── Nuget.Projects.props ├── NetScape.Modules.Cache.csproj ├── Vector3.cs └── RuneTek5 │ ├── IndexPointer.cs │ └── RuneTek5Cache.cs ├── NetScape.Modules.Messages.Builder ├── AccessMode.cs ├── DataOrder.cs ├── DataTransformation.cs ├── FrameType.cs ├── MessageType.cs ├── MessageFrame.cs ├── FrameTypeExtensions.cs ├── Nuget.Projects.props └── NetScape.Modules.Messages.Builder.csproj ├── NetScape.Abstractions ├── Model │ ├── Game │ │ ├── Gender.cs │ │ ├── GameServerParameters.cs │ │ ├── PlayerSave.cs │ │ ├── EntityType.cs │ │ ├── WalkingQueue.cs │ │ ├── Appearance.cs │ │ └── Entity.cs │ ├── Region │ │ ├── ObjectGroup.cs │ │ ├── EntityUpdateType.cs │ │ ├── Collision │ │ │ ├── CollisionUpdateType.cs │ │ │ ├── CollisionFlag.cs │ │ │ └── DirectionFlag.cs │ │ ├── ObjectType.cs │ │ └── RegionCoordinates.cs │ ├── Messages │ │ ├── DecoderMessage.cs │ │ └── ProtoMessage.cs │ ├── World │ │ └── Updating │ │ │ ├── Blocks │ │ │ ├── AnimationBlock.cs │ │ │ └── AppearanceBlock.cs │ │ │ ├── Animation.cs │ │ │ ├── SynchronizationBlock.cs │ │ │ └── SynchronizationBlockSet.cs │ ├── Login │ │ ├── LoginRequest.cs │ │ ├── LoginDecoderState.cs │ │ ├── LoginResponse.cs │ │ └── PlayerCredentials.cs │ └── Mob.cs ├── Cache │ ├── CacheFile.cs │ ├── CompressionType.cs │ ├── DecodeException.cs │ ├── CacheFileEntryInfo.cs │ ├── CacheFileOptions.cs │ ├── CacheFileBase.cs │ └── CacheIndex.cs ├── Interfaces │ ├── Login │ │ ├── ILoginProvider.cs │ │ └── ILoginProcessor.cs │ ├── Game │ │ ├── Interface │ │ │ └── ITabManager.cs │ │ └── Player │ │ │ └── IPlayerInitializer.cs │ ├── Messages │ │ ├── IProtoMessageSender.cs │ │ ├── IMessageProvider.cs │ │ ├── IPlayerAwareHandler.cs │ │ ├── ICipherAwareHandler.cs │ │ ├── IEncoderMessage.cs │ │ ├── IMessageDecoder.cs │ │ └── RegionUpdateMessage.cs │ ├── IO │ │ ├── IChannelHandlerProvider.cs │ │ ├── IGameServer.cs │ │ ├── EventLoop │ │ │ └── IEventLoopGroupFactory.cs │ │ └── IGameServerParameters.cs │ ├── World │ │ ├── IWorld.cs │ │ ├── IEntityList.cs │ │ └── Updating │ │ │ └── IEntityUpdater.cs │ ├── Cache │ │ ├── ICacheSector.cs │ │ ├── IFileStore.cs │ │ └── IReferenceTableCache.cs │ └── Region │ │ ├── IRegionListener.cs │ │ ├── IRegionRepository.cs │ │ ├── IRegionUpdateOperation.cs │ │ ├── IGroupableEntity.cs │ │ └── Collision │ │ └── ICollisionUpdate.cs ├── Server │ └── ContainerProvider.cs ├── Util │ ├── IsaacRandomPair.cs │ └── TextUtil.cs ├── Constants.cs ├── FileSystem │ ├── IFileSystem.cs │ └── IPlayerRepository.cs ├── IO │ └── ServerChannelinitializer.cs ├── Nuget.Projects.props ├── Extensions │ ├── PathExtensions.cs │ ├── EntityTypeExtensions.cs │ └── CollisionFlagExtensions.cs └── NetScape.Abstractions.csproj ├── NetScape.Modules.FourSevenFour.LoginProtocol ├── Rs2LoginResponse.cs ├── HandshakeType.cs ├── Rs2LoginRequest.cs ├── JS5Request.cs ├── Handlers │ ├── LoginProvider.cs │ ├── LoginEncoder.cs │ └── JS5Decoder.cs ├── Nuget.Projects.props ├── FourSevenFourLoginModule.cs ├── FourSevenFourLoginStatus.cs ├── NetScape.Modules.FourSevenFour.LoginProtocol.csproj └── LoginProcessor.cs ├── NetScape.Modules.ThreeOneSeven.LoginProtocol ├── Rs2LoginResponse.cs ├── HandshakeType.cs ├── Rs2LoginRequest.cs ├── Handlers │ ├── LoginProvider.cs │ └── LoginEncoder.cs ├── ThreeOneSevenLoginModule.cs ├── Nuget.Projects.props ├── ThreeOneSevenLoginStatus.cs ├── NetScape.Modules.ThreeOneSeven.LoginProtocol.csproj └── LoginProcessor.cs ├── NetScape.Modules.FourSevenFour.World.Updating ├── Segments │ ├── SegmentType.cs │ ├── SynchronizationSegment.cs │ ├── RemoveMobSegment.cs │ ├── TeleportSegment.cs │ ├── AddPlayerSegment.cs │ └── MovementSegment.cs ├── FourSevenFourUpdatingModule.cs ├── Nuget.Projects.props └── NetScape.Modules.FourSevenFour.World.Updating.csproj ├── NetScape.Modules.ThreeOneSeven.World.Updating ├── Segments │ ├── SegmentType.cs │ ├── SynchronizationSegment.cs │ ├── RemoveMobSegment.cs │ ├── TeleportSegment.cs │ ├── AddPlayerSegment.cs │ └── MovementSegment.cs ├── ThreeOneSevenUpdatingModule.cs ├── Nuget.Projects.props └── NetScape.Modules.ThreeOneSeven.World.Updating.csproj ├── NetScape.Modules.Messages.Generator ├── GeneratorData.cs ├── FrameParameters.cs ├── MessageParameters.cs └── NetScape.Modules.Messages.Generator.csproj ├── NetScape.Modules.Region ├── RegionModule.cs ├── Nuget.Projects.props ├── NetScape.Modules.Region.csproj └── ObjectUpdateOperation.cs ├── NetScape.Modules.Region.Collision ├── CollisionModule.cs ├── Nuget.Projects.props └── NetScape.Modules.Region.Collision.csproj ├── NetScape.Modules.DAL ├── DALModule.cs ├── Nuget.Projects.props ├── Migrations │ └── 20210123212503_RemoveAppearanceFields.cs ├── NetScape.Modules.DAL.csproj └── DatabaseContext.cs ├── NetScape.Modules.Messages ├── Models │ ├── ProtoFieldCodec.cs │ └── ProtoMessageCodec.cs ├── Nuget.Projects.props ├── MessageProvider.cs ├── ProtoMessageSender.cs ├── MessageFrameEncoder.cs ├── MessageChannelHandler.cs ├── NetScape.Modules.Messages.csproj └── ProtoEncoder.cs ├── NetScape ├── Properties │ └── PublishProfiles │ │ └── FolderProfile.pubxml ├── DesignTimeDbContextFactory.cs ├── appsettings.json └── Kernel.cs ├── .github └── workflows │ ├── ci.yml │ ├── docs.yml │ └── release.yml ├── NetScape.Modules.World ├── WorldModule.cs ├── Nuget.Projects.props ├── NetScape.Modules.World.csproj └── PlayerEntityList.cs ├── .gitignore ├── NetScape.Modules.ThreeOneSeven.Game ├── Messages │ ├── Handlers │ │ ├── CommandMessageHandler.cs │ │ └── WalkingQueueMessageHandler.cs │ └── Decoders │ │ └── WalkingQueueMessageDecoder.cs ├── Nuget.Projects.props ├── Interface │ ├── RunButtonsHandler.cs │ ├── TabManager.cs │ ├── EmoteTabButtonsHandler.cs │ └── LogoutTabHandler.cs ├── NetScape.Modules.ThreeOneSeven.Game.csproj ├── ThreeOneSevenGameModule.cs └── Players │ └── PlayerInitializer.cs ├── NetScape.Modules.FourSevenFour.Game ├── Messages │ ├── Handlers │ │ ├── PingMessageHandler.cs │ │ ├── WelcomeScreenHandler.cs │ │ └── WalkingQueueMessageHandler.cs │ ├── Encoders │ │ └── SendPingMessage.cs │ └── Decoders │ │ └── WalkingQueueMessageDecoder.cs ├── Nuget.Projects.props ├── FourSevenFourGameModule.cs ├── NetScape.Modules.FourSevenFour.Game.csproj └── Player │ ├── TabManager.cs │ └── PlayerInitializer.cs ├── NetScape.Core ├── Nuget.Projects.props ├── FileSystem.cs └── NetScape.Core.csproj ├── NetScape.GameServer ├── Nuget.Projects.props ├── GameServerModule.cs ├── NetScape.Modules.Server.csproj └── IO │ ├── EventLoop │ └── GameServerEventLoopGroupFactory.cs │ └── GameServer.cs ├── NetScape.Modules.Logging.SeriLog ├── Nuget.Projects.props ├── SeriLogModule.cs └── NetScape.Modules.Logging.SeriLog.csproj ├── NetScape.Modules.DAL.Test └── NetScape.Modules.DAL.Test.csproj └── README.md /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-midnight -------------------------------------------------------------------------------- /docs/api/index.md: -------------------------------------------------------------------------------- 1 | # PLACEHOLDER 2 | NetScape Documentation -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /docs/api/.gitignore: -------------------------------------------------------------------------------- 1 | ############### 2 | # temp file # 3 | ############### 4 | *.yml 5 | .manifest 6 | -------------------------------------------------------------------------------- /docs/toc.yml: -------------------------------------------------------------------------------- 1 | - name: Articles 2 | href: articles/ 3 | - name: Api Documentation 4 | href: api/ 5 | homepage: api/index.md 6 | -------------------------------------------------------------------------------- /NetScape.Modules.Cache/Language.cs: -------------------------------------------------------------------------------- 1 | namespace NetScape.Modules.Cache 2 | { 3 | public enum Language 4 | { 5 | English = 0 6 | } 7 | } -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | ############### 2 | # folder # 3 | ############### 4 | /**/DROP/ 5 | /**/TEMP/ 6 | /**/packages/ 7 | /**/bin/ 8 | /**/obj/ 9 | _site 10 | -------------------------------------------------------------------------------- /NetScape.Modules.Messages.Builder/AccessMode.cs: -------------------------------------------------------------------------------- 1 | namespace NetScape.Modules.Messages.Builder 2 | { 3 | public enum AccessMode 4 | { 5 | Byte, Bit 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Model/Game/Gender.cs: -------------------------------------------------------------------------------- 1 | namespace NetScape.Abstractions.Model.Game 2 | { 3 | public enum Gender 4 | { 5 | Male, 6 | Female 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /NetScape.Modules.Messages.Builder/DataOrder.cs: -------------------------------------------------------------------------------- 1 | namespace NetScape.Modules.Messages.Builder 2 | { 3 | public enum DataOrder 4 | { 5 | Big, Little, Middle, InversedMiddle 6 | } 7 | } -------------------------------------------------------------------------------- /NetScape.Modules.Messages.Builder/DataTransformation.cs: -------------------------------------------------------------------------------- 1 | namespace NetScape.Modules.Messages.Builder 2 | { 3 | public enum DataTransformation 4 | { 5 | None, Add, Negate, Subtract 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /NetScape.Modules.Messages.Builder/FrameType.cs: -------------------------------------------------------------------------------- 1 | namespace NetScape.Modules.Messages.Builder 2 | { 3 | public enum FrameType 4 | { 5 | Raw, Fixed, VariableByte, VariableShort, ReadAll 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /NetScape.Modules.Cache/BaseVarType.cs: -------------------------------------------------------------------------------- 1 | namespace NetScape.Modules.Cache 2 | { 3 | public enum BaseVarType 4 | { 5 | None, 6 | 7 | Integer, 8 | Long, 9 | String, 10 | Vector3 11 | } 12 | } -------------------------------------------------------------------------------- /NetScape.Abstractions/Cache/CacheFile.cs: -------------------------------------------------------------------------------- 1 | namespace NetScape.Abstractions.Cache 2 | { 3 | public class CacheFile 4 | { 5 | public CacheFileInfo FileInfo { get; set; } 6 | 7 | public byte[] Bytes { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Interfaces/Login/ILoginProvider.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Interfaces.IO; 2 | 3 | namespace NetScape.Abstractions.Interfaces.Login 4 | { 5 | public interface ILoginProvider : IChannelHandlerProvider 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Cache/CompressionType.cs: -------------------------------------------------------------------------------- 1 | namespace NetScape.Abstractions.Cache 2 | { 3 | public enum CompressionType 4 | { 5 | Undefined = -1, 6 | None = 0, 7 | Bzip2 = 1, 8 | Gzip = 2, 9 | Lzma = 3 10 | } 11 | } -------------------------------------------------------------------------------- /NetScape.Modules.FourSevenFour.LoginProtocol/Rs2LoginResponse.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Model.Login; 2 | 3 | namespace NetScape.Modules.FourSevenFour.LoginProtocol 4 | { 5 | public class Rs2LoginResponse : LoginResponse 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /NetScape.Modules.ThreeOneSeven.LoginProtocol/Rs2LoginResponse.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Model.Login; 2 | 3 | namespace NetScape.Modules.ThreeOneSeven.LoginProtocol 4 | { 5 | public class Rs2LoginResponse : LoginResponse 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /NetScape.Modules.FourSevenFour.LoginProtocol/HandshakeType.cs: -------------------------------------------------------------------------------- 1 | namespace NetScape.Modules.FourSevenFour.LoginProtocol 2 | { 3 | public enum HandshakeType : byte 4 | { 5 | Default = 0, 6 | ServiceGame = 14, 7 | ServiceUpdate = 15 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /NetScape.Modules.ThreeOneSeven.LoginProtocol/HandshakeType.cs: -------------------------------------------------------------------------------- 1 | namespace NetScape.Modules.ThreeOneSeven.LoginProtocol 2 | { 3 | public enum HandshakeType : byte 4 | { 5 | Default = 0, 6 | ServiceGame = 14, 7 | ServiceUpdate = 15 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Model/Region/ObjectGroup.cs: -------------------------------------------------------------------------------- 1 | namespace NetScape.Abstractions.Model.Region 2 | { 3 | public enum ObjectGroup : int 4 | { 5 | Wall = 0, 6 | Wall_Decoration = 1, 7 | Interactable_Object = 2, 8 | Ground_Decoration = 3 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /NetScape.Modules.Messages.Builder/MessageType.cs: -------------------------------------------------------------------------------- 1 | namespace NetScape.Modules.Messages.Builder 2 | { 3 | public enum MessageType 4 | { 5 | Byte = sizeof(byte), 6 | Short = sizeof(short), 7 | TriByte = 3, 8 | Int = sizeof(int), 9 | Long = sizeof(long) 10 | } 11 | } -------------------------------------------------------------------------------- /NetScape.Modules.FourSevenFour.LoginProtocol/Rs2LoginRequest.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Model.Login; 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace NetScape.Modules.FourSevenFour.LoginProtocol 6 | { 7 | public record Rs2LoginRequest : LoginRequest 8 | { 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /NetScape.Modules.ThreeOneSeven.LoginProtocol/Rs2LoginRequest.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Model.Login; 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace NetScape.Modules.ThreeOneSeven.LoginProtocol 6 | { 7 | public record Rs2LoginRequest : LoginRequest 8 | { 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /NetScape.Modules.FourSevenFour.World.Updating/Segments/SegmentType.cs: -------------------------------------------------------------------------------- 1 | namespace NetScape.Modules.FourSevenFour.World.Updating.Segments 2 | { 3 | public enum SegmentType 4 | { 5 | Add_Mob, 6 | No_Movement, 7 | Remove_Mob, 8 | Run, 9 | Teleport, 10 | Walk 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /NetScape.Modules.ThreeOneSeven.World.Updating/Segments/SegmentType.cs: -------------------------------------------------------------------------------- 1 | namespace NetScape.Modules.ThreeOneSeven.World.Updating.Segments 2 | { 3 | public enum SegmentType 4 | { 5 | Add_Mob, 6 | No_Movement, 7 | Remove_Mob, 8 | Run, 9 | Teleport, 10 | Walk 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Server/ContainerProvider.cs: -------------------------------------------------------------------------------- 1 | using Autofac; 2 | 3 | namespace NetScape.Abstractions.Server 4 | { 5 | /// 6 | /// Provides the container across the application 7 | /// 8 | public class ContainerProvider 9 | { 10 | public IContainer Container { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Interfaces/Game/Interface/ITabManager.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace NetScape.Abstractions.Interfaces.Game.Interface 4 | { 5 | public interface ITabManager 6 | { 7 | Task SetTabAsync(Model.Game.Player player, int tabId, int interfaceId); 8 | 9 | int[] Default { get; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Model/Game/GameServerParameters.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Interfaces.IO; 2 | 3 | namespace NetScape.Abstractions.Model.Game 4 | { 5 | public sealed class GameServerParameters : IGameServerParameters 6 | { 7 | public string BindAddress { get; set; } 8 | public ushort Port { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Interfaces/Messages/IProtoMessageSender.cs: -------------------------------------------------------------------------------- 1 | using Google.Protobuf; 2 | using NetScape.Abstractions.Model.Game; 3 | using System.Threading.Tasks; 4 | 5 | namespace NetScape.Abstractions.Interfaces.Messages 6 | { 7 | public interface IProtoMessageSender 8 | { 9 | Task SendAsync(Player player, IMessage message); 10 | } 11 | } -------------------------------------------------------------------------------- /NetScape.Abstractions/Interfaces/IO/IChannelHandlerProvider.cs: -------------------------------------------------------------------------------- 1 | using DotNetty.Transport.Channels; 2 | using System; 3 | 4 | namespace NetScape.Abstractions.Interfaces.IO 5 | { 6 | /// 7 | /// Provides channel handlers 8 | /// 9 | public interface IChannelHandlerProvider 10 | { 11 | Func Provide { get; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Model/Messages/DecoderMessage.cs: -------------------------------------------------------------------------------- 1 | using Google.Protobuf; 2 | using NetScape.Abstractions.Model.Game; 3 | 4 | namespace NetScape.Abstractions.Model.Messages 5 | { 6 | public class DecoderMessage where TMessage : IMessage 7 | { 8 | public TMessage Message { get; set; } 9 | public Player Player { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Model/World/Updating/Blocks/AnimationBlock.cs: -------------------------------------------------------------------------------- 1 | namespace NetScape.Abstractions.Model.World.Updating.Blocks 2 | { 3 | public class AnimationBlock : SynchronizationBlock 4 | { 5 | public Animation Animation { get; } 6 | 7 | public AnimationBlock(Animation animation) 8 | { 9 | Animation = animation; 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /NetScape.Abstractions/Interfaces/World/IWorld.cs: -------------------------------------------------------------------------------- 1 | using Autofac; 2 | using NetScape.Abstractions.Interfaces.Region; 3 | using NetScape.Abstractions.Model.Game; 4 | 5 | namespace NetScape.Abstractions.Interfaces.World 6 | { 7 | public interface IWorld : IStartable 8 | { 9 | void Add(Player player); 10 | void Remove(Player player); 11 | IRegionRepository RegionRepository { get; } 12 | } 13 | } -------------------------------------------------------------------------------- /NetScape.Modules.Messages.Generator/GeneratorData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NetScape.Modules.Messages.Builder; 3 | 4 | namespace NetScape.Modules.Messages.Generator 5 | { 6 | [Obsolete] 7 | public class GeneratorData 8 | { 9 | public string Name { get; set; } 10 | public int Id { get; set; } 11 | public MessageParameters[] Params { get; set; } 12 | public FrameType FrameType { get; set; } 13 | } 14 | } -------------------------------------------------------------------------------- /NetScape.Modules.Region/RegionModule.cs: -------------------------------------------------------------------------------- 1 | using Autofac; 2 | using NetScape.Abstractions.Interfaces.Region; 3 | 4 | namespace NetScape.Modules.Region 5 | { 6 | public class RegionModule : Module 7 | { 8 | protected override void Load(ContainerBuilder builder) 9 | { 10 | builder.RegisterType().As().SingleInstance(); 11 | base.Load(builder); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Interfaces/World/IEntityList.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using NetScape.Abstractions.Model.Game; 3 | 4 | namespace NetScape.Abstractions.Interfaces.World 5 | { 6 | public interface IEntityList where TEntity : Entity 7 | { 8 | void Add(TEntity entity); 9 | 10 | void Remove(TEntity entity); 11 | 12 | TEntity[] Entities { get; } 13 | 14 | int Count { get; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /NetScape.Modules.Region.Collision/CollisionModule.cs: -------------------------------------------------------------------------------- 1 | using Autofac; 2 | using NetScape.Abstractions.Interfaces.Region.Collision; 3 | 4 | namespace NetScape.Modules.Region.Collision 5 | { 6 | public class CollisionModule : Module 7 | { 8 | protected override void Load(ContainerBuilder builder) 9 | { 10 | builder.RegisterType().As(); 11 | base.Load(builder); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Interfaces/Messages/IMessageProvider.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Interfaces.IO; 2 | 3 | namespace NetScape.Abstractions.Interfaces.Messages 4 | { 5 | /// 6 | /// Provides channel handlers for after the user has been authenticated 7 | /// 8 | /// 9 | public interface IMessageProvider : IChannelHandlerProvider 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Util/IsaacRandomPair.cs: -------------------------------------------------------------------------------- 1 | namespace NetScape.Abstractions.Util 2 | { 3 | public class IsaacRandomPair 4 | { 5 | public IsaacRandom EncodingRandom { get; } 6 | public IsaacRandom DecodingRandom { get; } 7 | 8 | public IsaacRandomPair(IsaacRandom encodingRandom, IsaacRandom decodingRandom) 9 | { 10 | this.EncodingRandom = encodingRandom; 11 | this.DecodingRandom = decodingRandom; 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /NetScape.Modules.DAL/DALModule.cs: -------------------------------------------------------------------------------- 1 | using Autofac; 2 | using NetScape.Abstractions.FileSystem; 3 | using NetScape.Abstractions.Model.Game; 4 | 5 | namespace NetScape.Modules.DAL 6 | { 7 | public class DALModule : Module where TPlayer : Player, new() 8 | { 9 | protected override void Load(ContainerBuilder builder) 10 | { 11 | builder.RegisterType>().As(); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Constants.cs: -------------------------------------------------------------------------------- 1 | using DotNetty.Common.Utilities; 2 | using NetScape.Abstractions.Model; 3 | using NetScape.Abstractions.Model.Game; 4 | 5 | namespace NetScape.Abstractions 6 | { 7 | public class Constants 8 | { 9 | public static int RegionSize { get; } = 8; 10 | public static AttributeKey PlayerAttributeKey { get; } = AttributeKey.ValueOf("Player"); 11 | public static Position HomePosition => new Position(3333, 3333, 0); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Interfaces/Cache/ICacheSector.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Cache; 2 | 3 | namespace NetScape.Abstractions.Interfaces.Cache 4 | { 5 | public interface ICacheSector 6 | { 7 | int ChunkIndex { get; } 8 | bool Extended { get; } 9 | int FileId { get; } 10 | CacheIndex Index { get; } 11 | int? NextSectorPosition { get; set; } 12 | byte[] Payload { get; } 13 | int Position { get; set; } 14 | byte[] Encode(); 15 | } 16 | } -------------------------------------------------------------------------------- /NetScape.Modules.Messages.Generator/FrameParameters.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace NetScape.Modules.Messages.Generator 4 | { 5 | [Obsolete] 6 | public class FrameParameters 7 | { 8 | public string Namespace { get; set; } 9 | public GeneratorMessageType Type { get; set; } 10 | public GeneratorData[] Messages { get; set; } 11 | } 12 | 13 | [Obsolete] 14 | public enum GeneratorMessageType 15 | { 16 | Decoder, 17 | Encoder 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /NetScape.Modules.Messages.Generator/MessageParameters.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NetScape.Modules.Messages.Builder; 3 | 4 | namespace NetScape.Modules.Messages.Generator 5 | { 6 | [Obsolete] 7 | public class MessageParameters 8 | { 9 | public string Name { get; set; } 10 | public MessageType Type { get; set; } 11 | public DataOrder? Order { get; set; } 12 | public DataTransformation? Transform { get; set; } 13 | public bool Signed { get; set; } 14 | } 15 | } -------------------------------------------------------------------------------- /NetScape.Abstractions/Cache/DecodeException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace NetScape.Abstractions.Cache 4 | { 5 | [Serializable] 6 | public class DecodeException : Exception 7 | { 8 | public DecodeException() 9 | { 10 | } 11 | 12 | public DecodeException(string message) : base(message) 13 | { 14 | } 15 | 16 | public DecodeException(string message, Exception innerException) : base(message, innerException) 17 | { 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /NetScape.Abstractions/Model/World/Updating/Animation.cs: -------------------------------------------------------------------------------- 1 | namespace NetScape.Abstractions.Model.World.Updating 2 | { 3 | public record Animation 4 | { 5 | public static readonly Animation StopAnimation = new Animation(-1); 6 | public int Delay { get; } 7 | public int Id { get; } 8 | 9 | public Animation(int id) : this(id, 0) { } 10 | 11 | public Animation(int id, int delay) 12 | { 13 | Id = id; 14 | Delay = delay; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /NetScape.Modules.Messages/Models/ProtoFieldCodec.cs: -------------------------------------------------------------------------------- 1 | using Google.Protobuf.Reflection; 2 | 3 | namespace NetScape.Modules.Messages.Models 4 | { 5 | public class ProtoFieldCodec 6 | { 7 | public FieldDescriptor FieldDescriptor { get; } 8 | public FieldCodec FieldCodec { get; } 9 | 10 | public ProtoFieldCodec(FieldDescriptor fieldDescriptor, FieldCodec fieldCodec) 11 | { 12 | FieldDescriptor = fieldDescriptor; 13 | FieldCodec = fieldCodec; 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /NetScape.Abstractions/Interfaces/Cache/IFileStore.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Cache; 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | namespace NetScape.Abstractions.Interfaces.Cache 6 | { 7 | public interface IFileStore : IDisposable 8 | { 9 | string CacheDirectory { get; } 10 | bool ReadOnly { get; } 11 | IEnumerable GetIndexes(); 12 | byte[] ReadFileData(CacheIndex index, int value); 13 | void WriteFileData(CacheIndex index, int value, byte[] v); 14 | } 15 | } -------------------------------------------------------------------------------- /NetScape.Abstractions/Interfaces/IO/IGameServer.cs: -------------------------------------------------------------------------------- 1 | using DotNetty.Transport.Channels; 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace NetScape.Abstractions.Interfaces.IO 6 | { 7 | public interface IGameServer : IAsyncDisposable 8 | { 9 | /// 10 | /// The Server Channel 11 | /// 12 | IChannel Channel { get; set; } 13 | 14 | /// 15 | /// Binds the game server 16 | /// 17 | Task BindAsync(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /NetScape.Modules.Cache/Exceptions/DownloaderException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace NetScape.Modules.Cache.Exceptions 4 | { 5 | [Serializable] 6 | public class DownloaderException : Exception 7 | { 8 | public DownloaderException() 9 | { 10 | } 11 | 12 | public DownloaderException(string message) : base(message) 13 | { 14 | } 15 | 16 | public DownloaderException(string message, Exception innerException) : base(message, innerException) 17 | { 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /NetScape.Modules.Cache/Exceptions/SoundtrackException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace NetScape.Modules.Cache.Exceptions 4 | { 5 | [Serializable] 6 | public class SoundtrackException : Exception 7 | { 8 | public SoundtrackException() 9 | { 10 | } 11 | 12 | public SoundtrackException(string message) : base(message) 13 | { 14 | } 15 | 16 | public SoundtrackException(string message, Exception innerException) : base(message, innerException) 17 | { 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /NetScape.Abstractions/Interfaces/Messages/IPlayerAwareHandler.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Model.Game; 2 | 3 | namespace NetScape.Abstractions.Interfaces.Messages 4 | { 5 | /// 6 | /// A handler which is aware of the player 7 | /// 8 | public interface IPlayerAwareHandler 9 | { 10 | /// 11 | /// Gets or sets the player. 12 | /// 13 | /// 14 | /// The player. 15 | /// 16 | public Player Player { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /NetScape/Properties/PublishProfiles/FolderProfile.pubxml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | FileSystem 8 | Release 9 | Any CPU 10 | net5.0 11 | bin\Release\net5.0\publish\ 12 | 13 | -------------------------------------------------------------------------------- /NetScape.Modules.FourSevenFour.World.Updating/Segments/SynchronizationSegment.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Model.World.Updating; 2 | 3 | namespace NetScape.Modules.FourSevenFour.World.Updating.Segments 4 | { 5 | public abstract class SynchronizationSegment 6 | { 7 | public SynchronizationBlockSet BlockSet { get; } 8 | 9 | public SynchronizationSegment(SynchronizationBlockSet blockSet) 10 | { 11 | BlockSet = blockSet; 12 | } 13 | 14 | public abstract SegmentType Type { get; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /NetScape.Modules.ThreeOneSeven.World.Updating/Segments/SynchronizationSegment.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Model.World.Updating; 2 | 3 | namespace NetScape.Modules.ThreeOneSeven.World.Updating.Segments 4 | { 5 | public abstract class SynchronizationSegment 6 | { 7 | public SynchronizationBlockSet BlockSet { get; } 8 | 9 | public SynchronizationSegment(SynchronizationBlockSet blockSet) 10 | { 11 | BlockSet = blockSet; 12 | } 13 | 14 | public abstract SegmentType Type { get; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /NetScape.Modules.FourSevenFour.World.Updating/Segments/RemoveMobSegment.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Model.World.Updating; 2 | 3 | namespace NetScape.Modules.FourSevenFour.World.Updating.Segments 4 | { 5 | public class RemoveMobSegment : SynchronizationSegment 6 | { 7 | private static readonly SynchronizationBlockSet EmptyBlockSet = new SynchronizationBlockSet(); 8 | 9 | public RemoveMobSegment() : base(EmptyBlockSet) 10 | { 11 | 12 | } 13 | 14 | public override SegmentType Type => SegmentType.Remove_Mob; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /NetScape.Modules.ThreeOneSeven.World.Updating/Segments/RemoveMobSegment.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Model.World.Updating; 2 | 3 | namespace NetScape.Modules.ThreeOneSeven.World.Updating.Segments 4 | { 5 | public class RemoveMobSegment : SynchronizationSegment 6 | { 7 | private static readonly SynchronizationBlockSet EmptyBlockSet = new SynchronizationBlockSet(); 8 | 9 | public RemoveMobSegment() : base(EmptyBlockSet) 10 | { 11 | 12 | } 13 | 14 | public override SegmentType Type => SegmentType.Remove_Mob; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: .NET 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@v2 14 | - name: Setup .NET 15 | uses: actions/setup-dotnet@v1 16 | with: 17 | dotnet-version: 5.0.x 18 | - name: Restore dependencies 19 | run: dotnet restore 20 | - name: Build 21 | run: dotnet build --no-restore 22 | - name: Test 23 | run: dotnet test --no-build --verbosity normal 24 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Model/Messages/ProtoMessage.cs: -------------------------------------------------------------------------------- 1 | using Google.Protobuf; 2 | using NetScape.Abstractions.Model.Game; 3 | 4 | namespace NetScape.Abstractions.Model.Messages 5 | { 6 | public class ProtoMessage 7 | { 8 | public Player Player { get; } 9 | public int Opcode { get; } 10 | public IMessage Message { get; } 11 | 12 | public ProtoMessage(int opcode, Player player, IMessage message) 13 | { 14 | Player = player; 15 | Opcode = opcode; 16 | Message = message; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /NetScape.Modules.FourSevenFour.World.Updating/FourSevenFourUpdatingModule.cs: -------------------------------------------------------------------------------- 1 | using Autofac; 2 | using NetScape.Abstractions.Interfaces.World.Updating; 3 | using NetScape.Abstractions.Model.Game; 4 | 5 | namespace NetScape.Modules.FourSevenFour.World.Updating 6 | { 7 | public class FourSevenFourUpdatingModule : Module 8 | { 9 | protected override void Load(ContainerBuilder builder) 10 | { 11 | builder.RegisterType() 12 | .As>(); 13 | base.Load(builder); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /NetScape.Modules.ThreeOneSeven.World.Updating/ThreeOneSevenUpdatingModule.cs: -------------------------------------------------------------------------------- 1 | using Autofac; 2 | using NetScape.Abstractions.Interfaces.World.Updating; 3 | using NetScape.Abstractions.Model.Game; 4 | 5 | namespace NetScape.Modules.ThreeOneSeven.World.Updating 6 | { 7 | public class ThreeOneSevenUpdatingModule : Module 8 | { 9 | protected override void Load(ContainerBuilder builder) 10 | { 11 | builder.RegisterType() 12 | .As>(); 13 | base.Load(builder); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Interfaces/Messages/ICipherAwareHandler.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Util; 2 | 3 | namespace NetScape.Abstractions.Interfaces.Messages 4 | { 5 | /// 6 | /// A handler which has a cipher 7 | /// 8 | public interface ICipherAwareHandler 9 | { 10 | /// 11 | /// Gets or sets the cipher pair. 12 | /// 13 | /// 14 | /// The cipher pair. 15 | /// 16 | IsaacRandomPair CipherPair { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Interfaces/Region/IRegionListener.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Model.Game; 2 | using NetScape.Abstractions.Model.Region; 3 | 4 | namespace NetScape.Abstractions.Interfaces.Region 5 | { 6 | /// 7 | /// A class that should be implemented by listeners that execute actions when an entity is added, moved, or removed from 8 | /// a region. 9 | /// Major 10 | /// 11 | public interface IRegionListener 12 | { 13 | void Execute(IRegion region, Entity entity, EntityUpdateType type); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /NetScape.Modules.Cache/CacheModule.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Interfaces.Cache; 2 | using NetScape.Modules.Cache; 3 | using NetScape.Modules.Cache.RuneTek5; 4 | using Autofac; 5 | 6 | namespace NetScape.Modules.Cache 7 | { 8 | public class CacheModule : Module 9 | { 10 | protected override void Load(ContainerBuilder builder) 11 | { 12 | builder.RegisterType().As().As().SingleInstance(); 13 | builder.RegisterType().As().SingleInstance(); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /NetScape.Modules.World/WorldModule.cs: -------------------------------------------------------------------------------- 1 | using Autofac; 2 | using NetScape.Abstractions.Interfaces.World; 3 | using NetScape.Abstractions.Model.Game; 4 | 5 | namespace NetScape.Modules.World 6 | { 7 | public class WorldModule : Module 8 | { 9 | protected override void Load(ContainerBuilder builder) 10 | { 11 | builder.RegisterType().As().As().SingleInstance(); 12 | builder.RegisterType().As>().SingleInstance(); 13 | base.Load(builder); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Model/Game/PlayerSave.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using System.ComponentModel.DataAnnotations.Schema; 3 | 4 | namespace NetScape.Abstractions.Model.Game 5 | { 6 | public partial class Player 7 | { 8 | [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 9 | public int Id { get; set; } 10 | 11 | [Key] 12 | public string Username { get; set; } 13 | public string Password { get; set; } 14 | public Appearance Appearance { get; set; } 15 | public int AppearanceId { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /NetScape.Modules.FourSevenFour.LoginProtocol/JS5Request.cs: -------------------------------------------------------------------------------- 1 | namespace NetScape.Modules.FourSevenFour.LoginProtocol 2 | { 3 | public class JS5Request 4 | { 5 | public int Index { get; } 6 | public int File { get; } 7 | public bool Priority { get; } 8 | public int EncryptionKey { get; } 9 | public JS5Request(int index, int file, bool priority, int encryptionKey) 10 | { 11 | Index = index; 12 | File = file; 13 | Priority = priority; 14 | EncryptionKey = encryptionKey; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /NetScape.Abstractions/FileSystem/IFileSystem.cs: -------------------------------------------------------------------------------- 1 | namespace NetScape.Abstractions.FileSystem 2 | { 3 | public interface IFileSystem 4 | { 5 | /// 6 | /// Gets the base file system path. 7 | /// 8 | /// 9 | /// The file system base path. 10 | /// 11 | string BasePath { get; } 12 | 13 | /// 14 | /// Gets the cache path. 15 | /// 16 | /// 17 | /// The cache path. 18 | /// 19 | string CachePath { get; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Interfaces/Messages/IEncoderMessage.cs: -------------------------------------------------------------------------------- 1 | using DotNetty.Buffers; 2 | 3 | namespace NetScape.Abstractions.Interfaces.Messages 4 | { 5 | /// 6 | /// Outgoing message encoder 7 | /// 8 | /// The type of message 9 | public interface IEncoderMessage 10 | { 11 | /// 12 | /// Converts to message. 13 | /// 14 | /// The allocator. 15 | /// T 16 | T ToMessage(IByteBufferAllocator alloc); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Model/Region/EntityUpdateType.cs: -------------------------------------------------------------------------------- 1 | namespace NetScape.Abstractions.Model.Region 2 | { 3 | /// 4 | /// Major 5 | /// 6 | public enum EntityUpdateType 7 | { 8 | /// 9 | /// The add type, when an Entity has been added to a 10 | /// 11 | Add, 12 | 13 | /// 14 | /// The remove type, when an Entity has been removed from a 15 | /// 16 | Remove 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /NetScape.Modules.FourSevenFour.World.Updating/Segments/TeleportSegment.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Model; 2 | using NetScape.Abstractions.Model.World.Updating; 3 | 4 | namespace NetScape.Modules.FourSevenFour.World.Updating.Segments 5 | { 6 | public class TeleportSegment : SynchronizationSegment 7 | { 8 | public Position Destination { get; } 9 | public TeleportSegment(SynchronizationBlockSet blockSet, Position dest) : base(blockSet) 10 | { 11 | Destination = dest; 12 | } 13 | 14 | public override SegmentType Type => SegmentType.Teleport; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /NetScape.Modules.ThreeOneSeven.World.Updating/Segments/TeleportSegment.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Model; 2 | using NetScape.Abstractions.Model.World.Updating; 3 | 4 | namespace NetScape.Modules.ThreeOneSeven.World.Updating.Segments 5 | { 6 | public class TeleportSegment : SynchronizationSegment 7 | { 8 | public Position Destination { get; } 9 | public TeleportSegment(SynchronizationBlockSet blockSet, Position dest) : base(blockSet) 10 | { 11 | Destination = dest; 12 | } 13 | 14 | public override SegmentType Type => SegmentType.Teleport; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *.*~ 3 | project.lock.json 4 | .DS_Store 5 | *.pyc 6 | nupkg/ 7 | 8 | # Visual Studio Code 9 | .vscode 10 | 11 | # Rider 12 | .idea 13 | 14 | # User-specific files 15 | *.suo 16 | *.user 17 | *.userosscache 18 | *.sln.docstates 19 | 20 | # Build results 21 | [Dd]ebug/ 22 | [Dd]ebugPublic/ 23 | [Rr]elease/ 24 | [Rr]eleases/ 25 | x64/ 26 | x86/ 27 | build/ 28 | bld/ 29 | [Bb]in/ 30 | [Oo]bj/ 31 | [Oo]ut/ 32 | msbuild.log 33 | msbuild.err 34 | msbuild.wrn 35 | 36 | # Visual Studio 2015 37 | .vs/ 38 | ASPNetScape/Properties/PublishProfiles/FolderProfile.pubxml 39 | NetScape.Modules.Messages/Generated/ 40 | -------------------------------------------------------------------------------- /NetScape.Modules.Messages.Builder/MessageFrame.cs: -------------------------------------------------------------------------------- 1 | using DotNetty.Buffers; 2 | using System; 3 | 4 | namespace NetScape.Modules.Messages.Builder 5 | { 6 | /** 7 | * @author Graham 8 | */ 9 | [Serializable] 10 | public class MessageFrame 11 | { 12 | public int Id { get; } 13 | public FrameType Type { get; } 14 | public IByteBuffer Payload { get; } 15 | 16 | public MessageFrame(int opcode, FrameType type, IByteBuffer payload) 17 | { 18 | Id = opcode; 19 | Type = type; 20 | Payload = payload; 21 | } 22 | 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Model/Region/Collision/CollisionUpdateType.cs: -------------------------------------------------------------------------------- 1 | namespace NetScape.Abstractions.Model.Region.Collision 2 | { 3 | public enum CollisionUpdateType 4 | { 5 | /// 6 | /// Indicates that a will be adding new flags to collision matrices 7 | /// 8 | Adding, 9 | 10 | /// 11 | /// Indicates that a will be clearing existing flags from collision matrices. 12 | /// 13 | Removing 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Interfaces/Region/IRegionRepository.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Model; 2 | using NetScape.Abstractions.Model.Region; 3 | using System.Collections.Generic; 4 | 5 | namespace NetScape.Abstractions.Interfaces.Region 6 | { 7 | public interface IRegionRepository 8 | { 9 | void AddRegionListener(IRegionListener listener); 10 | bool Contains(IRegion region); 11 | bool Contains(RegionCoordinates coordinates); 12 | IRegion FromPosition(Position position); 13 | IRegion Get(RegionCoordinates coordinates); 14 | List GetRegions(); 15 | bool Remove(IRegion region); 16 | } 17 | } -------------------------------------------------------------------------------- /docs/templates/darkfx/styles/toggle-theme.js: -------------------------------------------------------------------------------- 1 | const sw = document.getElementById("switch-style"), b = document.body; 2 | if (sw && b) { 3 | sw.checked = window.localStorage && localStorage.getItem("theme") === "dark-theme" || !window.localStorage; 4 | b.classList.toggle("dark-theme", sw.checked) 5 | b.classList.toggle("light-theme", !sw.checked) 6 | 7 | sw.addEventListener("change", function (){ 8 | b.classList.toggle("dark-theme", this.checked) 9 | b.classList.toggle("light-theme", !this.checked) 10 | if (window.localStorage) { 11 | this.checked ? localStorage.setItem("theme", "dark-theme") : localStorage.setItem("theme", "light-theme") 12 | } 13 | }) 14 | } -------------------------------------------------------------------------------- /NetScape.Modules.ThreeOneSeven.World.Updating/Segments/AddPlayerSegment.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Model; 2 | using NetScape.Abstractions.Model.World.Updating; 3 | 4 | namespace NetScape.Modules.ThreeOneSeven.World.Updating.Segments 5 | { 6 | public class AddPlayerSegment : SynchronizationSegment 7 | { 8 | public override SegmentType Type => SegmentType.Add_Mob; 9 | public int Index { get; } 10 | public Position Position { get; } 11 | 12 | public AddPlayerSegment(SynchronizationBlockSet blockSet, int index, Position position) : base(blockSet) 13 | { 14 | Index = index; 15 | Position = position; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Interfaces/Game/Player/IPlayerInitializer.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Model.Login; 2 | using System.Threading.Tasks; 3 | 4 | namespace NetScape.Abstractions.Interfaces.Game.Player 5 | { 6 | /// 7 | /// Initializes a player after login is complete. 8 | /// 9 | public interface IPlayerInitializer 10 | { 11 | /// 12 | /// Initializes a after 13 | /// authenticates the player successfully. 14 | /// 15 | /// The player. 16 | Task InitializeAsync(Model.Game.Player player); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Interfaces/IO/EventLoop/IEventLoopGroupFactory.cs: -------------------------------------------------------------------------------- 1 | using DotNetty.Transport.Channels; 2 | using System; 3 | 4 | namespace NetScape.Abstractions.Interfaces.IO.EventLoop 5 | { 6 | /// 7 | /// Handles distribution and disposal of all event loops 8 | /// 9 | /// 10 | public interface IEventLoopGroupFactory : IDisposable 11 | { 12 | /// Gets or Creates new loop group for the netty handlers. 13 | IEventLoopGroup GetWorkerGroup(); 14 | 15 | /// Gets or Creates new loop group for the socket IO. 16 | IEventLoopGroup GetBossGroup(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /NetScape.Abstractions/IO/ServerChannelinitializer.cs: -------------------------------------------------------------------------------- 1 | using DotNetty.Transport.Channels; 2 | using NetScape.Abstractions.Interfaces.Login; 3 | 4 | namespace NetScape.Abstractions.IO 5 | { 6 | public class ServerChannelInitializer : ChannelInitializer 7 | { 8 | private readonly ILoginProvider _loginProvider; 9 | 10 | public ServerChannelInitializer(ILoginProvider loginProvider) 11 | { 12 | _loginProvider = loginProvider; 13 | } 14 | 15 | protected override void InitChannel(IChannel channel) 16 | { 17 | var pipeline = channel.Pipeline; 18 | pipeline.AddLast(_loginProvider.Provide()); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Interfaces/IO/IGameServerParameters.cs: -------------------------------------------------------------------------------- 1 | namespace NetScape.Abstractions.Interfaces.IO 2 | { 3 | /// 4 | /// Parameters of the game server 5 | /// 6 | public interface IGameServerParameters 7 | { 8 | /// 9 | /// Gets or sets the bind address. 10 | /// 11 | /// 12 | /// The bind address. 13 | /// 14 | string BindAddress { get; set; } 15 | 16 | /// 17 | /// Gets or sets the port. 18 | /// 19 | /// 20 | /// The port. 21 | /// 22 | ushort Port { get; set; } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Interfaces/World/Updating/IEntityUpdater.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Interfaces.Messages; 2 | using NetScape.Abstractions.Model.Game; 3 | using NetScape.Abstractions.Model.Region; 4 | using System.Collections.Generic; 5 | using System.Threading.Tasks; 6 | 7 | namespace NetScape.Abstractions.Interfaces.World.Updating 8 | { 9 | public interface IEntityUpdater where T : Entity 10 | { 11 | Task PreUpdateAsync(T entity, Dictionary> encodes, 12 | Dictionary> updates); 13 | 14 | Task UpdateAsync(T entity); 15 | Task PostUpdateAsync(T entity); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Model/Region/Collision/CollisionFlag.cs: -------------------------------------------------------------------------------- 1 | namespace NetScape.Abstractions.Model.Region.Collision 2 | { 3 | public enum CollisionFlag 4 | { 5 | Mob_North_West = 1, 6 | Mob_North = 2, 7 | Mob_North_East = 3, 8 | Mob_East = 4, 9 | Mob_South_East = 5, 10 | Mob_South = 6, 11 | Mob_South_West = 7, 12 | Mob_West = 8, 13 | Projectile_North_West = 9, 14 | Projectile_North = 10, 15 | Projectile_North_East = 11, 16 | Projectile_East = 12, 17 | Projectile_South_East = 13, 18 | Projectile_South = 14, 19 | Projectile_South_West = 15, 20 | Projectile_West = 16, 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /NetScape.Modules.Messages/Models/ProtoMessageCodec.cs: -------------------------------------------------------------------------------- 1 | using Google.Protobuf; 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | namespace NetScape.Modules.Messages.Models 6 | { 7 | public class ProtoMessageCodec 8 | { 9 | public MessageCodec MessageCodec { get; } 10 | public List FieldCodec { get; } 11 | public Func CreationMethod { get; } 12 | public ProtoMessageCodec(Func creationMethod, MessageCodec messageCodec, List fieldCodec) 13 | { 14 | CreationMethod = creationMethod; 15 | MessageCodec = messageCodec; 16 | FieldCodec = fieldCodec; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /.github/workflows/docs.yml: -------------------------------------------------------------------------------- 1 | name: docs 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v2 12 | - name: docfx-action 13 | # You may pin to the exact commit or the version. 14 | # uses: nikeee/docfx-action@b9c2cf92e3b4aa06878a1410833a8828b4bdcd26 15 | uses: nikeee/docfx-action@v1.0.0 16 | with: 17 | args: docs/docfx.json 18 | - uses: maxheld83/ghpages@master 19 | name: Publish Documentation on GitHub Pages 20 | env: 21 | BUILD_DIR: docs/_site # docfx's default output directory is _site 22 | GH_PAT: ${{ secrets.GH_PAT }} # See https://github.com/maxheld83/ghpages 23 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Model/Region/Collision/DirectionFlag.cs: -------------------------------------------------------------------------------- 1 | namespace NetScape.Abstractions.Model.Region.Collision 2 | { 3 | /// 4 | /// A directional flag in a . Consists of a and a flag indicating whether 5 | /// that tile is impenetrable as well as untraversable. 6 | /// 7 | public record DirectionFlag 8 | { 9 | public bool Impenetrable { get; } 10 | public Direction Direction { get; } 11 | 12 | public DirectionFlag(bool impenetrable, Direction direction) 13 | { 14 | Impenetrable = impenetrable; 15 | Direction = direction; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Interfaces/Region/IRegionUpdateOperation.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Interfaces.Messages; 2 | 3 | namespace NetScape.Abstractions.Interfaces.Region 4 | { 5 | public interface IRegionUpdateOperation 6 | { 7 | /// 8 | /// Gets a that would counteract the effect of this UpdateOperation. 9 | /// 10 | /// The RegionUpdateMessage 11 | RegionUpdateMessage Inverse(); 12 | 13 | /// 14 | /// Returns this UpdateOperation as a RegionUpdateMessage. 15 | /// 16 | /// RegionUpdateMessage 17 | RegionUpdateMessage ToMessage(); 18 | } 19 | } -------------------------------------------------------------------------------- /NetScape.Modules.FourSevenFour.World.Updating/Segments/AddPlayerSegment.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Model; 2 | using NetScape.Abstractions.Model.World.Updating; 3 | 4 | namespace NetScape.Modules.FourSevenFour.World.Updating.Segments 5 | { 6 | public class AddPlayerSegment : SynchronizationSegment 7 | { 8 | public override SegmentType Type => SegmentType.Add_Mob; 9 | public int Index { get; } 10 | public Position Position { get; } 11 | public Direction Direction { get; } 12 | public AddPlayerSegment(SynchronizationBlockSet blockSet, int index, Position position, Direction direction) : base(blockSet) 13 | { 14 | Index = index; 15 | Position = position; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Interfaces/Login/ILoginProcessor.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Model.Login; 2 | 3 | namespace NetScape.Abstractions.Interfaces.Login 4 | { 5 | /// 6 | /// The login processor is in-charge of processing logins in a async manner 7 | /// 8 | /// The type of the request. 9 | /// The type of the response. 10 | public interface ILoginProcessor where TRequest : LoginRequest 11 | { 12 | /// 13 | /// Enqueues the specified request. 14 | /// 15 | /// The request. 16 | void Enqueue(TRequest request); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Model/World/Updating/SynchronizationBlock.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Model.Game; 2 | using NetScape.Abstractions.Model.World.Updating.Blocks; 3 | using NetScape.Abstractions.Util; 4 | 5 | namespace NetScape.Abstractions.Model.World.Updating 6 | { 7 | public abstract class SynchronizationBlock 8 | { 9 | public static AnimationBlock CreateAnimationBlock(Animation animation) 10 | { 11 | return new AnimationBlock(animation); 12 | } 13 | 14 | public static AppearanceBlock CreateAppearanceBlock(Player player) 15 | { 16 | int combat = 3; 17 | return new AppearanceBlock(TextUtil.NameToLong(player.Username), player.Appearance, combat, 0, 0, false); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /NetScape.Modules.ThreeOneSeven.Game/Messages/Handlers/CommandMessageHandler.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Model.Messages; 2 | using NetScape.Modules.Messages; 3 | using Serilog; 4 | using static NetScape.Modules.Messages.Models.ThreeOneSevenDecoderMessages.Types; 5 | 6 | namespace NetScape.Modules.ThreeOneSeven.Game.Messages.Handlers 7 | { 8 | [MessageHandler] 9 | public class CommandMessageHandler 10 | { 11 | 12 | [Message(typeof(CommandMessage))] 13 | public void OnCommand(DecoderMessage decoderMessage) 14 | { 15 | var commandMessage = decoderMessage.Message; 16 | Log.Logger.Information("Player {0} executed command {1}", decoderMessage.Player.Username, commandMessage.Command); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /NetScape.Modules.FourSevenFour.LoginProtocol/Handlers/LoginProvider.cs: -------------------------------------------------------------------------------- 1 | using Autofac; 2 | using DotNetty.Transport.Channels; 3 | using NetScape.Abstractions.Interfaces; 4 | using NetScape.Abstractions.Interfaces.Login; 5 | using System; 6 | using NetScape.Abstractions.Server; 7 | 8 | namespace NetScape.Modules.FourSevenFour.LoginProtocol.Handlers 9 | { 10 | public class LoginProvider : ILoginProvider 11 | { 12 | private readonly IContainer _container; 13 | 14 | public LoginProvider(ContainerProvider containerProvider) 15 | { 16 | _container = containerProvider.Container; 17 | } 18 | 19 | public Func Provide => () => new IChannelHandler[] { 20 | _container.Resolve() 21 | }; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /NetScape.Modules.Messages.Builder/FrameTypeExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace NetScape.Modules.Messages.Builder 4 | { 5 | public static class FrameTypeExtensions 6 | { 7 | public static int GetBytes(this FrameType frameType, DotNetty.Buffers.IByteBuffer input) 8 | { 9 | switch (frameType) 10 | { 11 | case FrameType.ReadAll: 12 | return input.ReadableBytes; 13 | case FrameType.VariableByte: 14 | return input.ReadByte(); 15 | case FrameType.VariableShort: 16 | return input.ReadUnsignedShort(); 17 | default: 18 | throw new ArgumentException("Invalid frameType input argument"); 19 | } 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /NetScape.Modules.ThreeOneSeven.LoginProtocol/Handlers/LoginProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NetScape.Abstractions.Interfaces.Login; 3 | using DotNetty.Transport.Channels; 4 | using Serilog; 5 | using Autofac; 6 | using NetScape.Abstractions.Interfaces; 7 | using NetScape.Abstractions.Server; 8 | 9 | namespace NetScape.Modules.ThreeOneSeven.LoginProtocol.Handlers 10 | { 11 | public class LoginProvider : ILoginProvider 12 | { 13 | private readonly IContainer _container; 14 | 15 | public LoginProvider(ContainerProvider containerProvider) 16 | { 17 | _container = containerProvider.Container; 18 | } 19 | 20 | public Func Provide => () => new IChannelHandler[] { 21 | _container.Resolve() 22 | }; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Interfaces/Cache/IReferenceTableCache.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Concurrent; 3 | using System.Collections.Generic; 4 | using NetScape.Abstractions.Cache; 5 | 6 | namespace NetScape.Abstractions.Interfaces.Cache 7 | { 8 | public interface IReferenceTableCache : IDisposable 9 | { 10 | ConcurrentDictionary CachedReferenceTables { get; set; } 11 | void FlushCachedReferenceTables(); 12 | IEnumerable GetFileIds(CacheIndex index); 13 | CacheFileInfo GetFileInfo(CacheIndex index, int fileId); 14 | ReferenceTableFile GetReferenceTable(CacheIndex index, bool createIfNotFound = false); 15 | T GetFile(CacheIndex index, int fileId) where T : CacheFileBase; 16 | IEnumerable GetIndexes(); 17 | } 18 | } -------------------------------------------------------------------------------- /NetScape.Modules.FourSevenFour.Game/Messages/Handlers/PingMessageHandler.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Model.Messages; 2 | using NetScape.Modules.FourSevenFour.Game.Messages.Encoders; 3 | using NetScape.Modules.Messages; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using static NetScape.Modules.Messages.Models.FourSevenFourDecoderMessages.Types; 10 | 11 | namespace NetScape.Modules.FourSevenFour.Game.Messages.Handlers 12 | { 13 | [MessageHandler] 14 | public class PingMessageHandler 15 | { 16 | [Message(typeof(PingMessage))] 17 | public void OnPingMessage(DecoderMessage message) 18 | { 19 | _ = message.Player.SendAsync(new SendPingMessage(message.Player)); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /NetScape.Modules.DAL/Nuget.Projects.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | true 4 | true 5 | true 6 | https://github.com/jayarrowz/NetScape 7 | true 8 | LICENSE.txt 9 | 10 | NetScape 11 | NetScape DAL 12 | false 13 | false 14 | true 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /NetScape.Core/Nuget.Projects.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | true 4 | true 5 | true 6 | https://github.com/jayarrowz/NetScape 7 | true 8 | LICENSE.txt 9 | 10 | NetScape 11 | NetScape Core Libraries 12 | false 13 | false 14 | true 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /NetScape.Modules.Cache/Nuget.Projects.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | true 4 | true 5 | true 6 | https://github.com/jayarrowz/NetScape 7 | true 8 | LICENSE.txt 9 | 10 | NetScape 11 | NetScape Cache 12 | false 13 | false 14 | true 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Interfaces/Region/IGroupableEntity.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Model.Region; 2 | 3 | namespace NetScape.Abstractions.Interfaces.Region 4 | { 5 | /// 6 | /// An entity that can be sent as part of a grouped region update message. 7 | /// Only extensions may implement this interface. 8 | /// 9 | public interface IGroupableEntity 10 | { 11 | /// 12 | /// Gets this Entity, as an of a . 13 | /// 14 | /// The region. 15 | /// The type. 16 | /// The UpdateOperation. 17 | IRegionUpdateOperation ToUpdateOperation(IRegion region, EntityUpdateType type); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Nuget.Projects.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | true 4 | true 5 | true 6 | https://github.com/jayarrowz/NetScape 7 | true 8 | LICENSE.txt 9 | 10 | NetScape 11 | NetScape Abstractions 12 | false 13 | false 14 | true 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /NetScape.GameServer/Nuget.Projects.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | true 4 | true 5 | true 6 | https://github.com/jayarrowz/NetScape 7 | true 8 | LICENSE.txt 9 | 10 | NetScape 11 | NetScape Server Module 12 | false 13 | false 14 | true 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /NetScape.Modules.ThreeOneSeven.LoginProtocol/Handlers/LoginEncoder.cs: -------------------------------------------------------------------------------- 1 | using DotNetty.Buffers; 2 | using DotNetty.Codecs; 3 | using DotNetty.Transport.Channels; 4 | using NetScape.Abstractions.Model.Login; 5 | 6 | namespace NetScape.Modules.ThreeOneSeven.LoginProtocol.Handlers 7 | { 8 | public class LoginEncoder : MessageToByteEncoder> 9 | { 10 | protected override void Encode(IChannelHandlerContext context, LoginResponse message, IByteBuffer output) 11 | { 12 | output.WriteByte((int)message.Status); 13 | 14 | if (message.Status == ThreeOneSevenLoginStatus.StatusOk) 15 | { 16 | output.WriteByte(message.Rights); 17 | output.WriteByte(message.Flagged ? 1 : 0); 18 | } 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /NetScape.Modules.World/Nuget.Projects.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | true 4 | true 5 | true 6 | https://github.com/jayarrowz/NetScape 7 | true 8 | LICENSE.txt 9 | 10 | NetScape 11 | NetScape World Module 12 | false 13 | false 14 | true 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /NetScape.Modules.Region/Nuget.Projects.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | true 4 | true 5 | true 6 | https://github.com/jayarrowz/NetScape 7 | true 8 | LICENSE.txt 9 | 10 | NetScape 11 | NetScape Region Module 12 | false 13 | false 14 | true 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /NetScape.Modules.Messages/Nuget.Projects.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | true 4 | true 5 | true 6 | https://github.com/jayarrowz/NetScape 7 | true 8 | LICENSE.txt 9 | 10 | NetScape 11 | NetScape Messages Module 12 | false 13 | false 14 | true 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /NetScape.Modules.ThreeOneSeven.LoginProtocol/ThreeOneSevenLoginModule.cs: -------------------------------------------------------------------------------- 1 | using Autofac; 2 | using NetScape.Abstractions.Interfaces.Login; 3 | using NetScape.Modules.ThreeOneSeven.LoginProtocol.Handlers; 4 | 5 | namespace NetScape.Modules.ThreeOneSeven.LoginProtocol 6 | { 7 | public class ThreeOneSevenLoginModule : Module 8 | { 9 | protected override void Load(ContainerBuilder builder) 10 | { 11 | builder.RegisterType().As().SingleInstance(); 12 | builder.RegisterType(); 13 | builder.RegisterType(); 14 | builder.RegisterType(); 15 | builder.RegisterType().As>() 16 | .As().SingleInstance(); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /NetScape.Modules.Logging.SeriLog/Nuget.Projects.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | true 4 | true 5 | true 6 | https://github.com/jayarrowz/NetScape 7 | true 8 | LICENSE.txt 9 | 10 | NetScape 11 | NetScape SeriLog Module 12 | false 13 | false 14 | true 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /NetScape.Modules.FourSevenFour.Game/Nuget.Projects.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | true 4 | true 5 | true 6 | https://github.com/jayarrowz/NetScape 7 | true 8 | LICENSE.txt 9 | 10 | NetScape 11 | NetScape 474 Gaming Module 12 | false 13 | false 14 | true 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /NetScape.Modules.ThreeOneSeven.Game/Nuget.Projects.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | true 4 | true 5 | true 6 | https://github.com/jayarrowz/NetScape 7 | true 8 | LICENSE.txt 9 | 10 | NetScape 11 | NetScape 317 Game Module 12 | false 13 | false 14 | true 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /NetScape.Modules.Messages.Builder/Nuget.Projects.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | true 4 | true 5 | true 6 | https://github.com/jayarrowz/NetScape 7 | true 8 | LICENSE.txt 9 | 10 | NetScape 11 | NetScape Message Builder Module 12 | false 13 | false 14 | true 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /NetScape.Modules.Region.Collision/Nuget.Projects.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | true 4 | true 5 | true 6 | https://github.com/jayarrowz/NetScape 7 | true 8 | LICENSE.txt 9 | 10 | NetScape 11 | NetScape Region Collision Module 12 | false 13 | false 14 | true 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /NetScape.Modules.FourSevenFour.World.Updating/Nuget.Projects.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | true 4 | true 5 | true 6 | https://github.com/jayarrowz/NetScape 7 | true 8 | LICENSE.txt 9 | 10 | NetScape 11 | NetScape 474 Updating Module 12 | false 13 | false 14 | true 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /NetScape.Modules.ThreeOneSeven.World.Updating/Nuget.Projects.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | true 4 | true 5 | true 6 | https://github.com/jayarrowz/NetScape 7 | true 8 | LICENSE.txt 9 | 10 | NetScape 11 | NetScape 317 Updating Module 12 | false 13 | false 14 | true 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /NetScape.Modules.FourSevenFour.LoginProtocol/Nuget.Projects.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | true 4 | true 5 | true 6 | https://github.com/jayarrowz/NetScape 7 | true 8 | LICENSE.txt 9 | 10 | NetScape 11 | NetScape 474 Login Protocol Module 12 | false 13 | false 14 | true 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /NetScape.Modules.ThreeOneSeven.LoginProtocol/Nuget.Projects.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | true 4 | true 5 | true 6 | https://github.com/jayarrowz/NetScape 7 | true 8 | LICENSE.txt 9 | 10 | NetScape 11 | NetScape 317 Login Protocol Module 12 | false 13 | false 14 | true 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /NetScape.Modules.ThreeOneSeven.Game/Interface/RunButtonsHandler.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Model.Messages; 2 | using NetScape.Modules.Messages; 3 | using System; 4 | using System.Linq; 5 | using static NetScape.Modules.Messages.Models.ThreeOneSevenDecoderMessages.Types; 6 | 7 | namespace NetScape.Modules.ThreeOneSeven.Game.Interface 8 | { 9 | 10 | [MessageHandler] 11 | public class RunButtonsHandler 12 | { 13 | private static readonly int[] _runButtons = new int[] { 152, 153 }; 14 | 15 | [Message(typeof(ButtonMessage), nameof(Filter))] 16 | public void OnButtonClick(DecoderMessage decoderMessage) 17 | { 18 | decoderMessage.Player.WalkingQueue.Running = decoderMessage.Message.InterfaceId == 153; 19 | } 20 | 21 | public Predicate> Filter { get; } = e => _runButtons.Contains(e.Message.InterfaceId); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Interfaces/Messages/IMessageDecoder.cs: -------------------------------------------------------------------------------- 1 | using Google.Protobuf; 2 | using NetScape.Abstractions.Model.Game; 3 | using NetScape.Abstractions.Model.Messages; 4 | using NetScape.Modules.Messages.Builder; 5 | using System; 6 | 7 | namespace NetScape.Abstractions.Interfaces.Messages 8 | { 9 | public interface IMessageDecoder 10 | { 11 | int[] Ids { get; } 12 | void DecodeAndPublish(Player player, MessageFrame frame); 13 | void Publish(Player player, object message); 14 | FrameType FrameType { get; } 15 | string TypeName { get; } 16 | IDisposable SubscribeDelegate(Delegate method, Delegate filter); 17 | IDisposable SubscribeDelegateAsync(Delegate method, Delegate filter); 18 | } 19 | 20 | public interface IMessageDecoder : IMessageDecoder, IObservable> where TMessage : IMessage 21 | { 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /NetScape.Modules.Messages/MessageProvider.cs: -------------------------------------------------------------------------------- 1 | using Autofac; 2 | using DotNetty.Transport.Channels; 3 | using NetScape.Abstractions.Interfaces; 4 | using NetScape.Abstractions.Interfaces.Messages; 5 | using System; 6 | using NetScape.Abstractions.Server; 7 | 8 | namespace NetScape.Modules.Messages 9 | { 10 | public class MessageProvider : IMessageProvider 11 | { 12 | private readonly IContainer _container; 13 | 14 | public MessageProvider(ContainerProvider containerProvider) 15 | { 16 | _container = containerProvider.Container; 17 | } 18 | 19 | public Func Provide => () => new IChannelHandler[] { 20 | _container.Resolve(), 21 | _container.Resolve(), 22 | _container.Resolve(), 23 | _container.Resolve(), 24 | }; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /NetScape.Modules.Region/NetScape.Modules.Region.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage 5 | netcoreapp5.0 6 | false 7 | NetScape Region Modules 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /NetScape.Modules.FourSevenFour.LoginProtocol/Handlers/LoginEncoder.cs: -------------------------------------------------------------------------------- 1 | using DotNetty.Buffers; 2 | using DotNetty.Codecs; 3 | using DotNetty.Transport.Channels; 4 | using NetScape.Abstractions.Model.Login; 5 | 6 | namespace NetScape.Modules.FourSevenFour.LoginProtocol.Handlers 7 | { 8 | public class LoginEncoder : MessageToByteEncoder> 9 | { 10 | protected override void Encode(IChannelHandlerContext context, LoginResponse message, IByteBuffer output) 11 | { 12 | output.WriteByte((int)message.Status); 13 | 14 | if (message.Status == FourSevenFourLoginStatus.StatusOk) 15 | { 16 | output.WriteByte(message.Rights); 17 | output.WriteByte(message.Flagged ? 1 : 0); 18 | output.WriteShort(message.Player.Index); 19 | output.WriteByte(1); 20 | } 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Model/Login/LoginRequest.cs: -------------------------------------------------------------------------------- 1 | using DotNetty.Transport.Channels; 2 | using System; 3 | using System.Threading.Tasks; 4 | using NetScape.Abstractions.Util; 5 | 6 | namespace NetScape.Abstractions.Model.Login 7 | { 8 | public record LoginRequest 9 | { 10 | public int[] ArchiveCrcs { get; set; } 11 | 12 | public int ClientVersion { get; set; } 13 | 14 | public PlayerCredentials Credentials { get; set; } 15 | 16 | public bool LowMemory { get; set; } 17 | 18 | public IsaacRandomPair RandomPair { get; set; } 19 | 20 | public bool Reconnecting { get; set; } 21 | 22 | public int ReleaseNumber { get; set; } 23 | public TRes Result { get; set; } 24 | 25 | /// 26 | /// Called on response of request 27 | /// 28 | public Func OnResult { get; set; } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Cache/CacheFileEntryInfo.cs: -------------------------------------------------------------------------------- 1 | namespace NetScape.Abstractions.Cache 2 | { 3 | /// 4 | /// Represents metadata of an entry within a . 5 | /// 6 | public class CacheFileEntryInfo 7 | { 8 | /// 9 | /// The entry's id. 10 | /// 11 | public int? EntryId { get; set; } 12 | 13 | /// 14 | /// This entry's identifier. 15 | /// 16 | public int? Identifier { get; set; } 17 | 18 | /// 19 | /// Returns a copy of this object with the same values. 20 | /// 21 | /// 22 | public CacheFileEntryInfo Clone() 23 | { 24 | return new CacheFileEntryInfo 25 | { 26 | EntryId = this.EntryId, 27 | Identifier = this.Identifier 28 | }; 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /NetScape.Core/FileSystem.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.FileSystem; 2 | using System; 3 | using System.IO; 4 | using Microsoft.Extensions.Configuration; 5 | 6 | namespace NetScape.Core 7 | { 8 | public class FileSystem : IFileSystem 9 | { 10 | private readonly FileSystemConfig _fileConfig; 11 | 12 | public FileSystem(IConfigurationRoot configurationRoot) 13 | { 14 | _fileConfig = configurationRoot.GetSection("FileSystem").Get(); 15 | BasePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), 16 | _fileConfig.BaseFolder); 17 | } 18 | 19 | public string BasePath { get; } 20 | 21 | public string CachePath => Path.Combine(BasePath, _fileConfig.CacheFolder); 22 | } 23 | 24 | public class FileSystemConfig 25 | { 26 | public string BaseFolder { get; set; } 27 | public string CacheFolder { get; set; } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Model/Login/LoginDecoderState.cs: -------------------------------------------------------------------------------- 1 | namespace NetScape.Abstractions.Model.Login 2 | { 3 | public enum LoginDecoderState 4 | { 5 | /// 6 | /// The login handshake state will wait for the username hash to be received. Once it is, a server session key will 7 | /// be sent to the client and the state will be set to the login header state. 8 | /// 9 | LoginHandshake, 10 | 11 | /// 12 | /// The login header state will wait for the login type and payload length to be received. These are saved, and then 13 | /// the state will be set to the login payload state. 14 | /// 15 | LoginHeader, 16 | 17 | /// 18 | /// The login payloadThe login payload state will wait for all login information (such as client release number, username and 19 | /// password). 20 | /// 21 | LoginPayload 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /NetScape.Modules.FourSevenFour.LoginProtocol/FourSevenFourLoginModule.cs: -------------------------------------------------------------------------------- 1 | using Autofac; 2 | using NetScape.Abstractions.Interfaces.Login; 3 | using NetScape.Modules.FourSevenFour.LoginProtocol.Handlers; 4 | 5 | namespace NetScape.Modules.FourSevenFour.LoginProtocol 6 | { 7 | public class FourSevenFourLoginModule : Module 8 | { 9 | protected override void Load(ContainerBuilder builder) 10 | { 11 | builder.RegisterType().As().SingleInstance(); 12 | builder.RegisterType(); 13 | builder.RegisterType(); 14 | builder.RegisterType().AsSelf(); 15 | builder.RegisterType().AsSelf(); 16 | builder.RegisterType(); 17 | builder.RegisterType().As>() 18 | .As().SingleInstance(); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Interfaces/Region/Collision/ICollisionUpdate.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Collections.Extensions; 2 | using NetScape.Abstractions.Model; 3 | using NetScape.Abstractions.Model.Region.Collision; 4 | 5 | namespace NetScape.Abstractions.Interfaces.Region.Collision 6 | { 7 | /// 8 | /// A global update to the collision matrices. 9 | /// 10 | public interface ICollisionUpdate 11 | { 12 | /// 13 | /// Gets or sets the flags. 14 | /// 15 | /// 16 | /// A mapping of s to their s. 17 | /// 18 | MultiValueDictionary Flags { get; set; } 19 | 20 | /// 21 | /// Gets or sets the type of update. 22 | /// 23 | /// 24 | /// The type of this update. 25 | /// 26 | CollisionUpdateType Type { get; set; } 27 | } 28 | } -------------------------------------------------------------------------------- /NetScape/DesignTimeDbContextFactory.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Microsoft.EntityFrameworkCore.Design; 3 | using Microsoft.Extensions.Configuration; 4 | using NetScape.Abstractions.Model.Game; 5 | using NetScape.Core; 6 | using NetScape.Modules.DAL; 7 | 8 | namespace NetScape 9 | { 10 | public class DesignTimeDbContextFactory : IDesignTimeDbContextFactory> 11 | { 12 | public DatabaseContext CreateDbContext(string[] args) 13 | { 14 | var configRoot = ServerHandler.CreateConfigurationRoot("appsettings.json"); 15 | var optionsBuilder = new DbContextOptionsBuilder>(); 16 | optionsBuilder.UseNpgsql(configRoot.GetConnectionString("NetScape"), 17 | x => x.MigrationsAssembly(typeof(DatabaseContext) 18 | .Assembly.GetName().Name)); 19 | return new DatabaseContext(optionsBuilder.Options); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /NetScape.Modules.Messages.Builder/NetScape.Modules.Messages.Builder.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage 5 | false 6 | netstandard2.0 7 | NetScape Message Builder Module 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /NetScape.Modules.ThreeOneSeven.Game/NetScape.Modules.ThreeOneSeven.Game.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage 5 | netcoreapp5.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /NetScape.Modules.FourSevenFour.LoginProtocol/FourSevenFourLoginStatus.cs: -------------------------------------------------------------------------------- 1 | namespace NetScape.Modules.FourSevenFour.LoginProtocol 2 | { 3 | public enum FourSevenFourLoginStatus 4 | { 5 | StatusExchangeData = 0, 6 | StatusDelay = 1, 7 | StatusOk = 2, 8 | StatusInvalidCredentials = 3, 9 | StatusAccountDisabled = 4, 10 | StatusAccountOnline = 5, 11 | StatusGameUpdated = 6, 12 | StatusServerFull = 7, 13 | StatusLoginServerOffline = 8, 14 | StatusTooManyConnections = 9, 15 | StatusBadSessionId = 10, 16 | StatusLoginServerRejectedSession = 11, 17 | StatusMembersAccountRequired = 12, 18 | StatusCouldNotComplete = 13, 19 | StatusUpdating = 14, 20 | StatusReconnectionOk = 15, 21 | StatusTooManyLogins = 16, 22 | StatusInMembersArea = 17, 23 | StatusInvalidLoginServer = 20, 24 | StatusProfileTransfer = 21, 25 | TypeStandard = 16, 26 | TypeReconnection = 18 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /NetScape.Modules.ThreeOneSeven.LoginProtocol/ThreeOneSevenLoginStatus.cs: -------------------------------------------------------------------------------- 1 | namespace NetScape.Modules.ThreeOneSeven.LoginProtocol 2 | { 3 | public enum ThreeOneSevenLoginStatus 4 | { 5 | StatusExchangeData = 0, 6 | StatusDelay = 1, 7 | StatusOk = 2, 8 | StatusInvalidCredentials = 3, 9 | StatusAccountDisabled = 4, 10 | StatusAccountOnline = 5, 11 | StatusGameUpdated = 6, 12 | StatusServerFull = 7, 13 | StatusLoginServerOffline = 8, 14 | StatusTooManyConnections = 9, 15 | StatusBadSessionId = 10, 16 | StatusLoginServerRejectedSession = 11, 17 | StatusMembersAccountRequired = 12, 18 | StatusCouldNotComplete = 13, 19 | StatusUpdating = 14, 20 | StatusReconnectionOk = 15, 21 | StatusTooManyLogins = 16, 22 | StatusInMembersArea = 17, 23 | StatusInvalidLoginServer = 20, 24 | StatusProfileTransfer = 21, 25 | TypeStandard = 16, 26 | TypeReconnection = 18 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /NetScape.Modules.FourSevenFour.Game/Messages/Encoders/SendPingMessage.cs: -------------------------------------------------------------------------------- 1 | using DotNetty.Buffers; 2 | using NetScape.Abstractions.Interfaces.Messages; 3 | using NetScape.Abstractions.Model.Game; 4 | using NetScape.Modules.Messages; 5 | using NetScape.Modules.Messages.Builder; 6 | 7 | namespace NetScape.Modules.FourSevenFour.Game.Messages.Encoders 8 | { 9 | public class SendPingMessage : IEncoderMessage 10 | { 11 | public Abstractions.Model.Game.Player Player { get; } 12 | 13 | public SendPingMessage(Abstractions.Model.Game.Player player) 14 | { 15 | Player = player; 16 | } 17 | 18 | public MessageFrame ToMessage(IByteBufferAllocator alloc) 19 | { 20 | var messageFrameBuilder = new MessageFrameBuilder(alloc, 238, FrameType.VariableShort); 21 | messageFrameBuilder.Put(MessageType.Int, Player.PingCount++ > 0xF42400 ? Player.PingCount = 1 : Player.PingCount); 22 | return messageFrameBuilder.ToMessageFrame(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Cache/CacheFileOptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace NetScape.Abstractions.Cache 4 | { 5 | [Flags] 6 | public enum CacheFileOptions 7 | { 8 | /// 9 | /// A flag which indicates this contains Djb2 hashed identifiers. 10 | /// 11 | Identifiers = 1, 12 | 13 | /// 14 | /// A flag which indicates this } contains whirlpool digests for its entries. 15 | /// 16 | WhirlpoolDigests = 2, 17 | 18 | /// 19 | /// A flag which indicates this contains sizes for its entries. 20 | /// 21 | Sizes = 4, 22 | 23 | /// 24 | /// A flag which indicates this contains some kind of hash which is currently unused by 25 | /// the RuneScape client. 26 | /// 27 | MysteryHashes = 8 28 | } 29 | } -------------------------------------------------------------------------------- /NetScape.Modules.Region.Collision/NetScape.Modules.Region.Collision.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage 5 | netcoreapp5.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Model/Game/EntityType.cs: -------------------------------------------------------------------------------- 1 | namespace NetScape.Abstractions.Model.Game 2 | { 3 | /// 4 | /// Represents a type of 5 | /// 6 | public enum EntityType 7 | { 8 | /// 9 | /// A GameObject that is loaded dynamically, usually for specific Players. 10 | /// 11 | Dynamic_Object, 12 | 13 | /// 14 | /// An Item that is positioned on the ground. 15 | /// 16 | Ground_Item, 17 | 18 | /// 19 | /// A NPC 20 | /// 21 | Npc, 22 | 23 | /// 24 | /// A player 25 | /// 26 | Player, 27 | 28 | /// 29 | /// A projectile (e.g. an arrow). 30 | /// 31 | Projectile, 32 | 33 | /// 34 | /// A GameObject that is loaded statically (i.e. from the game resources) at start-up. 35 | /// 36 | Static_Object 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /NetScape.Modules.ThreeOneSeven.Game/ThreeOneSevenGameModule.cs: -------------------------------------------------------------------------------- 1 | using Autofac; 2 | using NetScape.Abstractions.Interfaces.Game.Interface; 3 | using NetScape.Abstractions.Interfaces.Game.Player; 4 | using NetScape.Abstractions.Interfaces.Messages; 5 | using NetScape.Modules.ThreeOneSeven.Game.Interface; 6 | using NetScape.Modules.ThreeOneSeven.Game.Players; 7 | 8 | namespace NetScape.Modules.ThreeOneSeven.Game 9 | { 10 | public class ThreeOneSevenGameModule : Autofac.Module 11 | { 12 | protected override void Load(ContainerBuilder builder) 13 | { 14 | builder.RegisterType().As(); 15 | builder.RegisterType().As(); 16 | 17 | #region Handlers 18 | builder.RegisterAssemblyTypes(typeof(ThreeOneSevenGameModule).Assembly) 19 | .AsClosedTypesOf(typeof(IMessageDecoder<>)) 20 | .As() 21 | .SingleInstance(); 22 | #endregion 23 | base.Load(builder); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /NetScape/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "BossGroupThreadCount": 1, 3 | "WorkerGroupThreadCount": 8, 4 | "BindAddr": "127.0.0.1", 5 | "LoginProcessorTimeout": 10000, 6 | "BindPort": 43594, 7 | "FileSystem": { 8 | "BaseFolder": "AspNetServerData/", 9 | "CacheFolder": "cache/" 10 | }, 11 | "Logging": { 12 | "LogLevel": { 13 | "Default": "Information", 14 | "Microsoft": "Information", 15 | "Microsoft.EntityFrameworkCore": "Warning", 16 | "Microsoft.Hosting.Lifetime": "Information" 17 | } 18 | }, 19 | "ConnectionStrings": { 20 | "NetScape": "Host=127.0.0.1;Database=rsps;Port=5432;Username=postgres;Password=dadabaa" 21 | }, 22 | "Serilog": { 23 | "Using": [ "Serilog.Sinks.Console" ], 24 | "MinimumLevel": "Debug", 25 | "WriteTo": [ 26 | { "Name": "Console" }, 27 | { 28 | "Name": "File", 29 | "Args": { "path": "NetScape-LOG.log" } 30 | } 31 | ], 32 | "Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ], 33 | "Properties": { 34 | "Application": "NetScape" 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /NetScape.Modules.Logging.SeriLog/SeriLogModule.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using Autofac; 4 | using Microsoft.Extensions.Configuration; 5 | using Serilog; 6 | using Serilog.Extensions.Logging; 7 | using Serilog.Events; 8 | using Module = Autofac.Module; 9 | 10 | namespace NetScape.Modules.Logging.SeriLog 11 | { 12 | public sealed class SeriLogModule : Module 13 | { 14 | private readonly IConfigurationRoot _configurationRoot; 15 | 16 | public SeriLogModule(IConfigurationRoot configurationRoot) 17 | { 18 | _configurationRoot = configurationRoot; 19 | } 20 | 21 | protected override void Load(ContainerBuilder builder) 22 | { 23 | var loggerConfig = new LoggerConfiguration() 24 | .ReadFrom.Configuration(_configurationRoot); 25 | 26 | var logger = loggerConfig.CreateLogger() 27 | .ForContext(MethodBase.GetCurrentMethod().DeclaringType); 28 | Log.Logger = logger; 29 | builder.RegisterInstance(logger).As(); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /NetScape.Modules.FourSevenFour.LoginProtocol/NetScape.Modules.FourSevenFour.LoginProtocol.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage 5 | netcoreapp5.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /NetScape.Modules.World/NetScape.Modules.World.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage 5 | netcoreapp5.0 6 | false 7 | NetScape World Module 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /NetScape.Modules.FourSevenFour.Game/FourSevenFourGameModule.cs: -------------------------------------------------------------------------------- 1 | using Autofac; 2 | using NetScape.Abstractions.Interfaces.Game.Interface; 3 | using NetScape.Abstractions.Interfaces.Game.Player; 4 | using NetScape.Abstractions.Interfaces.Messages; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | using NetScape.Modules.FourSevenFour.Game.Player; 11 | 12 | namespace NetScape.Modules.FourSevenFour.Game 13 | { 14 | public class FourSevenFourGameModule : Module 15 | { 16 | protected override void Load(ContainerBuilder builder) 17 | { 18 | builder.RegisterType().As(); 19 | builder.RegisterType().As(); 20 | 21 | #region Handlers 22 | builder.RegisterAssemblyTypes(typeof(FourSevenFourGameModule).Assembly) 23 | .AsClosedTypesOf(typeof(IMessageDecoder<>)) 24 | .As() 25 | .SingleInstance(); 26 | #endregion 27 | base.Load(builder); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Extensions/PathExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace NetScape.Abstractions.Extensions 4 | { 5 | public static class PathExtensions 6 | { 7 | public static char[] InvalidCharacters = { '/', ':', '"', '*', '?', '>', '<', '|', '\0' }; 8 | 9 | /// 10 | /// Parses the given directory and unifies its format, to be applied to unpredictable user input. 11 | /// Converts backslashes to forward slashes, and appends a directory separator. 12 | /// 13 | /// 14 | /// 15 | public static string FixDirectory(string path) 16 | { 17 | // Expand environment variables 18 | var result = Environment.ExpandEnvironmentVariables(path); 19 | 20 | // Replace backslashes with forward slashes 21 | result = result.Replace('\\', '/'); 22 | 23 | // Add trailing slash if not present 24 | if (!result.EndsWith("/")) 25 | { 26 | result += "/"; 27 | } 28 | 29 | return result; 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /NetScape.Abstractions/FileSystem/IPlayerRepository.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Model.Game; 2 | using NetScape.Abstractions.Model.Login; 3 | using System.Threading.Tasks; 4 | 5 | namespace NetScape.Abstractions.FileSystem 6 | { 7 | public interface IPlayerRepository 8 | { 9 | /// 10 | /// Retrive player for name 11 | /// 12 | /// The player name. 13 | /// Player 14 | Task GetAsync(string name); 15 | 16 | /// 17 | /// Retrive player for player credentials 18 | /// 19 | /// The player credentials. 20 | /// Player 21 | Task GetOrCreateAsync(PlayerCredentials playerCredentials); 22 | 23 | /// 24 | /// Adds player if the player does not exist, otherwise the player is updated 25 | /// 26 | /// The player. 27 | /// Number of rows updated 28 | Task AddOrUpdateAsync(Player player); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Model/Region/ObjectType.cs: -------------------------------------------------------------------------------- 1 | namespace NetScape.Abstractions.Model.Region 2 | { 3 | public class ObjectType 4 | { 5 | public static readonly ObjectType Lengthwise_Wall = new(0, ObjectGroup.Wall); 6 | public static readonly ObjectType Triangular_Corner = new(1, ObjectGroup.Wall); 7 | public static readonly ObjectType Wall_Corner = new(2, ObjectGroup.Wall); 8 | public static readonly ObjectType Rectangular_Corner = new(3, ObjectGroup.Wall); 9 | public static readonly ObjectType Diagonal_Wall = new(9, ObjectGroup.Interactable_Object); 10 | public static readonly ObjectType Interactable = new(10, ObjectGroup.Interactable_Object); 11 | public static readonly ObjectType Diagonal_Interactable = new(11, ObjectGroup.Interactable_Object); 12 | public static readonly ObjectType Floor_Decoration = new(22, ObjectGroup.Ground_Decoration); 13 | 14 | public ObjectType(int value, ObjectGroup group) 15 | { 16 | Value = value; 17 | Group = group; 18 | } 19 | 20 | public int Value { get; } 21 | public ObjectGroup Group { get; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /NetScape.Modules.FourSevenFour.World.Updating/NetScape.Modules.FourSevenFour.World.Updating.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage 5 | netcoreapp5.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Model/Game/WalkingQueue.cs: -------------------------------------------------------------------------------- 1 | using Nito.Collections; 2 | 3 | namespace NetScape.Abstractions.Model.Game 4 | { 5 | /// 6 | /// A queue of s which a will follow. 7 | /// 8 | public class WalkingQueue 9 | { 10 | /// 11 | /// The Deque of active points in this WalkingQueue. 12 | /// 13 | /// 14 | /// The points. 15 | /// 16 | public Deque Points { get; } = new(); 17 | 18 | /// 19 | /// The Deque of previous points in this WalkingQueue. 20 | /// 21 | /// 22 | /// The previous points. 23 | /// 24 | public Deque PreviousPoints { get; set; } = new(); 25 | 26 | /// 27 | /// Gets or sets a value indicating whether this is running. 28 | /// 29 | /// 30 | /// true if running; otherwise, false. 31 | /// 32 | public bool Running { get; set; } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /NetScape.Modules.ThreeOneSeven.Game/Interface/TabManager.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Interfaces.Game.Interface; 2 | using NetScape.Abstractions.Interfaces.Messages; 3 | using NetScape.Modules.Messages.Models; 4 | using System.Threading.Tasks; 5 | 6 | namespace NetScape.Modules.ThreeOneSeven.Game.Interface 7 | { 8 | public class TabManager : ITabManager 9 | { 10 | private readonly IProtoMessageSender _protoMessageSender; 11 | 12 | public TabManager(IProtoMessageSender protoMessageSender) 13 | { 14 | _protoMessageSender = protoMessageSender; 15 | } 16 | 17 | public int[] Default { get; } = new int[] { 2423, 3917, 638, 3213, 1644, 5608, 1151, -1, 5065, 5715, 2449, 904, 147, 962, }; 18 | 19 | public Task SetTabAsync(Abstractions.Model.Game.Player player, int tabId, int interfaceId) 20 | { 21 | var switchTabMessage = new ThreeOneSevenEncoderMessages.Types.SwitchTabInterfaceMessage 22 | { 23 | InterfaceId = interfaceId, 24 | TabId = tabId 25 | }; 26 | return _protoMessageSender.SendAsync(player, switchTabMessage); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /NetScape.Modules.Messages/ProtoMessageSender.cs: -------------------------------------------------------------------------------- 1 | using Google.Protobuf; 2 | using NetScape.Abstractions.Interfaces.Messages; 3 | using NetScape.Abstractions.Model.Game; 4 | using NetScape.Abstractions.Model.Messages; 5 | using System; 6 | using System.Threading.Tasks; 7 | 8 | namespace NetScape.Modules.Messages 9 | { 10 | public class ProtoMessageSender : IProtoMessageSender 11 | { 12 | private readonly ProtoMessageCodecHandler _protoMessageCodecHandler; 13 | public ProtoMessageSender(ProtoMessageCodecHandler protoMessageCodecHandler) 14 | { 15 | _protoMessageCodecHandler = protoMessageCodecHandler; 16 | } 17 | 18 | public Task SendAsync(Player player, IMessage message) 19 | { 20 | try 21 | { 22 | var opcode = _protoMessageCodecHandler.EncoderTypeMap[message.Descriptor.ClrType]; 23 | return player.ChannelHandlerContext.Channel.WriteAndFlushAsync(new ProtoMessage(opcode, player, message)); 24 | } catch(Exception e) 25 | { 26 | Serilog.Log.Logger.Error(e, nameof(SendAsync)); 27 | throw; 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /NetScape.Modules.Region/ObjectUpdateOperation.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Interfaces.Messages; 2 | using NetScape.Abstractions.Interfaces.Region; 3 | using NetScape.Abstractions.Model.Region; 4 | 5 | namespace NetScape.Modules.Region 6 | { 7 | public class ObjectUpdateOperation : RegionUpdateOperation 8 | { 9 | /// 10 | /// Initializes a new instance of the class. 11 | /// 12 | /// The region which the ObjectUpdateOperation occured. Must not be null. 13 | /// The type. 14 | /// The object. 15 | public ObjectUpdateOperation(IRegion region, EntityUpdateType type, GameObject obj) : base(region, type, obj) 16 | { 17 | } 18 | 19 | protected override RegionUpdateMessage Add(int offset) 20 | { 21 | return null; 22 | //return new SendObjectMessage(entity, offset); 23 | } 24 | 25 | protected override RegionUpdateMessage Remove(int offset) 26 | { 27 | return null; 28 | // return new RemoveObjectMessage(entity, offset); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Model/World/Updating/Blocks/AppearanceBlock.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Model.Game; 2 | 3 | namespace NetScape.Abstractions.Model.World.Updating.Blocks 4 | { 5 | public class AppearanceBlock : SynchronizationBlock 6 | { 7 | public Appearance Appearance { get; set; } 8 | public int Combat { get; set; } 9 | public bool IsSkulled { get; set; } 10 | public long Name { get; set; } 11 | public int NpcId { get; set; } 12 | public int HeadIcon { get; set; } 13 | public int Skill { get; set; } 14 | 15 | public AppearanceBlock(long name, Appearance appearance, int combat, int skill, int headIcon, bool isSkulled) : this(name, appearance, combat, skill, headIcon, isSkulled, -1) 16 | { 17 | } 18 | 19 | public AppearanceBlock(long name, Appearance appearance, int combat, int skill, int headIcon, bool isSkulled, int npcId) 20 | { 21 | Name = name; 22 | Appearance = appearance; 23 | Combat = combat; 24 | Skill = skill; 25 | //this.equipment = equipment.duplicate(); 26 | HeadIcon = headIcon; 27 | IsSkulled = isSkulled; 28 | NpcId = npcId; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /NetScape.Modules.DAL.Test/NetScape.Modules.DAL.Test.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp5.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | runtime; build; native; contentfiles; analyzers; buildtransitive 15 | all 16 | 17 | 18 | runtime; build; native; contentfiles; analyzers; buildtransitive 19 | all 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /NetScape.Modules.FourSevenFour.World.Updating/Segments/MovementSegment.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Dawn; 3 | using NetScape.Abstractions.Model; 4 | using NetScape.Abstractions.Model.World.Updating; 5 | 6 | namespace NetScape.Modules.FourSevenFour.World.Updating.Segments 7 | { 8 | public class MovementSegment : SynchronizationSegment 9 | { 10 | public Direction[] Directions { get; } 11 | public override SegmentType Type => GetSegmentType(); 12 | 13 | public MovementSegment(SynchronizationBlockSet blockSet, Direction[] directions) : base(blockSet) 14 | { 15 | Guard.Argument(directions.Length, nameof(Directions)).GreaterThan(-1).LessThan(3); 16 | Directions = directions; 17 | } 18 | 19 | private SegmentType GetSegmentType() 20 | { 21 | switch (Directions.Length) 22 | { 23 | case 0: 24 | return SegmentType.No_Movement; 25 | case 1: 26 | return SegmentType.Walk; 27 | case 2: 28 | return SegmentType.Run; 29 | default: 30 | throw new InvalidOperationException("Direction type not supported"); 31 | } 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /NetScape.Modules.ThreeOneSeven.World.Updating/Segments/MovementSegment.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Dawn; 3 | using NetScape.Abstractions.Model; 4 | using NetScape.Abstractions.Model.World.Updating; 5 | 6 | namespace NetScape.Modules.ThreeOneSeven.World.Updating.Segments 7 | { 8 | public class MovementSegment : SynchronizationSegment 9 | { 10 | public Direction[] Directions { get; } 11 | public override SegmentType Type => GetSegmentType(); 12 | 13 | public MovementSegment(SynchronizationBlockSet blockSet, Direction[] directions) : base(blockSet) 14 | { 15 | Guard.Argument(directions.Length, nameof(Directions)).GreaterThan(-1).LessThan(3); 16 | Directions = directions; 17 | } 18 | 19 | private SegmentType GetSegmentType() 20 | { 21 | switch (Directions.Length) 22 | { 23 | case 0: 24 | return SegmentType.No_Movement; 25 | case 1: 26 | return SegmentType.Walk; 27 | case 2: 28 | return SegmentType.Run; 29 | default: 30 | throw new InvalidOperationException("Direction type not supported"); 31 | } 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Cache/CacheFileBase.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Cache; 2 | 3 | namespace NetScape.Abstractions.Cache 4 | { 5 | /// 6 | /// Base type for all cache files. 7 | /// Child types must implement methods to convert to and from bytes. 8 | /// 9 | public abstract class CacheFileBase 10 | { 11 | public CacheFileInfo Info { get; set; } = new CacheFileInfo(); 12 | 13 | public void FromBinaryFile(BinaryFile file) 14 | { 15 | this.Info = file.Info; 16 | 17 | var thisBinaryFile = this as BinaryFile; 18 | 19 | if (thisBinaryFile != null) 20 | { 21 | thisBinaryFile.Data = file.Data; 22 | } 23 | else 24 | { 25 | this.Decode(file.Data); 26 | } 27 | } 28 | 29 | public abstract void Decode(byte[] data); 30 | 31 | public BinaryFile ToBinaryFile() 32 | { 33 | var file = this as BinaryFile; 34 | 35 | return file ?? new BinaryFile 36 | { 37 | Info = this.Info, 38 | Data = this.Encode() 39 | }; 40 | } 41 | 42 | public abstract byte[] Encode(); 43 | } 44 | } -------------------------------------------------------------------------------- /NetScape.GameServer/GameServerModule.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Interfaces.IO; 2 | using NetScape.Abstractions.Interfaces.IO.EventLoop; 3 | using NetScape.Abstractions.IO; 4 | using NetScape.Modules.Server.IO; 5 | using NetScape.Modules.Server.IO.EventLoop; 6 | using Autofac; 7 | using NetScape.Abstractions.Model.Game; 8 | using NetScape.Abstractions.Interfaces.Messages; 9 | 10 | namespace NetScape.Modules.Server 11 | { 12 | public sealed class GameServerModule : Module 13 | { 14 | private readonly IGameServerParameters _gameServerParams; 15 | 16 | public GameServerModule(string bindAddr, ushort port) 17 | { 18 | _gameServerParams = 19 | new GameServerParameters { BindAddress = bindAddr, Port = port }; 20 | } 21 | 22 | protected override void Load(ContainerBuilder builder) 23 | { 24 | builder.RegisterType().As(); 25 | builder.RegisterType(); 26 | builder.RegisterType() 27 | .As(); 28 | builder.RegisterInstance(_gameServerParams).As(); 29 | base.Load(builder); 30 | } 31 | 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /NetScape.GameServer/NetScape.Modules.Server.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage 5 | netcoreapp5.0 6 | false 7 | NetScape Netty Server Module 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Model/Game/Appearance.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | 5 | namespace NetScape.Abstractions.Model.Game 6 | { 7 | public record Appearance 8 | { 9 | public static Appearance DefaultAppearance => new Appearance(Gender.Male, new int[] { 0, 10, 18, 26, 33, 36, 42 }, new int[5]); 10 | 11 | [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 12 | public int Id { get; set; } 13 | 14 | public int[] Colors { get; set; } 15 | 16 | [DataType("varchar(20)")] 17 | public Gender Gender { get; set; } 18 | public int[] Style { get; set; } 19 | 20 | public Appearance() 21 | { 22 | 23 | } 24 | 25 | public Appearance(Gender gender, int[] style, int[] colors) 26 | { 27 | if (style == null || colors == null) 28 | { 29 | throw new ArgumentException("No arguments can be null."); 30 | } 31 | 32 | Gender = gender; 33 | Style = style; 34 | Colors = colors; 35 | } 36 | 37 | [NotMapped] 38 | public bool IsFemale => Gender == Gender.Female; 39 | 40 | [NotMapped] 41 | public bool IsMale => Gender == Gender.Male; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /NetScape.Modules.ThreeOneSeven.Game/Interface/EmoteTabButtonsHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using NetScape.Abstractions.Model.Messages; 3 | using NetScape.Abstractions.Model.World.Updating; 4 | using NetScape.Modules.Messages; 5 | using NetScape.Modules.Messages.Models; 6 | 7 | namespace NetScape.Modules.ThreeOneSeven.Game.Interface 8 | { 9 | [MessageHandler] 10 | public class EmoteTabButtonsHandler 11 | { 12 | private Dictionary ButtonAnimationMap { get; } = new Dictionary 13 | { 14 | { 168, 855 }, 15 | { 169, 856 }, 16 | { 162, 857 }, 17 | { 164, 858 }, 18 | }; 19 | 20 | [Message(typeof(ThreeOneSevenDecoderMessages.Types.ButtonMessage), nameof(CanExecute))] 21 | public void OnButtonClick(DecoderMessage message) 22 | { 23 | var buttonId = message.Message.InterfaceId; 24 | int animation = ButtonAnimationMap[buttonId]; 25 | message.Player.SendAnimation(new Animation(animation)); 26 | } 27 | 28 | public bool CanExecute(DecoderMessage message) 29 | { 30 | return ButtonAnimationMap.ContainsKey(message.Message.InterfaceId); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /docs/docfx.json: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": [ 3 | { 4 | "src": [ 5 | { 6 | "files": [ 7 | "**.csproj" 8 | ], 9 | "exclude": [ "**/bin/**", "**/obj/**" ], 10 | "src": "../" 11 | } 12 | ], 13 | "dest": "api", 14 | "disableGitFeatures": false, 15 | "disableDefaultFilter": false 16 | } 17 | ], 18 | "build": { 19 | "content": [ 20 | { 21 | "files": [ 22 | "api/**.yml", 23 | "api/index.md" 24 | ] 25 | }, 26 | { 27 | "files": [ 28 | "*.md" 29 | ] 30 | } 31 | ], 32 | "resource": [ 33 | { 34 | "files": [ 35 | "images/**" 36 | ] 37 | } 38 | ], 39 | "overwrite": [ 40 | { 41 | "files": [ 42 | "apidoc/**.md" 43 | ], 44 | "exclude": [ 45 | "obj/**", 46 | "_site/**" 47 | ] 48 | } 49 | ], 50 | "dest": "_site", 51 | "globalMetadataFiles": [], 52 | "fileMetadataFiles": [], 53 | "template": [ 54 | "default", 55 | "templates/darkfx" 56 | ], 57 | "postProcessors": [], 58 | "markdownEngineName": "markdig", 59 | "noLangKeyword": false, 60 | "keepFileLink": false, 61 | "cleanupCacheHistory": false, 62 | "disableGitFeatures": false 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Extensions/EntityTypeExtensions.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Model.Game; 2 | 3 | namespace NetScape.Abstractions.Extensions 4 | { 5 | /// 6 | /// Extensions for the EntityType enum 7 | /// 8 | public static class EntityTypeExtensions 9 | { 10 | /// 11 | /// Determines whether this instance is mob. 12 | /// 13 | /// Type of the entity. 14 | /// 15 | /// true if the specified entity type is mob; otherwise, false. 16 | /// 17 | public static bool IsMob(this EntityType entityType) 18 | { 19 | return entityType == EntityType.Player || entityType == EntityType.Npc; 20 | } 21 | 22 | /// 23 | /// Returns whether or not this EntityType should be short-lived (i.e. not added to its regions local objects). 24 | /// 25 | /// Type of the entity. 26 | /// 27 | /// true if the specified entity type is short-lived; otherwise, false. 28 | /// 29 | public static bool IsTransient(this EntityType entityType) 30 | { 31 | return entityType == EntityType.Projectile; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /NetScape.Modules.FourSevenFour.Game/NetScape.Modules.FourSevenFour.Game.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage 5 | netcoreapp5.0 6 | false 7 | NetScape 474 Game Module 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /NetScape.Modules.Messages/MessageFrameEncoder.cs: -------------------------------------------------------------------------------- 1 | using DotNetty.Buffers; 2 | using DotNetty.Codecs; 3 | using DotNetty.Transport.Channels; 4 | using NetScape.Abstractions.Interfaces.Messages; 5 | using NetScape.Abstractions.Model.Game; 6 | using NetScape.Abstractions.Util; 7 | using NetScape.Modules.Messages.Builder; 8 | 9 | namespace NetScape.Modules.Messages 10 | { 11 | public class MessageFrameEncoder : MessageToByteEncoder, ICipherAwareHandler, IPlayerAwareHandler 12 | { 13 | public IsaacRandomPair CipherPair { get; set; } 14 | public Player Player { get; set; } 15 | 16 | protected override void Encode(IChannelHandlerContext context, MessageFrame frame, IByteBuffer output) 17 | { 18 | var type = frame.Type; 19 | IByteBuffer payload = frame.Payload; 20 | int opcode = frame.Id; 21 | 22 | int? isaacValue = CipherPair?.EncodingRandom?.NextInt() ?? null; 23 | opcode = isaacValue.HasValue ? opcode + isaacValue.Value & 0xFF : opcode & 0XFF; 24 | 25 | output.WriteByte(opcode); 26 | if (type == FrameType.VariableByte) 27 | output.WriteByte(payload.ReadableBytes); 28 | else if (type == FrameType.VariableShort) 29 | output.WriteShort(payload.ReadableBytes); 30 | output.WriteBytes(payload); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /NetScape.Modules.FourSevenFour.Game/Player/TabManager.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using NetScape.Abstractions.Interfaces.Game.Interface; 3 | using NetScape.Abstractions.Interfaces.Messages; 4 | using static NetScape.Modules.Messages.Models.FourSevenFourEncoderMessages.Types; 5 | 6 | namespace NetScape.Modules.FourSevenFour.Game.Player 7 | { 8 | public class TabManager : ITabManager 9 | { 10 | private readonly IProtoMessageSender _protoMessageSender; 11 | 12 | public TabManager(IProtoMessageSender protoMessageSender) 13 | { 14 | _protoMessageSender = protoMessageSender; 15 | } 16 | 17 | public int[] TabIds { get; } = new int[] { 90, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112 }; 18 | public int[] Default { get; } = new int[] { 137, 92, 320, 274, 149, 387, 271, 192, 589, 550, 551, 182, 261, 464, 239 }; 19 | 20 | public Task SetTabAsync(Abstractions.Model.Game.Player player, int tabId, int interfaceId) 21 | { 22 | var switchTabMessage = new OpenInterfaceMessage 23 | { 24 | InterfaceId = interfaceId, 25 | Window = 548, //Main window 26 | Position = TabIds[tabId], 27 | Walkable = true 28 | }; 29 | return _protoMessageSender.SendAsync(player, switchTabMessage); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /NetScape.Modules.Logging.SeriLog/NetScape.Modules.Logging.SeriLog.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage 5 | netcoreapp5.0 6 | false 7 | NetScape SeriLog Module 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Model/Mob.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Model.Game; 2 | using NetScape.Abstractions.Model.World.Updating; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.ComponentModel.DataAnnotations.Schema; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace NetScape.Abstractions.Model 11 | { 12 | public abstract class Mob : Entity 13 | { 14 | [NotMapped] public Direction FirstDirection { get; set; } = Direction.None; 15 | [NotMapped] public Direction SecondDirection { get; set; } = Direction.None; 16 | [NotMapped] public Direction LastDirection { get; set; } = Direction.North; 17 | [NotMapped] public SynchronizationBlockSet BlockSet { get; set; } = new SynchronizationBlockSet(); 18 | [NotMapped] public bool IsActive => Index != -1; 19 | [NotMapped] public bool IsTeleporting { get; set; } 20 | [NotMapped] public WalkingQueue WalkingQueue { get; set; } = new WalkingQueue(); 21 | public Direction[] GetDirections() 22 | { 23 | if (FirstDirection != Direction.None) 24 | { 25 | return SecondDirection == Direction.None ? new Direction[] { FirstDirection } 26 | : new Direction[] { FirstDirection, SecondDirection }; 27 | } 28 | 29 | return Direction.EmptyDirectionArray; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /NetScape.Modules.ThreeOneSeven.World.Updating/NetScape.Modules.ThreeOneSeven.World.Updating.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage 5 | netcoreapp5.0 6 | false 7 | 317 NetScape Entity Updating Module 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /NetScape.GameServer/IO/EventLoop/GameServerEventLoopGroupFactory.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Interfaces.IO.EventLoop; 2 | using DotNetty.Transport.Channels; 3 | using System.Threading.Tasks; 4 | using Microsoft.Extensions.Configuration; 5 | 6 | namespace NetScape.Modules.Server.IO.EventLoop 7 | { 8 | public class GameServerEventLoopGroupFactory : BaseLoopGroupFactory, IEventLoopGroupFactory 9 | { 10 | private const string BossGroupThreadCountConfigKey = "BossGroupThreadCount"; 11 | private const string WorkerGroupThreadCountConfigKey = "WorkerGroupThreadCount"; 12 | private readonly IConfigurationRoot _configurationRoot; 13 | 14 | public GameServerEventLoopGroupFactory(IConfigurationRoot configurationRoot) 15 | { 16 | _configurationRoot = configurationRoot; 17 | } 18 | 19 | public IEventLoopGroup GetBossGroup() 20 | { 21 | return BossEventLoopGroup ?? (BossEventLoopGroup = NewEventLoopGroup(int.Parse(_configurationRoot[BossGroupThreadCountConfigKey]))); 22 | } 23 | 24 | public IEventLoopGroup GetWorkerGroup() 25 | { 26 | return WorkerEventLoopGroup ?? (WorkerEventLoopGroup = NewEventLoopGroup(int.Parse(_configurationRoot[WorkerGroupThreadCountConfigKey]))); 27 | } 28 | 29 | protected override void Dispose(bool disposing) 30 | { 31 | base.Dispose(true); 32 | } 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /docs/templates/darkfx/partials/affix.tmpl.partial: -------------------------------------------------------------------------------- 1 | {{!Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information.}} 2 | 3 | 40 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Model/Game/Entity.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations.Schema; 2 | using NetScape.Abstractions.Interfaces.Region; 3 | using NetScape.Abstractions.Interfaces.World; 4 | 5 | namespace NetScape.Abstractions.Model.Game 6 | { 7 | public abstract class Entity 8 | { 9 | private Position _position; 10 | 11 | [NotMapped] 12 | public IWorld World { get; set; } 13 | 14 | [NotMapped] public int Index { get; set; } = -1; 15 | 16 | public Position Position 17 | { 18 | get => _position; 19 | set 20 | { 21 | if (World != null && _position != value) 22 | { 23 | Position old = _position; 24 | var repository = World.RegionRepository; 25 | IRegion current = repository.FromPosition(old), next = repository.FromPosition(value); 26 | current.RemoveEntity(this); 27 | _position = value; 28 | next.AddEntity(this); 29 | } else if (World == null) 30 | { 31 | _position = value; 32 | } 33 | } 34 | } 35 | 36 | [NotMapped] 37 | public abstract EntityType EntityType { get; } 38 | 39 | [NotMapped] 40 | public abstract int Width { get; } 41 | 42 | [NotMapped] 43 | public abstract int Length { get; } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /docs/templates/darkfx/partials/head.tmpl.partial: -------------------------------------------------------------------------------- 1 | {{!Copyright (c) Oscar Vasquez. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information.}} 2 | 3 | 4 | 5 | 6 | {{#title}}{{title}}{{/title}}{{^title}}{{>partials/title}}{{/title}} {{#_appTitle}}| {{_appTitle}} {{/_appTitle}} 7 | 8 | 9 | 10 | {{#_description}}{{/_description}} 11 | 12 | 13 | 14 | 15 | 16 | 17 | {{#_noindex}}{{/_noindex}} 18 | {{#_enableSearch}}{{/_enableSearch}} 19 | {{#_enableNewTab}}{{/_enableNewTab}} 20 | -------------------------------------------------------------------------------- /NetScape.Modules.ThreeOneSeven.LoginProtocol/NetScape.Modules.ThreeOneSeven.LoginProtocol.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage 5 | netcoreapp5.0 6 | false 7 | NetScape 317 Login Protocol Module 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /NetScape.Modules.DAL/Migrations/20210123212503_RemoveAppearanceFields.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Migrations; 2 | 3 | namespace NetScape.Modules.DAL.Migrations 4 | { 5 | public partial class RemoveAppearanceFields : Migration 6 | { 7 | protected override void Up(MigrationBuilder migrationBuilder) 8 | { 9 | migrationBuilder.DropIndex( 10 | name: "IX_Players_AppearanceId", 11 | table: "Players"); 12 | 13 | migrationBuilder.DropColumn( 14 | name: "PlayerId", 15 | table: "Appearances"); 16 | 17 | migrationBuilder.CreateIndex( 18 | name: "IX_Players_AppearanceId", 19 | table: "Players", 20 | column: "AppearanceId"); 21 | } 22 | 23 | protected override void Down(MigrationBuilder migrationBuilder) 24 | { 25 | migrationBuilder.DropIndex( 26 | name: "IX_Players_AppearanceId", 27 | table: "Players"); 28 | 29 | migrationBuilder.AddColumn( 30 | name: "PlayerId", 31 | table: "Appearances", 32 | type: "integer", 33 | nullable: false, 34 | defaultValue: 0); 35 | 36 | migrationBuilder.CreateIndex( 37 | name: "IX_Players_AppearanceId", 38 | table: "Players", 39 | column: "AppearanceId", 40 | unique: true); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /NetScape.Modules.ThreeOneSeven.Game/Interface/LogoutTabHandler.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.FileSystem; 2 | using NetScape.Abstractions.Interfaces.Messages; 3 | using NetScape.Abstractions.Model.Messages; 4 | using NetScape.Modules.Messages; 5 | using NetScape.Modules.Messages.Models; 6 | using System; 7 | using System.Threading.Tasks; 8 | using static NetScape.Modules.Messages.Models.ThreeOneSevenDecoderMessages.Types; 9 | using static NetScape.Modules.Messages.Models.ThreeOneSevenEncoderMessages.Types; 10 | 11 | namespace NetScape.Modules.ThreeOneSeven.Game.Interface 12 | { 13 | [MessageHandler] 14 | public class LogoutTabHandler 15 | { 16 | private readonly IProtoMessageSender _protoMessageSender; 17 | private readonly IPlayerRepository _playerRepository; 18 | public LogoutTabHandler(IProtoMessageSender protoMessageSender, IPlayerRepository playerRepository) 19 | { 20 | _protoMessageSender = protoMessageSender; 21 | _playerRepository = playerRepository; 22 | } 23 | 24 | [Message(typeof(ButtonMessage), nameof(Filter))] 25 | public async Task OnLogoutClick(DecoderMessage buttonMessage) 26 | { 27 | await _playerRepository.AddOrUpdateAsync(buttonMessage.Player); 28 | await _protoMessageSender.SendAsync(buttonMessage.Player, new LogoutMessage()); 29 | } 30 | 31 | public Predicate> Filter { get; } = (message) => message.Message.InterfaceId == 2458; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /NetScape.Modules.ThreeOneSeven.Game/Players/PlayerInitializer.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Interfaces.Game.Interface; 2 | using NetScape.Abstractions.Interfaces.Game.Player; 3 | using NetScape.Abstractions.Interfaces.Messages; 4 | using NetScape.Modules.Messages.Models; 5 | using System.Threading.Tasks; 6 | 7 | namespace NetScape.Modules.ThreeOneSeven.Game.Players 8 | { 9 | public class PlayerInitializer : IPlayerInitializer 10 | { 11 | private readonly ITabManager _tabManager; 12 | private readonly IProtoMessageSender _protoMessageSender; 13 | 14 | public PlayerInitializer(ITabManager tabManager, IProtoMessageSender protoMessageSender) 15 | { 16 | _tabManager = tabManager; 17 | _protoMessageSender = protoMessageSender; 18 | } 19 | 20 | public Task InitializeAsync(Abstractions.Model.Game.Player player) 21 | { 22 | var initMessage = new ThreeOneSevenEncoderMessages.Types. 23 | IdAssignmentMessage 24 | { IsMembers = true, NewId = player.Index }; 25 | _ = _protoMessageSender.SendAsync(player, initMessage); 26 | player.UpdateAppearance(); 27 | 28 | var defaultTabs = _tabManager.Default; 29 | for (int tab = 0; tab < defaultTabs.Length; tab++) 30 | { 31 | var interfaceId = defaultTabs[tab]; 32 | _ = _tabManager.SetTabAsync(player, tab, interfaceId); 33 | } 34 | return Task.CompletedTask; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /NetScape.Modules.FourSevenFour.Game/Messages/Handlers/WelcomeScreenHandler.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Interfaces.Messages; 2 | using NetScape.Abstractions.Model.Messages; 3 | using NetScape.Modules.Messages; 4 | using System; 5 | using System.Threading.Tasks; 6 | using static NetScape.Modules.Messages.Models.FourSevenFourDecoderMessages.Types; 7 | using static NetScape.Modules.Messages.Models.FourSevenFourEncoderMessages.Types; 8 | 9 | namespace NetScape.Modules.FourSevenFour.Game.Messages.Handlers 10 | { 11 | [MessageHandler] 12 | public class WelcomeScreenHandler 13 | { 14 | private readonly IProtoMessageSender _messageSender; 15 | 16 | public WelcomeScreenHandler(IProtoMessageSender messageSender) 17 | { 18 | _messageSender = messageSender; 19 | } 20 | 21 | [Message(typeof(ClickButtonMessage), nameof(Filter))] 22 | public async Task OnWelcomeScreenClick(DecoderMessage decoderMessage) 23 | { 24 | var player = decoderMessage.Player; 25 | var buttonPackedId = decoderMessage.Message.ButtonId; 26 | switch(buttonPackedId) 27 | { 28 | case 6: 29 | await _messageSender.SendAsync(player, new SendInterfaceMessage { InterfaceId = 548 }); 30 | player.UpdateAppearance(); 31 | return; 32 | } 33 | } 34 | 35 | public Predicate> Filter { get; } = e => e.Message.InterfaceId == 378; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /NetScape.Modules.DAL/NetScape.Modules.DAL.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage 5 | netcoreapp5.0 6 | false 7 | NetScape Database Access Layer 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | all 20 | runtime; build; native; contentfiles; analyzers; buildtransitive 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /NetScape.Modules.World/PlayerEntityList.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Dynamic; 4 | using System.Linq; 5 | using System.Threading; 6 | using NetScape.Abstractions.Interfaces.World; 7 | using NetScape.Abstractions.Model.Game; 8 | 9 | namespace NetScape.Modules.World 10 | { 11 | public class PlayerEntityList : IEntityList 12 | { 13 | private readonly Player[] _entities = new Player[2048]; 14 | private int _entityCount = 0; 15 | private readonly List _freeIndexes = new(); 16 | 17 | public void Add(Player entity) 18 | { 19 | lock (_freeIndexes) 20 | { 21 | if (_freeIndexes.Any()) 22 | { 23 | var index = _freeIndexes.First(); 24 | SetIndex(entity, index); 25 | return; 26 | } 27 | } 28 | 29 | var newIndex = Interlocked.Increment(ref _entityCount); 30 | SetIndex(entity, newIndex); 31 | } 32 | 33 | private void SetIndex(Player entity, int index) 34 | { 35 | _freeIndexes.Remove(index); 36 | entity.Index = index; 37 | _entities[index] = entity; 38 | } 39 | 40 | public void Remove(Player entity) 41 | { 42 | _entities[entity.Index] = null; 43 | Interlocked.Decrement(ref _entityCount); 44 | } 45 | 46 | public Player[] Entities => _entities; 47 | 48 | public int Count => _entityCount; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /NetScape.Modules.Cache/NetScape.Modules.Cache.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage 5 | netcoreapp5.0 6 | false 7 | NetScape Cache Modules 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /NetScape.Modules.Cache/Vector3.cs: -------------------------------------------------------------------------------- 1 | namespace NetScape.Modules.Cache 2 | { 3 | public class Vector3 4 | { 5 | // private static int UnknownInteger; 6 | 7 | private static Vector3[] UnknownVector3Array = new Vector3[0]; 8 | 9 | public Vector3() 10 | { 11 | this.Level = -1; 12 | } 13 | 14 | public Vector3(int level, int x, int y, int z) 15 | { 16 | this.Level = level; 17 | this.X = x; 18 | this.Y = y; 19 | this.Z = z; 20 | } 21 | 22 | private Vector3(Vector3 vector) 23 | { 24 | this.Level = vector.Level; 25 | this.X = vector.X; 26 | this.Y = vector.Y; 27 | this.Z = vector.Z; 28 | } 29 | 30 | private Vector3(int unknownInteger, bool unknownBoolean) 31 | { 32 | if (unknownInteger == -1) 33 | { 34 | this.Level = -1; 35 | } 36 | else 37 | { 38 | this.Level = (unknownInteger >> 28) & 3; 39 | this.X = ((unknownInteger >> 14) & 0x3fff) << 9; 40 | this.Y = 0; 41 | this.Z = (unknownInteger & 0x3fff) << 9; 42 | 43 | if (unknownBoolean) 44 | { 45 | this.X += 256; 46 | this.Z += 256; 47 | } 48 | } 49 | } 50 | 51 | public int Level { get; } 52 | public int X { get; } 53 | public int Y { get; } 54 | public int Z { get; } 55 | } 56 | } -------------------------------------------------------------------------------- /NetScape/Kernel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Autofac; 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.Extensions.Configuration; 5 | using NetScape.Core; 6 | using NetScape.Modules.DAL; 7 | using NetScape.Modules.Messages; 8 | using NetScape.Modules.Messages.Models; 9 | using NetScape.Modules.ThreeOneSeven.Game; 10 | using NetScape.Modules.ThreeOneSeven.LoginProtocol; 11 | using NetScape.Modules.ThreeOneSeven.World.Updating; 12 | using System.Collections.Generic; 13 | using NetScape.Abstractions.Model.Game; 14 | 15 | namespace NetScape 16 | { 17 | public class Kernel 18 | { 19 | public static void Main(string[] args) 20 | { 21 | List modules = new() 22 | { 23 | new ThreeOneSevenGameModule(), 24 | new MessagesModule( 25 | typeof(ThreeOneSevenEncoderMessages.Types), 26 | typeof(ThreeOneSevenDecoderMessages.Types) 27 | ), 28 | new ThreeOneSevenLoginModule(), 29 | new ThreeOneSevenUpdatingModule() 30 | }; 31 | ServerHandler.RunServer("appsettings.json", BuildDbOptions, modules); 32 | Console.ReadLine(); 33 | } 34 | 35 | private static void BuildDbOptions(DbContextOptionsBuilder optionsBuilder, IConfigurationRoot configurationRoot) 36 | { 37 | optionsBuilder.UseNpgsql(configurationRoot.GetConnectionString("NetScape"), 38 | x => x.MigrationsAssembly(typeof(DatabaseContext) 39 | .Assembly.FullName)); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /NetScape.Modules.Messages/MessageChannelHandler.cs: -------------------------------------------------------------------------------- 1 | using DotNetty.Buffers; 2 | using DotNetty.Transport.Channels; 3 | using NetScape.Abstractions; 4 | using NetScape.Abstractions.Interfaces.World; 5 | using NetScape.Abstractions.Model.Game; 6 | using Serilog; 7 | using System; 8 | using System.Threading.Tasks; 9 | 10 | namespace NetScape.Modules.Messages 11 | { 12 | public class MessageChannelHandler : SimpleChannelInboundHandler 13 | { 14 | private readonly ILogger _logger; 15 | private readonly IWorld _world; 16 | 17 | public MessageChannelHandler(ILogger logger, IWorld world) 18 | { 19 | _logger = logger; 20 | _world = world; 21 | } 22 | 23 | protected override void ChannelRead0(IChannelHandlerContext ctx, IByteBuffer msg) 24 | { 25 | msg.Retain(); 26 | ctx.FireChannelRead(msg); 27 | } 28 | 29 | public override void ChannelInactive(IChannelHandlerContext context) 30 | { 31 | var player = context.GetAttribute(Constants.PlayerAttributeKey).GetAndRemove(); 32 | _world.Remove(player); 33 | _logger.Information("Player: {0} disconnected Addr: {1}", player.Username, context.Channel.RemoteAddress); 34 | base.ChannelInactive(context); 35 | } 36 | 37 | public override void ExceptionCaught(IChannelHandlerContext context, Exception exception) 38 | { 39 | context.CloseAsync(); 40 | _logger.Error(exception, nameof(ExceptionCaught)); 41 | base.ExceptionCaught(context, exception); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | # This is a basic workflow to help you get started with Actions 2 | 3 | name: Nuget Publish 4 | 5 | # Controls when the action will run. 6 | on: 7 | # Triggers the workflow on push or pull request events but only for the master branch 8 | release: 9 | types: [ published ] 10 | 11 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 12 | jobs: 13 | # This workflow contains a single job called "build" 14 | build: 15 | # The type of runner that the job will run on 16 | runs-on: ubuntu-latest 17 | 18 | # Steps represent a sequence of tasks that will be executed as part of the job 19 | steps: 20 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 21 | - uses: actions/checkout@v2 22 | - uses: actions/setup-dotnet@v1 23 | name: Setup dotnet 24 | with: 25 | dotnet-version: 5.0.x 26 | - run: dotnet build 27 | - run: dotnet pack -c Release -o packed /p:Version=${{ github.event.release.tag_name }} 28 | - name: Setup NuGet.exe for use with actions 29 | # You may pin to the exact commit or the version. 30 | # uses: NuGet/setup-nuget@04b0c2b8d1b97922f67eca497d7cf0bf17b8ffe1 31 | uses: NuGet/setup-nuget@v1.0.5 32 | with: 33 | # NuGet version to install. Can be `latest`, `preview`, a concrete version like `5.3.1`, or a semver range specifier like `5.x`. 34 | nuget-api-key: ${{ secrets.NUGET_KEY }} 35 | - run: dotnet nuget push packed/*.nupkg --skip-duplicate --source https://api.nuget.org/v3/index.json --api-key ${{ secrets.NUGET_KEY }} 36 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Model/Login/LoginResponse.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Model.Game; 2 | 3 | namespace NetScape.Abstractions.Model.Login 4 | { 5 | /// 6 | /// Represents a login response. 7 | /// 8 | /// The type of the status. 9 | public class LoginResponse 10 | { 11 | 12 | /// 13 | /// Gets or sets a value indicating whether this is flagged. 14 | /// 15 | /// 16 | /// true if flagged; otherwise, false. 17 | /// 18 | public bool Flagged { get; set; } 19 | 20 | /// 21 | /// Gets or sets the rights. 22 | /// 23 | /// 24 | /// The rights. 25 | /// 26 | public int Rights { get; set; } 27 | 28 | /// 29 | /// Gets or sets the status. 30 | /// 31 | /// 32 | /// The status. 33 | /// 34 | public TStatus Status { get; set; } 35 | 36 | /// 37 | /// Gets or sets a value indicating whether this is created. 38 | /// 39 | /// 40 | /// true if created; otherwise, false. 41 | /// 42 | public bool Created { get; set; } 43 | 44 | /// 45 | /// Gets or sets the player. 46 | /// 47 | /// 48 | /// The player. 49 | /// 50 | public Player Player { get; set; } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Model/Login/PlayerCredentials.cs: -------------------------------------------------------------------------------- 1 | namespace NetScape.Abstractions.Model.Login 2 | { 3 | /// 4 | /// Holds the player credentials for a player 5 | /// 6 | public sealed record PlayerCredentials 7 | { 8 | 9 | /// 10 | /// Gets or sets the encoded username. 11 | /// 12 | /// 13 | /// The encoded username. 14 | /// 15 | public long EncodedUsername { get; set; } 16 | 17 | /// 18 | /// Gets or sets the password. 19 | /// 20 | /// 21 | /// The password. 22 | /// 23 | public string Password { get; set; } 24 | 25 | /// 26 | /// Gets or sets the uid. 27 | /// 28 | /// 29 | /// The uid. 30 | /// 31 | public int Uid { get; set; } 32 | 33 | /// 34 | /// Gets or sets the username. 35 | /// 36 | /// 37 | /// The username. 38 | /// 39 | public string Username { get; set; } 40 | 41 | /// 42 | /// Gets or sets the username hash. 43 | /// 44 | /// 45 | /// The username hash. 46 | /// 47 | public string UsernameHash { get; set; } 48 | 49 | /// 50 | /// Gets or sets the host address. 51 | /// 52 | /// 53 | /// The host address. 54 | /// 55 | public string HostAddress { get; set; } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Model/World/Updating/SynchronizationBlockSet.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace NetScape.Abstractions.Model.World.Updating 5 | { 6 | public class SynchronizationBlockSet : ICloneable 7 | { 8 | private readonly Dictionary _blocks = new Dictionary(8); 9 | 10 | public object Clone() 11 | { 12 | SynchronizationBlockSet copy = new SynchronizationBlockSet(); 13 | foreach (var block in _blocks) 14 | { 15 | copy._blocks.Add(block.Key, block.Value); 16 | } 17 | return copy; 18 | } 19 | 20 | public void Add(T block) where T : SynchronizationBlock 21 | { 22 | _blocks.Add(typeof(T), block); 23 | } 24 | 25 | public bool Contains() where T : SynchronizationBlock 26 | { 27 | return _blocks.ContainsKey(typeof(T)); 28 | } 29 | 30 | public T Get() where T : SynchronizationBlock 31 | { 32 | var containsBlock = _blocks.TryGetValue(typeof(T), out var block); 33 | return containsBlock ? (T)block : null; 34 | } 35 | 36 | public T Remove() where T : SynchronizationBlock 37 | { 38 | var block = Get(); 39 | if (block != null) 40 | { 41 | _blocks.Remove(typeof(T)); 42 | } 43 | return block; 44 | } 45 | 46 | public int Size() 47 | { 48 | return _blocks.Count; 49 | } 50 | 51 | public void Clear() 52 | { 53 | _blocks.Clear(); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Util/TextUtil.cs: -------------------------------------------------------------------------------- 1 | namespace NetScape.Abstractions.Util 2 | { 3 | public class TextUtil 4 | { 5 | /// 6 | /// An array of characters ordered by frequency - the elements with lower indices (generally) appear more often in 7 | /// chat messages. 8 | /// 9 | private static char[] VALID_CHARACTERS = { '_', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 10 | 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', 11 | '7', '8', '9' }; 12 | 13 | public static long NameToLong(string name) 14 | { 15 | long longName = 0L; 16 | for (int i = 0; i < name.Length && i < 12; i++) 17 | { 18 | char c = name[i]; 19 | longName *= 37L; 20 | if (c >= 'A' && c <= 'Z') 21 | { 22 | longName += (1 + c) - 65; 23 | } 24 | else if (c >= 'a' && c <= 'z') 25 | { 26 | longName += (1 + c) - 97; 27 | } 28 | else if (c >= '0' && c <= '9') 29 | { 30 | longName += (27 + c) - 48; 31 | } 32 | } 33 | while (longName % 37L == 0L && longName != 0L) 34 | { 35 | longName /= 37L; 36 | } 37 | return longName; 38 | } 39 | 40 | public static string LongToName(long longName) 41 | { 42 | if (longName <= 0L || longName >= 6582952005840035281L) 43 | { 44 | return "invalid_name"; 45 | } 46 | if (longName % 37L == 0L) 47 | { 48 | return "invalid_name"; 49 | } 50 | int length = 0; 51 | var name = new char[12]; 52 | while (longName != 0L) 53 | { 54 | long l1 = longName; 55 | longName /= 37L; 56 | name[11 - length++] = VALID_CHARACTERS[(int)(l1 - longName * 37L)]; 57 | } 58 | return new string(name, 12 - length, length); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /NetScape.Modules.DAL/DatabaseContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.EntityFrameworkCore.Metadata; 5 | using Microsoft.Extensions.Logging; 6 | using NetScape.Abstractions.Model.Game; 7 | 8 | #nullable disable 9 | 10 | namespace NetScape.Modules.DAL 11 | { 12 | public partial class DatabaseContext : DbContext where TPlayer : Player 13 | { 14 | private readonly ILoggerFactory _loggerFactory; 15 | 16 | public DatabaseContext(DbContextOptions> options, ILoggerFactory loggerFactory = null) 17 | : base(options) 18 | { 19 | _loggerFactory = loggerFactory; 20 | } 21 | 22 | public DbSet Players { get; set; } 23 | public DbSet Appearances { get; set; } 24 | 25 | protected override void OnModelCreating(ModelBuilder modelBuilder) 26 | { 27 | modelBuilder.HasAnnotation("Relational:Collation", "English_United Kingdom.1252"); 28 | modelBuilder 29 | .Entity() 30 | .Property(e => e.Colors) 31 | .HasConversion(v => string.Join(",", v), v => v.Split(",", StringSplitOptions.None).Select(int.Parse).ToArray()); 32 | modelBuilder 33 | .Entity() 34 | .Property(e => e.Style) 35 | .HasConversion(v => string.Join(",", v), v => v.Split(",", StringSplitOptions.None).Select(int.Parse).ToArray()); 36 | modelBuilder.Entity().OwnsOne(t => t.Position); 37 | OnModelCreatingPartial(modelBuilder); 38 | } 39 | 40 | partial void OnModelCreatingPartial(ModelBuilder modelBuilder); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /NetScape.Core/NetScape.Core.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage 5 | net5.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /NetScape.Modules.Messages.Generator/NetScape.Modules.Messages.Generator.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | false 6 | 7 | 8 | 9 | 10 | all 11 | runtime; build; native; contentfiles; analyzers; buildtransitive 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | $(GetTargetPathDependsOn);GetDependencyTargetPaths; 24 | true 25 | NetScape Message Generator Module 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Cache/CacheIndex.cs: -------------------------------------------------------------------------------- 1 | namespace NetScape.Abstractions.Cache 2 | { 3 | /// 4 | /// 5 | /// Villermen 6 | /// Pea2nuts 7 | public enum CacheIndex 8 | { 9 | Undefined = -1, 10 | AnimationFrames = 0, 11 | AnimationFrameBases = 1, 12 | Miscellaneous = 2, 13 | Interfaces = 3, 14 | EmptyUsedToBeSoundEffects = 4, 15 | Maps = 5, 16 | EmptyUsedToBeMidis = 6, 17 | Models = 7, 18 | Sprites = 8, 19 | EmptyUsedToBeTextures = 9, 20 | HuffmanEncoding = 10, 21 | EmptyUsedToBeJingles = 11, 22 | ClientScripts = 12, 23 | FontMetrics = 13, 24 | SoundEffects = 14, 25 | EmptyUnknown1 = 15, 26 | Locations = 16, 27 | Enums = 17, 28 | Npcs = 18, 29 | ItemDefinitions = 19, 30 | Sequences = 20, 31 | SpotAnimations = 21, 32 | Structs = 22, 33 | WorldMapInfo = 23, 34 | Quickchat = 24, 35 | GlobalQuickchat = 25, 36 | Materials = 26, 37 | Particles = 27, 38 | Defaults = 28, 39 | Billboards = 29, 40 | NativeLibraries = 30, 41 | Shaders = 31, 42 | LoadingSprites = 32, 43 | LoadingScreens = 33, 44 | RawLoadingSprites = 34, 45 | Cutscenes = 35, 46 | EmptyUsedToBeVorbisFiles = 36, 47 | EmptyUsedToBeGfxConfigs = 37, 48 | EmptyUnknown2 = 38, 49 | EmptyUnknown3 = 39, 50 | Music = 40, 51 | WorldMapAreas = 41, 52 | WorldMapLabels = 42, 53 | PngDiffuseTextures = 43, 54 | PngHdrTextures = 44, 55 | DxtDiffuseTextures = 45, 56 | MippedPngHdrTextures = 46, 57 | RuneTek7Models = 47, 58 | RuneTek7Animations = 48, 59 | DatabaseTableIndex = 49, 60 | ReferenceTables = 255 61 | } 62 | } -------------------------------------------------------------------------------- /NetScape.Modules.FourSevenFour.Game/Messages/Handlers/WalkingQueueMessageHandler.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Model; 2 | using NetScape.Abstractions.Model.Game; 3 | using NetScape.Abstractions.Model.Messages; 4 | using NetScape.Modules.Messages; 5 | using NetScape.Modules.Messages.Models; 6 | using System.Linq; 7 | using NetScape.Abstractions.Game; 8 | 9 | namespace NetScape.Modules.FourSevenFour.Game.Messages.Handlers { 10 | 11 | [MessageHandler] 12 | public class WalkingQueueMessageHandler 13 | { 14 | private readonly WalkingQueueHandler _walkingQueueHandler; 15 | public WalkingQueueMessageHandler(WalkingQueueHandler walkingQueueHandler) 16 | { 17 | _walkingQueueHandler = walkingQueueHandler; 18 | } 19 | 20 | [Message(typeof(FourSevenFourDecoderMessages.Types.WalkingQueueMessage))] 21 | public void OnWalkQueueMessage(DecoderMessage decoderMessage) 22 | { 23 | var player = decoderMessage.Player; 24 | var message = decoderMessage.Message; 25 | var positions = Enumerable.Range(0, message.X.Count) 26 | .Select(t => new Position 27 | { 28 | X = message.X[t], 29 | Y = message.Y[t] 30 | }).ToArray(); 31 | 32 | for (int index = 0; index < positions.Length; index++) 33 | { 34 | Position step = positions[index]; 35 | if (index == 0) 36 | { 37 | _walkingQueueHandler.AddFirstStep(player, step); 38 | } 39 | else 40 | { 41 | _walkingQueueHandler.AddStep(player, step); 42 | } 43 | } 44 | player.WalkingQueue.Running = message.Run || player.WalkingQueue.Running; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /NetScape.Modules.ThreeOneSeven.Game/Messages/Handlers/WalkingQueueMessageHandler.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Model; 2 | using NetScape.Abstractions.Model.Game; 3 | using NetScape.Abstractions.Model.Messages; 4 | using NetScape.Modules.Messages; 5 | using NetScape.Modules.Messages.Models; 6 | using System.Linq; 7 | using NetScape.Abstractions.Game; 8 | 9 | namespace NetScape.Modules.ThreeOneSeven.Game.Messages.Handlers 10 | { 11 | 12 | [MessageHandler] 13 | public class WalkingQueueMessageHandler 14 | { 15 | private readonly WalkingQueueHandler _walkingQueueHandler; 16 | public WalkingQueueMessageHandler(WalkingQueueHandler walkingQueueHandler) 17 | { 18 | _walkingQueueHandler = walkingQueueHandler; 19 | } 20 | 21 | [Message(typeof(ThreeOneSevenDecoderMessages.Types.WalkingQueueMessage))] 22 | public void OnWalkQueueMessage(DecoderMessage decoderMessage) 23 | { 24 | var player = decoderMessage.Player; 25 | var message = decoderMessage.Message; 26 | var positions = Enumerable.Range(0, message.X.Count) 27 | .Select(t => new Position 28 | { 29 | X = message.X[t], 30 | Y = message.Y[t] 31 | }).ToArray(); 32 | 33 | for (int index = 0; index < positions.Length; index++) 34 | { 35 | Position step = positions[index]; 36 | if (index == 0) 37 | { 38 | _walkingQueueHandler.AddFirstStep(player, step); 39 | } 40 | else 41 | { 42 | _walkingQueueHandler.AddStep(player, step); 43 | } 44 | } 45 | player.WalkingQueue.Running = message.Run || player.WalkingQueue.Running; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /NetScape.Abstractions/NetScape.Abstractions.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp5.0 5 | NetScape Abstraction Modules 6 | false 7 | $(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | # NetScape 2 | Modular Runescape Private Server in C# for learning purposes & fun! 3 | 4 | ### Code Docs 5 | * [All Docs](/NetScape/api) 6 | 7 | ## Getting Started 8 | 9 | These instructions will get you a copy of the project up and running on your local machine for development and testing purposes. See deployment for notes on how to deploy the project on a live system. 10 | 11 | ### Prerequisites 12 | * [PostgresSQL](https://www.postgresql.org/download/) 13 | * [Net5.0](https://dotnet.microsoft.com/download/dotnet/5.0) 14 | 15 | ### Installing 16 | 1. Create the folder ```AspNetServerData\Cache``` in your users home folder and add the 317 cache (Currently NetScape only supports the 317 protocol) 17 | 2. Go to [appsettings.json](https://github.com/JayArrowz/NetScape/blob/master/NetScape/appsettings.json) and ensure the ConnectionString to your database is correct 18 | 3. Go to your Terminal (Make sure its current directory is matching the root of this repo) or VS Console then type: 19 | ``` 20 | dotnet tool install -g dotnet-ef 21 | dotnet build 22 | dotnet ef database update --project NetScape 23 | ``` 24 | 25 | To Run in Terminal: 26 | ``` 27 | dotnet run --project netscape 28 | ``` 29 | 30 | ## Contributing 31 | 32 | Please read [CONTRIBUTING.md](https://gist.github.com/PurpleBooth/b24679402957c63ec426) for details on our code of conduct, and the process for submitting pull requests to us. 33 | 34 | ## Versioning 35 | 36 | We use [SemVer](http://semver.org/) for versioning. For the versions available, see the [tags on this repository](https://github.com/JayArrowz/NetScape/tags). 37 | 38 | ## Authors 39 | 40 | * **JayArrowz** - [JayArrowz](https://github.com/JayArrowz) 41 | 42 | See also the list of [contributors](https://github.com/JayArrowz/NetScape/contributors) who participated in this project. 43 | 44 | ## Acknowledgments 45 | * JayArrowz 46 | * Graham 47 | * Major 48 | * Scu11 49 | * https://github.com/villermen/runescape-cache-tools 50 | * https://github.com/apollo-rsps/apollo 51 | -------------------------------------------------------------------------------- /NetScape.Modules.Cache/RuneTek5/IndexPointer.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using NetScape.Abstractions.Extensions; 3 | 4 | namespace NetScape.Modules.Cache.RuneTek5 5 | { 6 | /// 7 | /// An points to a file inside a . 8 | /// 9 | /// Graham 10 | /// `Discardedx2 11 | /// Villermen 12 | public class IndexPointer 13 | { 14 | /// 15 | /// Length of index data in bytes. 16 | /// 17 | public const int Length = 6; 18 | 19 | /// 20 | /// The number of the first sector that contains the file. 21 | /// 22 | public int FirstSectorPosition { get; set; } 23 | 24 | /// 25 | /// The size of the file in bytes. 26 | /// 27 | public int Filesize { get; set; } 28 | 29 | /// 30 | /// Decodes an object from the given stream and advances the stream's position by 6 bytes. 31 | /// 32 | /// 33 | /// 34 | public static IndexPointer Decode(Stream stream) 35 | { 36 | var reader = new BinaryReader(stream); 37 | 38 | return new IndexPointer 39 | { 40 | Filesize = reader.ReadUInt24BigEndian(), 41 | FirstSectorPosition = reader.ReadUInt24BigEndian() 42 | }; 43 | } 44 | 45 | /// 46 | /// Encodes the to the given stream, advancing its position by 6 bytes. 47 | /// 48 | /// 49 | public void Encode(Stream stream) 50 | { 51 | var writer = new BinaryWriter(stream); 52 | writer.WriteUInt24BigEndian(this.Filesize); 53 | writer.WriteUInt24BigEndian(this.FirstSectorPosition); 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /NetScape.Modules.Messages/NetScape.Modules.Messages.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | $(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage 11 | netcoreapp5.0 12 | false 13 | true 14 | Generated 15 | NetScape 317 Messaging Module 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /NetScape.Modules.FourSevenFour.LoginProtocol/Handlers/JS5Decoder.cs: -------------------------------------------------------------------------------- 1 | using DotNetty.Buffers; 2 | using DotNetty.Codecs; 3 | using DotNetty.Transport.Channels; 4 | using Serilog; 5 | using System.Collections.Generic; 6 | 7 | namespace NetScape.Modules.FourSevenFour.LoginProtocol.Handlers 8 | { 9 | public class JS5Decoder : ByteToMessageDecoder 10 | { 11 | private int _encryptionKey; 12 | protected override void Decode(IChannelHandlerContext context, IByteBuffer input, List output) 13 | { 14 | if (input.ReadableBytes > 0 && input.IsReadable()) 15 | { 16 | input.MarkReaderIndex(); 17 | int opcode = input.ReadByte(); 18 | 19 | Log.Logger.Debug("File Request: Opcode: {0}", opcode); 20 | if (opcode is 0 or 1) 21 | { 22 | if (input.ReadableBytes < 3) 23 | { 24 | input.ResetReaderIndex(); 25 | return; 26 | } 27 | int index = input.ReadByte(); 28 | int file = input.ReadUnsignedShort(); 29 | bool priority = opcode == 1; 30 | Log.Logger.Debug("File Request: Index: {0}, File: {1} Priority: {2}", index, file, priority); 31 | _ = context.Channel.WriteAndFlushAsync(new JS5Request(index, file, priority, _encryptionKey)); 32 | } 33 | else if (opcode is 2 or 3 or 6) 34 | { 35 | input.SkipBytes(3); 36 | } 37 | else if (opcode == 4) 38 | { 39 | _encryptionKey = input.ReadByte(); 40 | if (input.ReadShort() != 0) 41 | { 42 | _ = context.Channel.DisconnectAsync(); 43 | } 44 | } 45 | else 46 | { 47 | Log.Logger.Warning("Unknown JS5 Opcode: {0} Size: {1}", opcode, input.ReadableBytes); 48 | } 49 | } 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Interfaces/Messages/RegionUpdateMessage.cs: -------------------------------------------------------------------------------- 1 | using DotNetty.Buffers; 2 | using NetScape.Modules.Messages; 3 | using NetScape.Modules.Messages.Builder; 4 | 5 | namespace NetScape.Abstractions.Interfaces.Messages 6 | { 7 | public abstract class RegionUpdateMessage : IEncoderMessage 8 | { 9 | /// 10 | /// The integer value indicating this RegionUpdateMessage is a high-priority message. 11 | /// 12 | protected static readonly int High_Priority = 0; 13 | 14 | /// 15 | /// The integer value indicating this RegionUpdateMessage is a low-priority message. 16 | /// 17 | protected static readonly int Low_Priority = 1; 18 | 19 | /// 20 | /// Converts to message. 21 | /// 22 | /// The bytebuffer allocator. 23 | /// 24 | public abstract MessageFrame ToMessage(IByteBufferAllocator alloc); 25 | 26 | /// 27 | /// Gets the priority. 28 | /// 29 | /// 30 | /// The priority. 31 | /// 32 | public abstract int Priority { get; } 33 | 34 | /// 35 | /// Returns a hash code for this instance. 36 | /// 37 | /// 38 | /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. 39 | /// 40 | public abstract override int GetHashCode(); 41 | 42 | /// 43 | /// Determines whether the specified , is equal to this instance. 44 | /// 45 | /// The to compare with this instance. 46 | /// 47 | /// true if the specified is equal to this instance; otherwise, false. 48 | /// 49 | public abstract override bool Equals(object o); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /NetScape.Modules.FourSevenFour.LoginProtocol/LoginProcessor.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.FileSystem; 2 | using NetScape.Abstractions.Login; 3 | using Serilog; 4 | using System.Threading.Tasks; 5 | 6 | namespace NetScape.Modules.FourSevenFour.LoginProtocol 7 | { 8 | public class LoginProcessor : DefaultLoginProcessor 9 | { 10 | private readonly IPlayerRepository _playerRepository; 11 | 12 | public LoginProcessor(ILogger logger, IPlayerRepository playerRepository) : base(logger) 13 | { 14 | _playerRepository = playerRepository; 15 | } 16 | 17 | /// 18 | /// Processes a single by retriving the player from 19 | /// 20 | /// The login request. 21 | /// 22 | protected override async Task ProcessAsync(Rs2LoginRequest request) 23 | { 24 | var password = request.Credentials.Password; 25 | var username = request.Credentials.Username; 26 | _logger.Information("Pending login from {0}", username); 27 | 28 | if (password.Length < 4 || password.Length > 20 || string.IsNullOrEmpty(username) || username.Length > 12) 29 | { 30 | _logger.Information("Username ('{0}') or password did not pass validation.", username); 31 | return new Rs2LoginResponse { Status = FourSevenFourLoginStatus.StatusInvalidCredentials }; 32 | } 33 | 34 | var playerInDatabase = await _playerRepository.GetAsync(username); 35 | 36 | if (playerInDatabase != null && !playerInDatabase.Password.Equals(password)) 37 | { 38 | return new Rs2LoginResponse { Status = FourSevenFourLoginStatus.StatusInvalidCredentials }; 39 | } 40 | 41 | var createdNewPlayer = playerInDatabase == null; 42 | 43 | var player = await _playerRepository.GetOrCreateAsync(request.Credentials); 44 | return new Rs2LoginResponse { Status = FourSevenFourLoginStatus.StatusOk, Player = player, Created = createdNewPlayer }; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /NetScape.Modules.ThreeOneSeven.LoginProtocol/LoginProcessor.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.FileSystem; 2 | using NetScape.Abstractions.Login; 3 | using Serilog; 4 | using System.Threading.Tasks; 5 | 6 | namespace NetScape.Modules.ThreeOneSeven.LoginProtocol 7 | { 8 | 9 | public class LoginProcessor : DefaultLoginProcessor 10 | { 11 | private readonly IPlayerRepository _playerRepository; 12 | 13 | public LoginProcessor(ILogger logger, IPlayerRepository playerRepository) : base(logger) 14 | { 15 | _playerRepository = playerRepository; 16 | } 17 | 18 | /// 19 | /// Processes a single by retriving the player from 20 | /// 21 | /// The login request. 22 | /// 23 | protected override async Task ProcessAsync(Rs2LoginRequest request) 24 | { 25 | var password = request.Credentials.Password; 26 | var username = request.Credentials.Username; 27 | _logger.Information("Pending login from {0}", username); 28 | 29 | if (password.Length < 4 || password.Length > 20 || string.IsNullOrEmpty(username) || username.Length > 12) 30 | { 31 | _logger.Information("Username ('{0}') or password did not pass validation.", username); 32 | return new Rs2LoginResponse { Status = ThreeOneSevenLoginStatus.StatusInvalidCredentials }; 33 | } 34 | 35 | var playerInDatabase = await _playerRepository.GetAsync(username); 36 | 37 | if (playerInDatabase != null && !playerInDatabase.Password.Equals(password)) 38 | { 39 | return new Rs2LoginResponse { Status = ThreeOneSevenLoginStatus.StatusInvalidCredentials }; 40 | } 41 | 42 | var createdNewPlayer = playerInDatabase == null; 43 | 44 | var player = await _playerRepository.GetOrCreateAsync(request.Credentials); 45 | return new Rs2LoginResponse { Status = ThreeOneSevenLoginStatus.StatusOk, Player = player, Created = createdNewPlayer }; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /NetScape.Modules.Cache/RuneTek5/RuneTek5Cache.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Cache; 2 | using NetScape.Abstractions.Interfaces.Cache; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | 7 | namespace NetScape.Modules.Cache.RuneTek5 8 | { 9 | /// 10 | /// Can read and write to a RuneTek5 type cache consisting of a single data (.dat2) file and some index (.id#) files. 11 | /// 12 | /// Graham 13 | /// `Discardedx2 14 | /// Villermen 15 | public class RuneTek5Cache : ReferenceTableCacheBase, IReferenceTableCache 16 | { 17 | /// 18 | /// The that backs this cache. 19 | /// 20 | private IFileStore _fileStore; 21 | 22 | /// 23 | /// Creates an interface on the cache stored in the given directory. 24 | /// 25 | /// 26 | /// 27 | public RuneTek5Cache(IFileStore fileStore) 28 | { 29 | _fileStore = fileStore; 30 | } 31 | 32 | public override IEnumerable GetIndexes() 33 | { 34 | return this._fileStore.GetIndexes(); 35 | } 36 | 37 | protected override BinaryFile GetBinaryFile(CacheFileInfo fileInfo) 38 | { 39 | var file = new BinaryFile 40 | { 41 | Info = fileInfo 42 | }; 43 | 44 | file.Decode(this._fileStore.ReadFileData(fileInfo.Index, fileInfo.FileId.Value)); 45 | 46 | return file; 47 | } 48 | 49 | protected override void PutBinaryFile(BinaryFile file) 50 | { 51 | // Write data to file store 52 | this._fileStore.WriteFileData(file.Info.Index, file.Info.FileId.Value, file.Encode()); 53 | } 54 | 55 | public override void Dispose() 56 | { 57 | base.Dispose(); 58 | 59 | if (this._fileStore != null) 60 | { 61 | this._fileStore.Dispose(); 62 | this._fileStore = null; 63 | } 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /NetScape.GameServer/IO/GameServer.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Interfaces.IO; 2 | using NetScape.Abstractions.Interfaces.IO.EventLoop; 3 | using NetScape.Abstractions.IO; 4 | using DotNetty.Transport.Bootstrapping; 5 | using DotNetty.Transport.Channels; 6 | using DotNetty.Transport.Channels.Sockets; 7 | using Serilog; 8 | using System.Net; 9 | using System.Threading.Tasks; 10 | 11 | namespace NetScape.Modules.Server.IO 12 | { 13 | public sealed class GameServer : IGameServer 14 | { 15 | private readonly IEventLoopGroupFactory _eventLoopGroupFactory; 16 | private readonly IGameServerParameters _gameServerParameters; 17 | private readonly ILogger _logger; 18 | private readonly ServerChannelInitializer _serverChannelInitializer; 19 | 20 | public GameServer(ILogger logger, 21 | IGameServerParameters gameServerParameters, 22 | IEventLoopGroupFactory eventLoopGroupFactory, 23 | ServerChannelInitializer serverChannelInitializer) 24 | { 25 | _logger = logger; 26 | _gameServerParameters = gameServerParameters; 27 | _eventLoopGroupFactory = eventLoopGroupFactory; 28 | _serverChannelInitializer = serverChannelInitializer; 29 | } 30 | 31 | public IChannel Channel { get; set; } 32 | 33 | public async Task BindAsync() 34 | { 35 | var bossGroup = _eventLoopGroupFactory.GetBossGroup(); 36 | var workerGroup = _eventLoopGroupFactory.GetWorkerGroup(); 37 | var bootstrap = new ServerBootstrap(); 38 | 39 | bootstrap.ChannelFactory(() => new TcpServerSocketChannel()); 40 | bootstrap.Group(bossGroup, workerGroup); 41 | bootstrap.ChildHandler(_serverChannelInitializer); 42 | 43 | Channel = await bootstrap.BindAsync(IPAddress.Parse(_gameServerParameters.BindAddress), _gameServerParameters.Port); 44 | _logger.Information("Network Bound NIC IP: {0} Port: {1}", _gameServerParameters.BindAddress, _gameServerParameters.Port); 45 | } 46 | 47 | public async ValueTask DisposeAsync() 48 | { 49 | await Channel.DisconnectAsync(); 50 | _eventLoopGroupFactory.Dispose(); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Extensions/CollisionFlagExtensions.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Model.Game; 2 | using NetScape.Abstractions.Model.Region.Collision; 3 | 4 | namespace NetScape.Abstractions.Extensions 5 | { 6 | public static class CollisionFlagExtensions 7 | { 8 | /** 9 | * Returns an array of CollisionFlags that indicate if a Mob can be positioned on a tile. 10 | * 11 | * @return The array of CollisionFlags. 12 | */ 13 | public static CollisionFlag[] Mobs() 14 | { 15 | return new CollisionFlag[] { 16 | CollisionFlag.Mob_North_West, 17 | CollisionFlag.Mob_North, 18 | CollisionFlag.Mob_North_East, 19 | CollisionFlag.Mob_West, 20 | CollisionFlag.Mob_East, 21 | CollisionFlag.Mob_South_West, 22 | CollisionFlag.Mob_South, 23 | CollisionFlag.Mob_South_East, 24 | }; 25 | } 26 | 27 | /** 28 | * Returns an array of CollisionFlags that indicate if a Projectile can be positioned on a tile. 29 | * 30 | * @return The array of CollisionFlags. 31 | */ 32 | public static CollisionFlag[] Projectiles() 33 | { 34 | return new CollisionFlag[] { 35 | CollisionFlag.Projectile_North_West, 36 | CollisionFlag.Projectile_North, 37 | CollisionFlag.Projectile_North_East, 38 | CollisionFlag.Projectile_West, 39 | CollisionFlag.Projectile_East, 40 | CollisionFlag.Projectile_South_West, 41 | CollisionFlag.Projectile_South, 42 | CollisionFlag.Projectile_South_East, 43 | }; 44 | } 45 | 46 | public static short AsShort(this CollisionFlag collisionFlag) 47 | { 48 | return (short)(1 << collisionFlag.GetBit()); 49 | } 50 | 51 | public static int GetBit(this CollisionFlag collisionFlag) 52 | { 53 | return (int)collisionFlag; 54 | } 55 | 56 | public static CollisionFlag[] ForType(EntityType entity) 57 | { 58 | return entity == EntityType.Projectile ? Projectiles() : Mobs(); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NetScape 2 | Modular Runescape Private Server in C# for learning purposes & fun! 3 | 4 | ## Badges 5 | [![wakatime](https://wakatime.com/badge/github/JayArrowz/NetScape.svg)](https://wakatime.com/badge/github/JayArrowz/NetScape) [![.NET](https://github.com/JayArrowz/NetScape/actions/workflows/docs.yml/badge.svg?branch=master)](https://github.com/JayArrowz/NetScape/actions/workflows/docs.yml) 6 | 7 | ## Getting Started 8 | 9 | These instructions will get you a copy of the project up and running on your local machine for development and testing purposes. See deployment for notes on how to deploy the project on a live system. 10 | 11 | ## Prerequisites 12 | * [PostgresSQL](https://www.postgresql.org/download/) 13 | * [Net5.0](https://dotnet.microsoft.com/download/dotnet/5.0) 14 | 15 | ## Code Docs 16 | * [Code Docs](https://jayarrowz.github.io/NetScape/api/) 17 | 18 | ## Installing 19 | 1. Create the folder ```AspNetServerData\Cache``` in your users home folder and add the cache 20 | 2. Go to [appsettings.json](https://github.com/JayArrowz/NetScape/blob/master/NetScape/appsettings.json) and ensure the ConnectionString to your database is correct 21 | 3. Go to your Terminal (Make sure its current directory is matching the root of this repo) or VS Console then type: 22 | ``` 23 | dotnet tool install -g dotnet-ef 24 | dotnet build 25 | dotnet ef database update --project NetScape 26 | ``` 27 | 28 | To Run in Terminal: 29 | ``` 30 | dotnet run --project netscape 31 | ``` 32 | 33 | ## Contributing 34 | 35 | Please read [CONTRIBUTING.md](https://gist.github.com/PurpleBooth/b24679402957c63ec426) for details on our code of conduct, and the process for submitting pull requests to us. 36 | 37 | ## Versioning 38 | 39 | We use [SemVer](http://semver.org/) for versioning. For the versions available, see the [tags on this repository](https://github.com/JayArrowz/NetScape/tags). 40 | 41 | ## Authors 42 | 43 | * **JayArrowz** - [JayArrowz](https://github.com/JayArrowz) 44 | 45 | See also the list of [contributors](https://github.com/JayArrowz/NetScape/contributors) who participated in this project. 46 | 47 | ## Acknowledgments 48 | * JayArrowz 49 | * Graham 50 | * Major 51 | * Scu11 52 | * https://github.com/villermen/runescape-cache-tools 53 | * https://github.com/apollo-rsps/apollo 54 | -------------------------------------------------------------------------------- /NetScape.Modules.FourSevenFour.Game/Player/PlayerInitializer.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using NetScape.Abstractions.Interfaces.Game.Interface; 3 | using NetScape.Abstractions.Interfaces.Game.Player; 4 | using NetScape.Abstractions.Interfaces.Messages; 5 | using NetScape.Modules.FourSevenFour.Game.Messages.Encoders; 6 | using static NetScape.Modules.Messages.Models.FourSevenFourEncoderMessages.Types; 7 | 8 | namespace NetScape.Modules.FourSevenFour.Game.Player 9 | { 10 | public class PlayerInitializer : IPlayerInitializer 11 | { 12 | private readonly ITabManager _tabManager; 13 | private readonly IProtoMessageSender _protoMessageSender; 14 | 15 | public PlayerInitializer(ITabManager tabManager, IProtoMessageSender protoMessageSender) 16 | { 17 | _tabManager = tabManager; 18 | _protoMessageSender = protoMessageSender; 19 | } 20 | 21 | public Task InitializeAsync(Abstractions.Model.Game.Player player) 22 | { 23 | _ = player.SendAsync(new SendMapRegionMessage(player)).ContinueWith(_ => 24 | { 25 | 26 | var defaultTabs = _tabManager.Default; 27 | for (int tab = 0; tab < defaultTabs.Length; tab++) 28 | { 29 | var interfaceId = defaultTabs[tab]; 30 | _ = _tabManager.SetTabAsync(player, tab, interfaceId); 31 | } 32 | }); 33 | 34 | var openLoginScreenMessage = new SendInterfaceMessage 35 | { 36 | InterfaceId = 549 37 | }; 38 | 39 | _ = _protoMessageSender.SendAsync(player, openLoginScreenMessage); 40 | _ = _protoMessageSender.SendAsync(player, new OpenInterfaceMessage 41 | { 42 | Window = 549, 43 | Position = 2, 44 | InterfaceId = 378, 45 | Walkable = true 46 | }); 47 | _ = _protoMessageSender.SendAsync(player, new OpenInterfaceMessage 48 | { 49 | Window = 549, 50 | Position = 3, 51 | InterfaceId = 17, 52 | Walkable = true 53 | }); 54 | return Task.CompletedTask; 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /NetScape.Modules.Messages/ProtoEncoder.cs: -------------------------------------------------------------------------------- 1 | using DotNetty.Codecs; 2 | using DotNetty.Transport.Channels; 3 | using NetScape.Abstractions.Model.Messages; 4 | using NetScape.Modules.Messages.Builder; 5 | using System; 6 | using System.Collections.Generic; 7 | 8 | namespace NetScape.Modules.Messages 9 | { 10 | public class ProtoEncoder : MessageToMessageEncoder 11 | { 12 | private readonly ProtoMessageCodecHandler _protoMessageCodecHandler; 13 | public ProtoEncoder(ProtoMessageCodecHandler protoMessageCodecHandler) 14 | { 15 | _protoMessageCodecHandler = protoMessageCodecHandler; 16 | } 17 | 18 | protected override void Encode(IChannelHandlerContext context, ProtoMessage message, List output) 19 | { 20 | var protoMessageCodec = _protoMessageCodecHandler.EncoderCodecs[message.Opcode]; 21 | var messageCodec = protoMessageCodec.MessageCodec; 22 | var fieldCodecs = protoMessageCodec.FieldCodec; 23 | Serilog.Log.Logger.Debug("Encoder Sent: {0} - {1} to {2}", message.Message, message.Message.Descriptor.ClrType.Name, message.Player.Username); 24 | var frameType = messageCodec.SizeType.GetFrameType(); 25 | var bldr = new MessageFrameBuilder(context.Allocator, message.Opcode, frameType); 26 | foreach (var field in fieldCodecs) 27 | { 28 | var isString = field.FieldCodec.Type == Models.FieldType.String; 29 | MessageType? messageType = isString ? null : field.FieldCodec.Type.GetMessageType(); 30 | var dataTransform = field.FieldCodec.Transform.GetDataTransformation(); 31 | var dataOrder = field.FieldCodec.Order.GetDataOrder(); 32 | object value = field.FieldDescriptor.Accessor.GetValue(message.Message); 33 | 34 | if (!isString) 35 | { 36 | long unboxedInt = field.ToUnboxedNumber(value); 37 | bldr.Put(messageType.Value, dataOrder, dataTransform, unboxedInt); 38 | } else 39 | { 40 | bldr.PutString((string)value); 41 | } 42 | } 43 | output.Add(bldr.ToMessageFrame()); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /NetScape.Modules.ThreeOneSeven.Game/Messages/Decoders/WalkingQueueMessageDecoder.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Model; 2 | using NetScape.Abstractions.Model.Game; 3 | using NetScape.Modules.Messages; 4 | using NetScape.Modules.Messages.Builder; 5 | using NetScape.Modules.Messages.Models; 6 | using System.Linq; 7 | 8 | namespace NetScape.Modules.ThreeOneSeven.Game.Messages.Decoders 9 | { 10 | public class WalkingQueueMessageDecoder : MessageDecoderBase 11 | { 12 | public override int[] Ids { get; } = new int[] { 248, 164, 98 }; 13 | public override FrameType FrameType { get; } = FrameType.VariableByte; 14 | 15 | protected override ThreeOneSevenDecoderMessages.Types.WalkingQueueMessage Decode(Player player, MessageFrame frame) 16 | { 17 | var reader = new MessageFrameReader(frame); 18 | var length = frame.Payload.ReadableBytes; 19 | 20 | if (frame.Id == 248) 21 | { 22 | length -= 14; // strip off anti-cheat data 23 | } 24 | 25 | int steps = (length - 5) / 2; 26 | int[,] path = new int[steps, 2]; 27 | int x = (int)reader.GetUnsigned(MessageType.Short, DataOrder.Little, DataTransformation.Add); 28 | for (int i = 0; i < steps; i++) 29 | { 30 | path[i, 0] = (int)reader.GetSigned(MessageType.Byte); 31 | path[i, 1] = (int)reader.GetSigned(MessageType.Byte); 32 | } 33 | int y = (int)reader.GetUnsigned(MessageType.Short, DataOrder.Little); 34 | var run = reader.GetUnsigned(MessageType.Byte, DataTransformation.Negate) == 1; 35 | 36 | var positions = new Position[steps + 1]; 37 | positions[0] = new Position(x, y); 38 | for (int i = 0; i < steps; i++) 39 | { 40 | positions[i + 1] = new Position(path[i, 0] + x, path[i, 1] + y); 41 | } 42 | ThreeOneSevenDecoderMessages.Types.WalkingQueueMessage walkingQueueMessage = new() { Run = run, }; 43 | walkingQueueMessage.X.Add(positions.Select(t => t.X)); 44 | walkingQueueMessage.Y.Add(positions.Select(t => t.Y)); 45 | return walkingQueueMessage; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /NetScape.Abstractions/Model/Region/RegionCoordinates.cs: -------------------------------------------------------------------------------- 1 | namespace NetScape.Abstractions.Model.Region 2 | { 3 | /// 4 | /// An immutable class representing the coordinates of a region, where the coordinates ({@code x, y}) are the top-left of 5 | /// the region. 6 | /// @author Graham 7 | /// @author Major 8 | /// 9 | public record RegionCoordinates 10 | { 11 | 12 | /// 13 | /// Gets the RegionCoordinates for the specified . 14 | /// 15 | /// The Position. 16 | /// The RegionCoordinates. 17 | public static RegionCoordinates FromPosition(Position position) 18 | { 19 | return new RegionCoordinates(position.TopLeftRegionX, position.TopLeftRegionY); 20 | } 21 | 22 | /// 23 | /// Creates the RegionCoordinates. 24 | /// 25 | /// The x coordinate. 26 | /// The y coordinate. 27 | public RegionCoordinates(int x, int y) 28 | { 29 | this.X = x; 30 | this.Y = y; 31 | } 32 | 33 | /// 34 | /// Gets the absolute x coordinate of this Region (which can be compared directly against . 35 | /// 36 | /// The absolute x coordinate. 37 | public int AbsoluteX 38 | { 39 | get 40 | { 41 | return Constants.RegionSize * (X + 6); 42 | } 43 | } 44 | 45 | /// 46 | /// Gets the absolute y coordinate of this Region (which can be compared directly against . 47 | /// 48 | /// The absolute y coordinate. 49 | public int AbsoluteY 50 | { 51 | get 52 | { 53 | return Constants.RegionSize * (Y + 6); 54 | } 55 | } 56 | 57 | /// 58 | /// Gets the x coordinate (equivalent to the of a position within this region). 59 | /// 60 | /// The x coordinate. 61 | public int X { get; } 62 | 63 | /// 64 | /// Gets the y coordinate (equivalent to the of a position within this region). 65 | /// 66 | /// The y coordinate. 67 | public int Y { get; } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /NetScape.Modules.FourSevenFour.Game/Messages/Decoders/WalkingQueueMessageDecoder.cs: -------------------------------------------------------------------------------- 1 | using NetScape.Abstractions.Model; 2 | using NetScape.Abstractions.Model.Game; 3 | using NetScape.Modules.Messages; 4 | using NetScape.Modules.Messages.Builder; 5 | using NetScape.Modules.Messages.Models; 6 | using System.Linq; 7 | 8 | namespace NetScape.Modules.FourSevenFour.Game.Messages.Decoders 9 | { 10 | public class WalkingQueueMessageDecoder : MessageDecoderBase 11 | { 12 | public override int[] Ids { get; } = new int[] { 11, 46, 59 }; 13 | public override FrameType FrameType { get; } = FrameType.VariableByte; 14 | 15 | protected override FourSevenFourDecoderMessages.Types.WalkingQueueMessage Decode(Abstractions.Model.Game.Player player, MessageFrame frame) 16 | { 17 | var reader = new MessageFrameReader(frame); 18 | var length = frame.Payload.ReadableBytes; 19 | 20 | if (frame.Id == 11) 21 | { 22 | length -= 14; // strip off anti-cheat data 23 | } 24 | 25 | int steps = (length - 5) / 2; 26 | int[,] path = new int[steps, 2]; 27 | for (int i = 0; i < steps; i++) 28 | { 29 | path[i, 0] = (int)reader.GetSigned(MessageType.Byte); 30 | path[i, 1] = (int)reader.GetSigned(MessageType.Byte, DataTransformation.Subtract); 31 | } 32 | int x = (int)reader.GetUnsigned(MessageType.Short, DataTransformation.Add); 33 | int y = (int)reader.GetUnsigned(MessageType.Short, DataOrder.Little); 34 | var run = reader.GetUnsigned(MessageType.Byte, DataTransformation.Negate) == 1; 35 | 36 | var positions = new Position[steps + 1]; 37 | positions[0] = new Position(x, y); 38 | for (int i = 0; i < steps; i++) 39 | { 40 | positions[i + 1] = new Position(path[i, 0] + x, path[i, 1] + y); 41 | } 42 | FourSevenFourDecoderMessages.Types.WalkingQueueMessage walkingQueueMessage = new() { Run = run, }; 43 | walkingQueueMessage.X.Add(positions.Select(t => t.X)); 44 | walkingQueueMessage.Y.Add(positions.Select(t => t.Y)); 45 | return walkingQueueMessage; 46 | } 47 | } 48 | } 49 | --------------------------------------------------------------------------------