mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-15 18:45:23 -04:00
Use dispatch table for reading packets, split off CPE reading/writing into a separate file.
This commit is contained in:
parent
9f4d015709
commit
bf314359cd
@ -146,12 +146,13 @@
|
|||||||
<Compile Include="Model\ZombieModel.cs" />
|
<Compile Include="Model\ZombieModel.cs" />
|
||||||
<Compile Include="Network\Enums.cs" />
|
<Compile Include="Network\Enums.cs" />
|
||||||
<Compile Include="Network\INetworkProcessor.cs" />
|
<Compile Include="Network\INetworkProcessor.cs" />
|
||||||
|
<Compile Include="Network\NetworkProcessor.CPE.cs" />
|
||||||
<Compile Include="Network\NetworkProcessor.cs" />
|
<Compile Include="Network\NetworkProcessor.cs" />
|
||||||
<Compile Include="Network\Utils\AsyncDownloader.cs" />
|
<Compile Include="Network\Utils\AsyncDownloader.cs" />
|
||||||
<Compile Include="Network\Utils\FastNetReader.cs" />
|
<Compile Include="Network\Utils\FastNetReader.cs" />
|
||||||
<Compile Include="Network\Utils\FixedBufferStream.cs" />
|
<Compile Include="Network\Utils\FixedBufferStream.cs" />
|
||||||
<Compile Include="Network\Utils\GZipHeaderReader.cs" />
|
<Compile Include="Network\Utils\GZipHeaderReader.cs" />
|
||||||
<Compile Include="Network\WomConfigHandler.cs" />
|
<Compile Include="Network\NetworkProcessor.WoM.cs" />
|
||||||
<Compile Include="Commands\CommandManager.cs" />
|
<Compile Include="Commands\CommandManager.cs" />
|
||||||
<Compile Include="Commands\CommandReader.cs" />
|
<Compile Include="Commands\CommandReader.cs" />
|
||||||
<Compile Include="Physics\BoundingBox.cs" />
|
<Compile Include="Physics\BoundingBox.cs" />
|
||||||
|
@ -42,6 +42,8 @@ namespace ClassicalSharp {
|
|||||||
CpeDefineBlock = 35,
|
CpeDefineBlock = 35,
|
||||||
CpeDefineLiquid = 36,
|
CpeDefineLiquid = 36,
|
||||||
CpeRemoveBlockDefinition = 37,
|
CpeRemoveBlockDefinition = 37,
|
||||||
|
|
||||||
|
Max,
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum CpeMessage {
|
public enum CpeMessage {
|
||||||
|
331
ClassicalSharp/Network/NetworkProcessor.CPE.cs
Normal file
331
ClassicalSharp/Network/NetworkProcessor.CPE.cs
Normal file
@ -0,0 +1,331 @@
|
|||||||
|
using System;
|
||||||
|
using ClassicalSharp.TexturePack;
|
||||||
|
using OpenTK.Input;
|
||||||
|
|
||||||
|
namespace ClassicalSharp {
|
||||||
|
|
||||||
|
public partial class NetworkProcessor : INetworkProcessor {
|
||||||
|
|
||||||
|
#region Writing
|
||||||
|
|
||||||
|
public override void SendPlayerClick( MouseButton button, bool buttonDown, byte targetId, PickedPos pos ) {
|
||||||
|
Player p = game.LocalPlayer;
|
||||||
|
MakePlayerClick( (byte)button, buttonDown, p.YawDegrees, p.PitchDegrees, targetId,
|
||||||
|
pos.BlockPos, pos.BlockFace );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void MakeExtInfo( string appName, int extensionsCount ) {
|
||||||
|
WriteUInt8( (byte)PacketId.CpeExtInfo );
|
||||||
|
WriteString( appName );
|
||||||
|
WriteInt16( (short)extensionsCount );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void MakeExtEntry( string extensionName, int extensionVersion ) {
|
||||||
|
WriteUInt8( (byte)PacketId.CpeExtEntry );
|
||||||
|
WriteString( extensionName );
|
||||||
|
WriteInt32( extensionVersion );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void MakeCustomBlockSupportLevel( byte version ) {
|
||||||
|
WriteUInt8( (byte)PacketId.CpeCustomBlockSupportLevel );
|
||||||
|
WriteUInt8( version );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void MakePlayerClick( byte button, bool buttonDown, float yaw, float pitch, byte targetEntity,
|
||||||
|
Vector3I targetPos, CpeBlockFace targetFace ) {
|
||||||
|
WriteUInt8( (byte)PacketId.CpePlayerClick );
|
||||||
|
WriteUInt8( button );
|
||||||
|
WriteUInt8( buttonDown ? (byte)0 : (byte)1 );
|
||||||
|
WriteInt16( (short)Utils.DegreesToPacked( yaw, 65536 ) );
|
||||||
|
WriteInt16( (short)Utils.DegreesToPacked( pitch, 65536 ) );
|
||||||
|
WriteUInt8( targetEntity );
|
||||||
|
WriteInt16( (short)targetPos.X );
|
||||||
|
WriteInt16( (short)targetPos.Y );
|
||||||
|
WriteInt16( (short)targetPos.Z );
|
||||||
|
WriteUInt8( (byte)targetFace );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region Reading
|
||||||
|
|
||||||
|
int cpeServerExtensionsCount;
|
||||||
|
bool sendHeldBlock, useMessageTypes, usingTexturePack;
|
||||||
|
static string[] clientExtensions = {
|
||||||
|
"EmoteFix", "ClickDistance", "HeldBlock", "BlockPermissions",
|
||||||
|
"SelectionCuboid", "MessageTypes", "CustomBlocks", "EnvColors",
|
||||||
|
"HackControl", "EnvMapAppearance", "ExtPlayerList", "ChangeModel",
|
||||||
|
"EnvWeatherType", "PlayerClick", // NOTE: There are no plans to support TextHotKey.
|
||||||
|
};
|
||||||
|
|
||||||
|
void HandleCpeExtInfo() {
|
||||||
|
string appName = reader.ReadAsciiString();
|
||||||
|
Utils.LogDebug( "Server identified itself as: " + appName );
|
||||||
|
cpeServerExtensionsCount = reader.ReadInt16();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleCpeExtEntry() {
|
||||||
|
string extName = reader.ReadAsciiString();
|
||||||
|
int extVersion = reader.ReadInt32();
|
||||||
|
Utils.LogDebug( "cpe ext: " + extName + " , " + extVersion );
|
||||||
|
|
||||||
|
if( extName == "HeldBlock" ) {
|
||||||
|
sendHeldBlock = true;
|
||||||
|
} else if( extName == "MessageTypes" ) {
|
||||||
|
useMessageTypes = true;
|
||||||
|
} else if( extName == "ExtPlayerList" ) {
|
||||||
|
UsingExtPlayerList = true;
|
||||||
|
} else if( extName == "PlayerClick" ) {
|
||||||
|
UsingPlayerClick = true;
|
||||||
|
} else if( extName == "EnvMapAppearance" && extVersion == 2 ) {
|
||||||
|
usingTexturePack = true;
|
||||||
|
}
|
||||||
|
cpeServerExtensionsCount--;
|
||||||
|
|
||||||
|
if( cpeServerExtensionsCount == 0 ) {
|
||||||
|
MakeExtInfo( Utils.AppName, clientExtensions.Length );
|
||||||
|
SendPacket();
|
||||||
|
for( int i = 0; i < clientExtensions.Length; i++ ) {
|
||||||
|
string name = clientExtensions[i];
|
||||||
|
int version = (name == "ExtPlayerList" || name == "EnvMapApperance") ? 2 : 1;
|
||||||
|
MakeExtEntry( name, version );
|
||||||
|
SendPacket();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleCpeSetClickDistance() {
|
||||||
|
game.LocalPlayer.ReachDistance = reader.ReadInt16() / 32f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleCpeCustomBlockSupportLevel() {
|
||||||
|
byte supportLevel = reader.ReadUInt8();
|
||||||
|
MakeCustomBlockSupportLevel( 1 );
|
||||||
|
SendPacket();
|
||||||
|
|
||||||
|
if( supportLevel == 1 ) {
|
||||||
|
for( int i = (int)Block.CobblestoneSlab; i <= (int)Block.StoneBrick; i++ ) {
|
||||||
|
game.Inventory.CanPlace[i] = true;
|
||||||
|
game.Inventory.CanDelete[i] = true;
|
||||||
|
}
|
||||||
|
game.Events.RaiseBlockPermissionsChanged();
|
||||||
|
} else {
|
||||||
|
Utils.LogWarning( "Server's block support level is {0}, this client only supports level 1.", supportLevel );
|
||||||
|
Utils.LogWarning( "You won't be able to see or use blocks from levels above level 1" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleCpeHoldThis() {
|
||||||
|
byte blockType = reader.ReadUInt8();
|
||||||
|
bool canChange = reader.ReadUInt8() == 0;
|
||||||
|
game.Inventory.CanChangeHeldBlock = true;
|
||||||
|
game.Inventory.HeldBlock = (Block)blockType;
|
||||||
|
game.Inventory.CanChangeHeldBlock = canChange;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleCpeExtAddPlayerName() {
|
||||||
|
short nameId = reader.ReadInt16();
|
||||||
|
string playerName = Utils.StripColours( reader.ReadAsciiString() );
|
||||||
|
string listName = reader.ReadAsciiString();
|
||||||
|
string groupName = reader.ReadAsciiString();
|
||||||
|
byte groupRank = reader.ReadUInt8();
|
||||||
|
|
||||||
|
if( nameId >= 0 && nameId <= 255 ) {
|
||||||
|
CpeListInfo oldInfo = game.CpePlayersList[nameId];
|
||||||
|
CpeListInfo info = new CpeListInfo( (byte)nameId, playerName, listName, groupName, groupRank );
|
||||||
|
game.CpePlayersList[nameId] = info;
|
||||||
|
|
||||||
|
if( oldInfo != null ) {
|
||||||
|
game.Events.RaiseCpeListInfoChanged( (byte)nameId );
|
||||||
|
} else {
|
||||||
|
game.Events.RaiseCpeListInfoAdded( (byte)nameId );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleCpeExtAddEntity() {
|
||||||
|
byte entityId = reader.ReadUInt8();
|
||||||
|
string displayName = reader.ReadAsciiString();
|
||||||
|
string skinName = reader.ReadAsciiString();
|
||||||
|
AddEntity( entityId, displayName, skinName, false );
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleCpeExtRemovePlayerName() {
|
||||||
|
short nameId = reader.ReadInt16();
|
||||||
|
if( nameId >= 0 && nameId <= 255 ) {
|
||||||
|
game.Events.RaiseCpeListInfoRemoved( (byte)nameId );
|
||||||
|
game.CpePlayersList[nameId] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleCpeMakeSelection() {
|
||||||
|
byte selectionId = reader.ReadUInt8();
|
||||||
|
string label = reader.ReadAsciiString();
|
||||||
|
short startX = reader.ReadInt16();
|
||||||
|
short startY = reader.ReadInt16();
|
||||||
|
short startZ = reader.ReadInt16();
|
||||||
|
short endX = reader.ReadInt16();
|
||||||
|
short endY = reader.ReadInt16();
|
||||||
|
short endZ = reader.ReadInt16();
|
||||||
|
|
||||||
|
byte r = (byte)reader.ReadInt16();
|
||||||
|
byte g = (byte)reader.ReadInt16();
|
||||||
|
byte b = (byte)reader.ReadInt16();
|
||||||
|
byte a = (byte)reader.ReadInt16();
|
||||||
|
|
||||||
|
Vector3I p1 = Vector3I.Min( startX, startY, startZ, endX, endY, endZ );
|
||||||
|
Vector3I p2 = Vector3I.Max( startX, startY, startZ, endX, endY, endZ );
|
||||||
|
FastColour col = new FastColour( r, g, b, a );
|
||||||
|
game.SelectionManager.AddSelection( selectionId, p1, p2, col );
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleCpeRemoveSelection() {
|
||||||
|
byte selectionId = reader.ReadUInt8();
|
||||||
|
game.SelectionManager.RemoveSelection( selectionId );
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleCpeEnvColours() {
|
||||||
|
byte variable = reader.ReadUInt8();
|
||||||
|
short red = reader.ReadInt16();
|
||||||
|
short green = reader.ReadInt16();
|
||||||
|
short blue = reader.ReadInt16();
|
||||||
|
bool invalid = red < 0 || red > 255 || green < 0 || green > 255 || blue < 0 || blue > 255;
|
||||||
|
FastColour col = new FastColour( red, green, blue );
|
||||||
|
|
||||||
|
if( variable == 0 ) { // sky colour
|
||||||
|
game.Map.SetSkyColour( invalid ? Map.DefaultSkyColour : col );
|
||||||
|
} else if( variable == 1 ) { // clouds colour
|
||||||
|
game.Map.SetCloudsColour( invalid ? Map.DefaultCloudsColour : col );
|
||||||
|
} else if( variable == 2 ) { // fog colour
|
||||||
|
game.Map.SetFogColour( invalid ? Map.DefaultFogColour : col );
|
||||||
|
} else if( variable == 3 ) { // ambient light (shadow light)
|
||||||
|
game.Map.SetShadowlight( invalid ? Map.DefaultShadowlight : col );
|
||||||
|
} else if( variable == 4 ) { // diffuse light (sun light)
|
||||||
|
game.Map.SetSunlight( invalid ? Map.DefaultSunlight : col );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleCpeSetBlockPermission() {
|
||||||
|
byte blockId = reader.ReadUInt8();
|
||||||
|
bool canPlace = reader.ReadUInt8() != 0;
|
||||||
|
bool canDelete = reader.ReadUInt8() != 0;
|
||||||
|
Inventory inv = game.Inventory;
|
||||||
|
|
||||||
|
if( blockId == 0 ) {
|
||||||
|
for( int i = 1; i < BlockInfo.CpeBlocksCount; i++ ) {
|
||||||
|
inv.CanPlace.SetNotOverridable( canPlace, i );
|
||||||
|
inv.CanDelete.SetNotOverridable( canDelete, i );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
inv.CanPlace.SetNotOverridable( canPlace, blockId );
|
||||||
|
inv.CanDelete.SetNotOverridable( canDelete, blockId );
|
||||||
|
}
|
||||||
|
game.Events.RaiseBlockPermissionsChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleCpeChangeModel() {
|
||||||
|
byte playerId = reader.ReadUInt8();
|
||||||
|
string modelName = reader.ReadAsciiString().ToLowerInvariant();
|
||||||
|
Player player = game.Players[playerId];
|
||||||
|
if( player != null ) {
|
||||||
|
player.SetModel( modelName );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleCpeEnvSetMapApperance() {
|
||||||
|
string url = reader.ReadAsciiString();
|
||||||
|
byte sideBlock = reader.ReadUInt8();
|
||||||
|
byte edgeBlock = reader.ReadUInt8();
|
||||||
|
short waterLevel = reader.ReadInt16();
|
||||||
|
game.Map.SetWaterLevel( waterLevel );
|
||||||
|
game.Map.SetEdgeBlock( (Block)edgeBlock );
|
||||||
|
game.Map.SetSidesBlock( (Block)sideBlock );
|
||||||
|
|
||||||
|
if( url == String.Empty ) {
|
||||||
|
TexturePackExtractor extractor = new TexturePackExtractor();
|
||||||
|
extractor.Extract( game.defaultTexPack, game );
|
||||||
|
} else {
|
||||||
|
game.Animations.Dispose();
|
||||||
|
if( usingTexturePack )
|
||||||
|
game.AsyncDownloader.DownloadData( url, true, "texturePack" );
|
||||||
|
else
|
||||||
|
game.AsyncDownloader.DownloadImage( url, true, "terrain" );
|
||||||
|
|
||||||
|
}
|
||||||
|
Utils.LogDebug( "Image url: " + url );
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleCpeEnvWeatherType() {
|
||||||
|
game.Map.SetWeather( (Weather)reader.ReadUInt8() );
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleCpeHackControl() {
|
||||||
|
game.LocalPlayer.CanFly = reader.ReadUInt8() != 0;
|
||||||
|
game.LocalPlayer.CanNoclip = reader.ReadUInt8() != 0;
|
||||||
|
game.LocalPlayer.CanSpeed = reader.ReadUInt8() != 0;
|
||||||
|
game.LocalPlayer.CanRespawn = reader.ReadUInt8() != 0;
|
||||||
|
game.CanUseThirdPersonCamera = reader.ReadUInt8() != 0;
|
||||||
|
|
||||||
|
if( !game.CanUseThirdPersonCamera ) {
|
||||||
|
game.SetCamera( false );
|
||||||
|
}
|
||||||
|
float jumpHeight = reader.ReadInt16() / 32f;
|
||||||
|
if( jumpHeight < 0 ) jumpHeight = 1.4f;
|
||||||
|
game.LocalPlayer.CalculateJumpVelocity( jumpHeight );
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleCpeExtAddEntity2() {
|
||||||
|
byte entityId = reader.ReadUInt8();
|
||||||
|
string displayName = reader.ReadAsciiString();
|
||||||
|
string skinName = reader.ReadAsciiString();
|
||||||
|
AddEntity( entityId, displayName, skinName, true );
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleCpeDefineBlockOrLiquid() {
|
||||||
|
byte block = reader.ReadUInt8();
|
||||||
|
BlockInfo info = game.BlockInfo;
|
||||||
|
info.ResetBlockInfo( block );
|
||||||
|
|
||||||
|
info.Name[block] = reader.ReadAsciiString();
|
||||||
|
info.CollideType[block] = (BlockCollideType)reader.ReadUInt8();
|
||||||
|
// TODO: Liquid collide type not properly supported.
|
||||||
|
info.SpeedMultiplier[block] = (float)Math.Pow( 2, (reader.ReadUInt8() - 128) / 64f );
|
||||||
|
info.SetTop( reader.ReadUInt8(), (Block)block );
|
||||||
|
info.SetSide( reader.ReadUInt8(), (Block)block );
|
||||||
|
info.SetBottom( reader.ReadUInt8(), (Block)block );
|
||||||
|
reader.ReadUInt8(); // opacity hint, but we ignore this.
|
||||||
|
info.BlocksLight[block] = reader.ReadUInt8() == 0;
|
||||||
|
reader.ReadUInt8(); // walk sound, but we ignore this.
|
||||||
|
info.EmitsLight[block] = reader.ReadUInt8() != 0;
|
||||||
|
|
||||||
|
if( lastOpcode == PacketId.CpeDefineBlock ) {
|
||||||
|
byte shape = reader.ReadUInt8();
|
||||||
|
if( shape == 1 ) info.Height[block] = 1;
|
||||||
|
else if( shape == 2 ) info.Height[block] = 0.5f;
|
||||||
|
// TODO: upside down slab not properly supported
|
||||||
|
else if( shape == 3 ) info.Height[block] = 0.5f;
|
||||||
|
else if( shape == 4 ) info.IsSprite[block] = true;
|
||||||
|
|
||||||
|
byte blockDraw = reader.ReadUInt8();
|
||||||
|
if( blockDraw == 0 ) info.IsOpaque[block] = true;
|
||||||
|
else if( blockDraw == 1 ) info.IsTransparent[block] = true;
|
||||||
|
else if( blockDraw == 2 ) info.IsTranslucent[block] = true;
|
||||||
|
else if( blockDraw == 3 ) info.IsTranslucent[block] = true;
|
||||||
|
|
||||||
|
Console.WriteLine( block + " : " + shape + "," + blockDraw );
|
||||||
|
} else {
|
||||||
|
byte fogDensity = reader.ReadUInt8();
|
||||||
|
info.FogDensity[block] = fogDensity == 0 ? 0 : (fogDensity + 1) / 128f;
|
||||||
|
info.FogColour[block] = new FastColour(
|
||||||
|
reader.ReadUInt8(), reader.ReadUInt8(), reader.ReadUInt8() );
|
||||||
|
}
|
||||||
|
info.SetupCullingCache();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleCpeRemoveBlockDefinition() {
|
||||||
|
game.BlockInfo.ResetBlockInfo( reader.ReadUInt8() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
@ -10,6 +10,7 @@ namespace ClassicalSharp {
|
|||||||
|
|
||||||
string womEnvIdentifier = "womenv_0", womTerrainIdentifier = "womterrain_0";
|
string womEnvIdentifier = "womenv_0", womTerrainIdentifier = "womterrain_0";
|
||||||
int womCounter = 0;
|
int womCounter = 0;
|
||||||
|
bool sendWomId = false, sentWomId = false;
|
||||||
|
|
||||||
void CheckForWomEnvironment() {
|
void CheckForWomEnvironment() {
|
||||||
DownloadedItem item;
|
DownloadedItem item;
|
@ -1,17 +1,16 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
#if __MonoCS__
|
|
||||||
using Ionic.Zlib;
|
|
||||||
#else
|
|
||||||
using System.IO.Compression;
|
|
||||||
#endif
|
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using ClassicalSharp.Network;
|
using ClassicalSharp.Network;
|
||||||
using ClassicalSharp.TexturePack;
|
using ClassicalSharp.TexturePack;
|
||||||
using OpenTK;
|
using OpenTK;
|
||||||
using OpenTK.Input;
|
#if __MonoCS__
|
||||||
|
using Ionic.Zlib;
|
||||||
|
#else
|
||||||
|
using System.IO.Compression;
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace ClassicalSharp {
|
namespace ClassicalSharp {
|
||||||
|
|
||||||
@ -19,6 +18,7 @@ namespace ClassicalSharp {
|
|||||||
|
|
||||||
public NetworkProcessor( Game window ) {
|
public NetworkProcessor( Game window ) {
|
||||||
game = window;
|
game = window;
|
||||||
|
SetupHandlers();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool IsSinglePlayer {
|
public override bool IsSinglePlayer {
|
||||||
@ -28,9 +28,6 @@ namespace ClassicalSharp {
|
|||||||
Socket socket;
|
Socket socket;
|
||||||
NetworkStream stream;
|
NetworkStream stream;
|
||||||
Game game;
|
Game game;
|
||||||
bool sendHeldBlock;
|
|
||||||
bool useMessageTypes;
|
|
||||||
bool usingTexturePack;
|
|
||||||
bool receivedFirstPosition;
|
bool receivedFirstPosition;
|
||||||
|
|
||||||
public override void Connect( IPAddress address, int port ) {
|
public override void Connect( IPAddress address, int port ) {
|
||||||
@ -69,12 +66,6 @@ namespace ClassicalSharp {
|
|||||||
SendPacket();
|
SendPacket();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void SendPlayerClick( MouseButton button, bool buttonDown, byte targetId, PickedPos pos ) {
|
|
||||||
Player p = game.LocalPlayer;
|
|
||||||
MakePlayerClick( (byte)button, buttonDown, p.YawDegrees, p.PitchDegrees, targetId,
|
|
||||||
pos.BlockPos, pos.BlockFace );
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Dispose() {
|
public override void Dispose() {
|
||||||
socket.Close();
|
socket.Close();
|
||||||
Disconnected = true;
|
Disconnected = true;
|
||||||
@ -131,13 +122,6 @@ namespace ClassicalSharp {
|
|||||||
8, 86, 2, 4, 66, 69, 2, 8, 138, 0, 77, 79, 2,
|
8, 86, 2, 4, 66, 69, 2, 8, 138, 0, 77, 79, 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
static string[] clientExtensions = {
|
|
||||||
"EmoteFix", "ClickDistance", "HeldBlock", "BlockPermissions",
|
|
||||||
"SelectionCuboid", "MessageTypes", "CustomBlocks", "EnvColors",
|
|
||||||
"HackControl", "EnvMapAppearance", "ExtPlayerList", "ChangeModel",
|
|
||||||
"EnvWeatherType", "PlayerClick", // NOTE: There are no plans to support TextHotKey.
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#region Writing
|
#region Writing
|
||||||
|
|
||||||
@ -176,37 +160,6 @@ namespace ClassicalSharp {
|
|||||||
WriteString( text );
|
WriteString( text );
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void MakeExtInfo( string appName, int extensionsCount ) {
|
|
||||||
WriteUInt8( (byte)PacketId.CpeExtInfo );
|
|
||||||
WriteString( appName );
|
|
||||||
WriteInt16( (short)extensionsCount );
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void MakeExtEntry( string extensionName, int extensionVersion ) {
|
|
||||||
WriteUInt8( (byte)PacketId.CpeExtEntry );
|
|
||||||
WriteString( extensionName );
|
|
||||||
WriteInt32( extensionVersion );
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void MakeCustomBlockSupportLevel( byte version ) {
|
|
||||||
WriteUInt8( (byte)PacketId.CpeCustomBlockSupportLevel );
|
|
||||||
WriteUInt8( version );
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void MakePlayerClick( byte button, bool buttonDown, float yaw, float pitch, byte targetEntity,
|
|
||||||
Vector3I targetPos, CpeBlockFace targetFace ) {
|
|
||||||
WriteUInt8( (byte)PacketId.CpePlayerClick );
|
|
||||||
WriteUInt8( button );
|
|
||||||
WriteUInt8( buttonDown ? (byte)0 : (byte)1 );
|
|
||||||
WriteInt16( (short)Utils.DegreesToPacked( yaw, 65536 ) );
|
|
||||||
WriteInt16( (short)Utils.DegreesToPacked( pitch, 65536 ) );
|
|
||||||
WriteUInt8( targetEntity );
|
|
||||||
WriteInt16( (short)targetPos.X );
|
|
||||||
WriteInt16( (short)targetPos.Y );
|
|
||||||
WriteInt16( (short)targetPos.Z );
|
|
||||||
WriteUInt8( (byte)targetFace );
|
|
||||||
}
|
|
||||||
|
|
||||||
static void WriteString( string value ) {
|
static void WriteString( string value ) {
|
||||||
int count = Math.Min( value.Length, 64 );
|
int count = Math.Min( value.Length, 64 );
|
||||||
for( int i = 0; i < count; i++ ) {
|
for( int i = 0; i < count; i++ ) {
|
||||||
@ -253,37 +206,39 @@ namespace ClassicalSharp {
|
|||||||
|
|
||||||
|
|
||||||
#region Reading
|
#region Reading
|
||||||
|
|
||||||
FastNetReader reader;
|
FastNetReader reader;
|
||||||
int cpeServerExtensionsCount;
|
|
||||||
DateTime receiveStart;
|
DateTime receiveStart;
|
||||||
DeflateStream gzipStream;
|
DeflateStream gzipStream;
|
||||||
GZipHeaderReader gzipHeader;
|
GZipHeaderReader gzipHeader;
|
||||||
int mapSizeIndex, mapIndex;
|
int mapSizeIndex, mapIndex;
|
||||||
byte[] mapSize = new byte[4], map;
|
byte[] mapSize = new byte[4], map;
|
||||||
FixedBufferStream gzippedMap;
|
FixedBufferStream gzippedMap;
|
||||||
bool sendWomId = false, sentWomId = false;
|
|
||||||
PacketId lastOpcode;
|
PacketId lastOpcode;
|
||||||
|
|
||||||
void ReadPacket( byte opcode ) {
|
void ReadPacket( byte opcode ) {
|
||||||
reader.Remove( 1 ); // remove opcode
|
reader.Remove( 1 ); // remove opcode
|
||||||
lastOpcode = (PacketId)opcode;
|
lastOpcode = (PacketId)opcode;
|
||||||
|
Action handler;
|
||||||
|
|
||||||
switch( (PacketId)opcode ) {
|
if( opcode >= maxHandledPacket || (handler = handlers[opcode]) == null)
|
||||||
case PacketId.Handshake:
|
throw new NotImplementedException( "Unsupported packet:" + (PacketId)opcode );
|
||||||
{
|
handler();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleHandshake() {
|
||||||
byte protocolVer = reader.ReadUInt8();
|
byte protocolVer = reader.ReadUInt8();
|
||||||
ServerName = reader.ReadAsciiString();
|
ServerName = reader.ReadAsciiString();
|
||||||
ServerMotd = reader.ReadAsciiString();
|
ServerMotd = reader.ReadAsciiString();
|
||||||
game.LocalPlayer.SetUserType( reader.ReadUInt8() );
|
game.LocalPlayer.SetUserType( reader.ReadUInt8() );
|
||||||
receivedFirstPosition = false;
|
receivedFirstPosition = false;
|
||||||
game.LocalPlayer.ParseHackFlags( ServerName, ServerMotd );
|
game.LocalPlayer.ParseHackFlags( ServerName, ServerMotd );
|
||||||
} break;
|
}
|
||||||
|
|
||||||
case PacketId.Ping:
|
void HandlePing() {
|
||||||
break;
|
}
|
||||||
|
|
||||||
case PacketId.LevelInitialise:
|
void HandleLevelInit() {
|
||||||
{
|
|
||||||
game.Map.Reset();
|
game.Map.Reset();
|
||||||
game.SetNewScreen( new LoadingMapScreen( game, ServerName, ServerMotd ) );
|
game.SetNewScreen( new LoadingMapScreen( game, ServerName, ServerMotd ) );
|
||||||
if( ServerMotd.Contains( "cfg=" ) ) {
|
if( ServerMotd.Contains( "cfg=" ) ) {
|
||||||
@ -304,13 +259,13 @@ namespace ClassicalSharp {
|
|||||||
Utils.LogWarning( "You will likely experience an 'Internal error (no progress possible) ReadInternal' exception when decompressing the map." );
|
Utils.LogWarning( "You will likely experience an 'Internal error (no progress possible) ReadInternal' exception when decompressing the map." );
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mapSizeIndex = 0;
|
mapSizeIndex = 0;
|
||||||
mapIndex = 0;
|
mapIndex = 0;
|
||||||
receiveStart = DateTime.UtcNow;
|
receiveStart = DateTime.UtcNow;
|
||||||
} break;
|
}
|
||||||
|
|
||||||
case PacketId.LevelDataChunk:
|
void HandleLevelDataChunk() {
|
||||||
{
|
|
||||||
int usedLength = reader.ReadInt16();
|
int usedLength = reader.ReadInt16();
|
||||||
gzippedMap.Position = 0;
|
gzippedMap.Position = 0;
|
||||||
gzippedMap.SetLength( usedLength );
|
gzippedMap.SetLength( usedLength );
|
||||||
@ -328,13 +283,13 @@ namespace ClassicalSharp {
|
|||||||
mapIndex += gzipStream.Read( map, mapIndex, map.Length - mapIndex );
|
mapIndex += gzipStream.Read( map, mapIndex, map.Length - mapIndex );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
reader.Remove( 1024 );
|
reader.Remove( 1024 );
|
||||||
byte progress = reader.ReadUInt8();
|
byte progress = reader.ReadUInt8();
|
||||||
game.Events.RaiseMapLoading( progress );
|
game.Events.RaiseMapLoading( progress );
|
||||||
} break;
|
}
|
||||||
|
|
||||||
case PacketId.LevelFinalise:
|
void HandleLevelFinalise() {
|
||||||
{
|
|
||||||
game.SetNewScreen( new NormalScreen( game ) );
|
game.SetNewScreen( new NormalScreen( game ) );
|
||||||
int mapWidth = reader.ReadInt16();
|
int mapWidth = reader.ReadInt16();
|
||||||
int mapHeight = reader.ReadInt16();
|
int mapHeight = reader.ReadInt16();
|
||||||
@ -344,6 +299,7 @@ namespace ClassicalSharp {
|
|||||||
Utils.LogDebug( "map loading took:" + loadingMs );
|
Utils.LogDebug( "map loading took:" + loadingMs );
|
||||||
game.Map.UseRawMap( map, mapWidth, mapHeight, mapLength );
|
game.Map.UseRawMap( map, mapWidth, mapHeight, mapLength );
|
||||||
game.Events.RaiseOnNewMapLoaded();
|
game.Events.RaiseOnNewMapLoaded();
|
||||||
|
|
||||||
map = null;
|
map = null;
|
||||||
gzipStream.Dispose();
|
gzipStream.Dispose();
|
||||||
if( sendWomId && !sentWomId ) {
|
if( sendWomId && !sentWomId ) {
|
||||||
@ -351,11 +307,10 @@ namespace ClassicalSharp {
|
|||||||
sentWomId = true;
|
sentWomId = true;
|
||||||
}
|
}
|
||||||
gzipStream = null;
|
gzipStream = null;
|
||||||
GC.Collect( 0 );
|
GC.Collect();
|
||||||
} break;
|
}
|
||||||
|
|
||||||
case PacketId.SetBlock:
|
void HandleSetBlock() {
|
||||||
{
|
|
||||||
int x = reader.ReadInt16();
|
int x = reader.ReadInt16();
|
||||||
int y = reader.ReadInt16();
|
int y = reader.ReadInt16();
|
||||||
int z = reader.ReadInt16();
|
int z = reader.ReadInt16();
|
||||||
@ -367,35 +322,51 @@ namespace ClassicalSharp {
|
|||||||
Utils.LogWarning( "Server tried to update a block at an invalid position!" );
|
Utils.LogWarning( "Server tried to update a block at an invalid position!" );
|
||||||
else
|
else
|
||||||
game.UpdateBlock( x, y, z, type );
|
game.UpdateBlock( x, y, z, type );
|
||||||
} break;
|
}
|
||||||
|
|
||||||
case PacketId.AddEntity:
|
void HandleAddEntity() {
|
||||||
{
|
|
||||||
byte entityId = reader.ReadUInt8();
|
byte entityId = reader.ReadUInt8();
|
||||||
string name = reader.ReadAsciiString();
|
string name = reader.ReadAsciiString();
|
||||||
AddEntity( entityId, name, name, true );
|
AddEntity( entityId, name, name, true );
|
||||||
} break;
|
}
|
||||||
|
|
||||||
case PacketId.EntityTeleport:
|
void HandleEntityTeleport() {
|
||||||
{
|
|
||||||
byte entityId = reader.ReadUInt8();
|
byte entityId = reader.ReadUInt8();
|
||||||
ReadAbsoluteLocation( entityId, true );
|
ReadAbsoluteLocation( entityId, true );
|
||||||
} break;
|
}
|
||||||
|
|
||||||
case PacketId.RelPosAndOrientationUpdate:
|
void HandleRelPosAndOrientationUpdate() {
|
||||||
ReadRelativeLocation();
|
byte playerId = reader.ReadUInt8();
|
||||||
break;
|
float x = reader.ReadInt8() / 32f;
|
||||||
|
float y = reader.ReadInt8() / 32f;
|
||||||
|
float z = reader.ReadInt8() / 32f;
|
||||||
|
|
||||||
case PacketId.RelPosUpdate:
|
float yaw = (float)Utils.PackedToDegrees( reader.ReadUInt8() );
|
||||||
ReadRelativePosition();
|
float pitch = (float)Utils.PackedToDegrees( reader.ReadUInt8() );
|
||||||
break;
|
LocationUpdate update = LocationUpdate.MakePosAndOri( x, y, z, yaw, pitch, true );
|
||||||
|
UpdateLocation( playerId, update, true );
|
||||||
|
}
|
||||||
|
|
||||||
case PacketId.OrientationUpdate:
|
void HandleRelPositionUpdate() {
|
||||||
ReadOrientation();
|
byte playerId = reader.ReadUInt8();
|
||||||
break;
|
float x = reader.ReadInt8() / 32f;
|
||||||
|
float y = reader.ReadInt8() / 32f;
|
||||||
|
float z = reader.ReadInt8() / 32f;
|
||||||
|
|
||||||
case PacketId.RemoveEntity:
|
LocationUpdate update = LocationUpdate.MakePos( x, y, z, true );
|
||||||
{
|
UpdateLocation( playerId, update, true );
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleOrientationUpdate() {
|
||||||
|
byte playerId = reader.ReadUInt8();
|
||||||
|
float yaw = (float)Utils.PackedToDegrees( reader.ReadUInt8() );
|
||||||
|
float pitch = (float)Utils.PackedToDegrees( reader.ReadUInt8() );
|
||||||
|
|
||||||
|
LocationUpdate update = LocationUpdate.MakeOri( yaw, pitch );
|
||||||
|
UpdateLocation( playerId, update, true );
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleRemoveEntity() {
|
||||||
byte entityId = reader.ReadUInt8();
|
byte entityId = reader.ReadUInt8();
|
||||||
Player player = game.Players[entityId];
|
Player player = game.Players[entityId];
|
||||||
if( entityId != 0xFF && player != null ) {
|
if( entityId != 0xFF && player != null ) {
|
||||||
@ -403,313 +374,24 @@ namespace ClassicalSharp {
|
|||||||
player.Despawn();
|
player.Despawn();
|
||||||
game.Players[entityId] = null;
|
game.Players[entityId] = null;
|
||||||
}
|
}
|
||||||
} break;
|
}
|
||||||
|
|
||||||
case PacketId.Message:
|
void HandleMessage() {
|
||||||
{
|
|
||||||
byte messageType = reader.ReadUInt8();
|
byte messageType = reader.ReadUInt8();
|
||||||
string text = reader.ReadChatString( ref messageType, useMessageTypes );
|
string text = reader.ReadChatString( ref messageType, useMessageTypes );
|
||||||
game.Chat.Add( text, (CpeMessage)messageType );
|
game.Chat.Add( text, (CpeMessage)messageType );
|
||||||
} break;
|
}
|
||||||
|
|
||||||
case PacketId.Kick:
|
void HandleKick() {
|
||||||
{
|
|
||||||
string reason = reader.ReadAsciiString();
|
string reason = reader.ReadAsciiString();
|
||||||
game.Disconnect( "&eLost connection to the server", reason );
|
game.Disconnect( "&eLost connection to the server", reason );
|
||||||
Dispose();
|
Dispose();
|
||||||
} break;
|
}
|
||||||
|
|
||||||
case PacketId.SetPermission:
|
void HandleSetPermission() {
|
||||||
{
|
|
||||||
game.LocalPlayer.SetUserType( reader.ReadUInt8() );
|
game.LocalPlayer.SetUserType( reader.ReadUInt8() );
|
||||||
} break;
|
|
||||||
|
|
||||||
case PacketId.CpeExtInfo:
|
|
||||||
{
|
|
||||||
string appName = reader.ReadAsciiString();
|
|
||||||
Utils.LogDebug( "Server identified itself as: " + appName );
|
|
||||||
cpeServerExtensionsCount = reader.ReadInt16();
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case PacketId.CpeExtEntry:
|
|
||||||
{
|
|
||||||
string extName = reader.ReadAsciiString();
|
|
||||||
int extVersion = reader.ReadInt32();
|
|
||||||
Utils.LogDebug( "cpe ext: " + extName + " , " + extVersion );
|
|
||||||
if( extName == "HeldBlock" ) {
|
|
||||||
sendHeldBlock = true;
|
|
||||||
} else if( extName == "MessageTypes" ) {
|
|
||||||
useMessageTypes = true;
|
|
||||||
} else if( extName == "ExtPlayerList" ) {
|
|
||||||
UsingExtPlayerList = true;
|
|
||||||
} else if( extName == "PlayerClick" ) {
|
|
||||||
UsingPlayerClick = true;
|
|
||||||
} else if( extName == "EnvMapAppearance" && extVersion == 2 ) {
|
|
||||||
usingTexturePack = true;
|
|
||||||
}
|
}
|
||||||
cpeServerExtensionsCount--;
|
|
||||||
|
|
||||||
if( cpeServerExtensionsCount == 0 ) {
|
|
||||||
MakeExtInfo( Utils.AppName, clientExtensions.Length );
|
|
||||||
SendPacket();
|
|
||||||
for( int i = 0; i < clientExtensions.Length; i++ ) {
|
|
||||||
string name = clientExtensions[i];
|
|
||||||
int version = (name == "ExtPlayerList" || name == "EnvMapApperance") ? 2 : 1;
|
|
||||||
MakeExtEntry( name, version );
|
|
||||||
SendPacket();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case PacketId.CpeSetClickDistance:
|
|
||||||
{
|
|
||||||
game.LocalPlayer.ReachDistance = reader.ReadInt16() / 32f;
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case PacketId.CpeCustomBlockSupportLevel:
|
|
||||||
{
|
|
||||||
byte supportLevel = reader.ReadUInt8();
|
|
||||||
MakeCustomBlockSupportLevel( 1 );
|
|
||||||
SendPacket();
|
|
||||||
|
|
||||||
if( supportLevel == 1 ) {
|
|
||||||
for( int i = (int)Block.CobblestoneSlab; i <= (int)Block.StoneBrick; i++ ) {
|
|
||||||
game.Inventory.CanPlace[i] = true;
|
|
||||||
game.Inventory.CanDelete[i] = true;
|
|
||||||
}
|
|
||||||
game.Events.RaiseBlockPermissionsChanged();
|
|
||||||
} else {
|
|
||||||
Utils.LogWarning( "Server's block support level is {0}, this client only supports level 1.", supportLevel );
|
|
||||||
Utils.LogWarning( "You won't be able to see or use blocks from levels above level 1" );
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case PacketId.CpeHoldThis:
|
|
||||||
{
|
|
||||||
byte blockType = reader.ReadUInt8();
|
|
||||||
bool canChange = reader.ReadUInt8() == 0;
|
|
||||||
game.Inventory.CanChangeHeldBlock = true;
|
|
||||||
game.Inventory.HeldBlock = (Block)blockType;
|
|
||||||
game.Inventory.CanChangeHeldBlock = canChange;
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case PacketId.CpeExtAddPlayerName:
|
|
||||||
{
|
|
||||||
short nameId = reader.ReadInt16();
|
|
||||||
string playerName = Utils.StripColours( reader.ReadAsciiString() );
|
|
||||||
string listName = reader.ReadAsciiString();
|
|
||||||
string groupName = reader.ReadAsciiString();
|
|
||||||
byte groupRank = reader.ReadUInt8();
|
|
||||||
if( nameId >= 0 && nameId <= 255 ) {
|
|
||||||
CpeListInfo oldInfo = game.CpePlayersList[nameId];
|
|
||||||
CpeListInfo info = new CpeListInfo( (byte)nameId, playerName, listName, groupName, groupRank );
|
|
||||||
game.CpePlayersList[nameId] = info;
|
|
||||||
|
|
||||||
if( oldInfo != null ) {
|
|
||||||
game.Events.RaiseCpeListInfoChanged( (byte)nameId );
|
|
||||||
} else {
|
|
||||||
game.Events.RaiseCpeListInfoAdded( (byte)nameId );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case PacketId.CpeExtAddEntity:
|
|
||||||
{
|
|
||||||
byte entityId = reader.ReadUInt8();
|
|
||||||
string displayName = reader.ReadAsciiString();
|
|
||||||
string skinName = reader.ReadAsciiString();
|
|
||||||
AddEntity( entityId, displayName, skinName, false );
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case PacketId.CpeExtRemovePlayerName:
|
|
||||||
{
|
|
||||||
short nameId = reader.ReadInt16();
|
|
||||||
if( nameId >= 0 && nameId <= 255 ) {
|
|
||||||
game.Events.RaiseCpeListInfoRemoved( (byte)nameId );
|
|
||||||
game.CpePlayersList[nameId] = null;
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case PacketId.CpeMakeSelection:
|
|
||||||
{
|
|
||||||
byte selectionId = reader.ReadUInt8();
|
|
||||||
string label = reader.ReadAsciiString();
|
|
||||||
short startX = reader.ReadInt16();
|
|
||||||
short startY = reader.ReadInt16();
|
|
||||||
short startZ = reader.ReadInt16();
|
|
||||||
short endX = reader.ReadInt16();
|
|
||||||
short endY = reader.ReadInt16();
|
|
||||||
short endZ = reader.ReadInt16();
|
|
||||||
|
|
||||||
byte r = (byte)reader.ReadInt16();
|
|
||||||
byte g = (byte)reader.ReadInt16();
|
|
||||||
byte b = (byte)reader.ReadInt16();
|
|
||||||
byte a = (byte)reader.ReadInt16();
|
|
||||||
|
|
||||||
Vector3I p1 = Vector3I.Min( startX, startY, startZ, endX, endY, endZ );
|
|
||||||
Vector3I p2 = Vector3I.Max( startX, startY, startZ, endX, endY, endZ );
|
|
||||||
FastColour col = new FastColour( r, g, b, a );
|
|
||||||
game.SelectionManager.AddSelection( selectionId, p1, p2, col );
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case PacketId.CpeRemoveSelection:
|
|
||||||
{
|
|
||||||
byte selectionId = reader.ReadUInt8();
|
|
||||||
game.SelectionManager.RemoveSelection( selectionId );
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case PacketId.CpeEnvColours:
|
|
||||||
{
|
|
||||||
byte variable = reader.ReadUInt8();
|
|
||||||
short red = reader.ReadInt16();
|
|
||||||
short green = reader.ReadInt16();
|
|
||||||
short blue = reader.ReadInt16();
|
|
||||||
bool invalid = red < 0 || red > 255 || green < 0 || green > 255 || blue < 0 || blue > 255;
|
|
||||||
FastColour col = new FastColour( red, green, blue );
|
|
||||||
|
|
||||||
if( variable == 0 ) { // sky colour
|
|
||||||
game.Map.SetSkyColour( invalid ? Map.DefaultSkyColour : col );
|
|
||||||
} else if( variable == 1 ) { // clouds colour
|
|
||||||
game.Map.SetCloudsColour( invalid ? Map.DefaultCloudsColour : col );
|
|
||||||
} else if( variable == 2 ) { // fog colour
|
|
||||||
game.Map.SetFogColour( invalid ? Map.DefaultFogColour : col );
|
|
||||||
} else if( variable == 3 ) { // ambient light (shadow light)
|
|
||||||
game.Map.SetShadowlight( invalid ? Map.DefaultShadowlight : col );
|
|
||||||
} else if( variable == 4 ) { // diffuse light (sun light)
|
|
||||||
game.Map.SetSunlight( invalid ? Map.DefaultSunlight : col );
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case PacketId.CpeSetBlockPermission:
|
|
||||||
{
|
|
||||||
byte blockId = reader.ReadUInt8();
|
|
||||||
bool canPlace = reader.ReadUInt8() != 0;
|
|
||||||
bool canDelete = reader.ReadUInt8() != 0;
|
|
||||||
Inventory inv = game.Inventory;
|
|
||||||
|
|
||||||
if( blockId == 0 ) {
|
|
||||||
for( int i = 1; i < BlockInfo.CpeBlocksCount; i++ ) {
|
|
||||||
inv.CanPlace.SetNotOverridable( canPlace, i );
|
|
||||||
inv.CanDelete.SetNotOverridable( canDelete, i );
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
inv.CanPlace.SetNotOverridable( canPlace, blockId );
|
|
||||||
inv.CanDelete.SetNotOverridable( canDelete, blockId );
|
|
||||||
}
|
|
||||||
game.Events.RaiseBlockPermissionsChanged();
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case PacketId.CpeChangeModel:
|
|
||||||
{
|
|
||||||
byte playerId = reader.ReadUInt8();
|
|
||||||
string modelName = reader.ReadAsciiString().ToLowerInvariant();
|
|
||||||
Player player = game.Players[playerId];
|
|
||||||
if( player != null ) {
|
|
||||||
player.SetModel( modelName );
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case PacketId.CpeEnvSetMapApperance:
|
|
||||||
{
|
|
||||||
string url = reader.ReadAsciiString();
|
|
||||||
byte sideBlock = reader.ReadUInt8();
|
|
||||||
byte edgeBlock = reader.ReadUInt8();
|
|
||||||
short waterLevel = reader.ReadInt16();
|
|
||||||
game.Map.SetWaterLevel( waterLevel );
|
|
||||||
game.Map.SetEdgeBlock( (Block)edgeBlock );
|
|
||||||
game.Map.SetSidesBlock( (Block)sideBlock );
|
|
||||||
if( url == String.Empty ) {
|
|
||||||
TexturePackExtractor extractor = new TexturePackExtractor();
|
|
||||||
extractor.Extract( game.defaultTexPack, game );
|
|
||||||
} else {
|
|
||||||
game.Animations.Dispose();
|
|
||||||
if( usingTexturePack )
|
|
||||||
game.AsyncDownloader.DownloadData( url, true, "texturePack" );
|
|
||||||
else
|
|
||||||
game.AsyncDownloader.DownloadImage( url, true, "terrain" );
|
|
||||||
|
|
||||||
}
|
|
||||||
Utils.LogDebug( "Image url: " + url );
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case PacketId.CpeEnvWeatherType:
|
|
||||||
game.Map.SetWeather( (Weather)reader.ReadUInt8() );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PacketId.CpeHackControl:
|
|
||||||
{
|
|
||||||
game.LocalPlayer.CanFly = reader.ReadUInt8() != 0;
|
|
||||||
game.LocalPlayer.CanNoclip = reader.ReadUInt8() != 0;
|
|
||||||
game.LocalPlayer.CanSpeed = reader.ReadUInt8() != 0;
|
|
||||||
game.LocalPlayer.CanRespawn = reader.ReadUInt8() != 0;
|
|
||||||
game.CanUseThirdPersonCamera = reader.ReadUInt8() != 0;
|
|
||||||
if( !game.CanUseThirdPersonCamera ) {
|
|
||||||
game.SetCamera( false );
|
|
||||||
}
|
|
||||||
float jumpHeight = reader.ReadInt16() / 32f;
|
|
||||||
if( jumpHeight < 0 ) jumpHeight = 1.4f;
|
|
||||||
game.LocalPlayer.CalculateJumpVelocity( jumpHeight );
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case PacketId.CpeExtAddEntity2:
|
|
||||||
{
|
|
||||||
byte entityId = reader.ReadUInt8();
|
|
||||||
string displayName = reader.ReadAsciiString();
|
|
||||||
string skinName = reader.ReadAsciiString();
|
|
||||||
AddEntity( entityId, displayName, skinName, true );
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case PacketId.CpeDefineBlock:
|
|
||||||
case PacketId.CpeDefineLiquid:
|
|
||||||
{
|
|
||||||
byte block = reader.ReadUInt8();
|
|
||||||
BlockInfo info = game.BlockInfo;
|
|
||||||
info.ResetBlockInfo( block );
|
|
||||||
|
|
||||||
info.Name[block] = reader.ReadAsciiString();
|
|
||||||
info.CollideType[block] = (BlockCollideType)reader.ReadUInt8();
|
|
||||||
// TODO: Liquid collide type not properly supported.
|
|
||||||
info.SpeedMultiplier[block] = (float)Math.Pow( 2, (reader.ReadUInt8() - 128) / 64f );
|
|
||||||
info.SetTop( reader.ReadUInt8(), (Block)block );
|
|
||||||
info.SetSide( reader.ReadUInt8(), (Block)block );
|
|
||||||
info.SetBottom( reader.ReadUInt8(), (Block)block );
|
|
||||||
reader.ReadUInt8(); // opacity hint, but we ignore this.
|
|
||||||
info.BlocksLight[block] = reader.ReadUInt8() == 0;
|
|
||||||
reader.ReadUInt8(); // walk sound, but we ignore this.
|
|
||||||
info.EmitsLight[block] = reader.ReadUInt8() != 0;
|
|
||||||
|
|
||||||
if( opcode == (byte)PacketId.CpeDefineBlock ) {
|
|
||||||
byte shape = reader.ReadUInt8();
|
|
||||||
if( shape == 1 ) info.Height[block] = 1;
|
|
||||||
else if( shape == 2 ) info.Height[block] = 0.5f;
|
|
||||||
// TODO: upside down slab not properly supported
|
|
||||||
else if( shape == 3 ) info.Height[block] = 0.5f;
|
|
||||||
else if( shape == 4 ) info.IsSprite[block] = true;
|
|
||||||
|
|
||||||
byte blockDraw = reader.ReadUInt8();
|
|
||||||
if( blockDraw == 0 ) info.IsOpaque[block] = true;
|
|
||||||
else if( blockDraw == 1 ) info.IsTransparent[block] = true;
|
|
||||||
else if( blockDraw == 2 ) info.IsTranslucent[block] = true;
|
|
||||||
else if( blockDraw == 3 ) info.IsTranslucent[block] = true;
|
|
||||||
|
|
||||||
Console.WriteLine( block + " : " + shape + "," + blockDraw );
|
|
||||||
} else {
|
|
||||||
byte fogDensity = reader.ReadUInt8();
|
|
||||||
info.FogDensity[block] = fogDensity == 0 ? 0 : (fogDensity + 1) / 128f;
|
|
||||||
info.FogColour[block] = new FastColour(
|
|
||||||
reader.ReadUInt8(), reader.ReadUInt8(), reader.ReadUInt8() );
|
|
||||||
}
|
|
||||||
info.SetupCullingCache();
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case PacketId.CpeRemoveBlockDefinition:
|
|
||||||
game.BlockInfo.ResetBlockInfo( reader.ReadUInt8() );
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new NotImplementedException( "Unsupported packet:" + (PacketId)opcode );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AddEntity( byte entityId, string displayName, string skinName, bool readPosition ) {
|
void AddEntity( byte entityId, string displayName, string skinName, bool readPosition ) {
|
||||||
if( entityId != 0xFF ) {
|
if( entityId != 0xFF ) {
|
||||||
@ -730,38 +412,11 @@ namespace ClassicalSharp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReadRelativeLocation() {
|
|
||||||
byte playerId = reader.ReadUInt8();
|
|
||||||
float x = reader.ReadInt8() / 32f;
|
|
||||||
float y = reader.ReadInt8() / 32f;
|
|
||||||
float z = reader.ReadInt8() / 32f;
|
|
||||||
float yaw = (float)Utils.PackedToDegrees( reader.ReadUInt8() );
|
|
||||||
float pitch = (float)Utils.PackedToDegrees( reader.ReadUInt8() );
|
|
||||||
LocationUpdate update = LocationUpdate.MakePosAndOri( x, y, z, yaw, pitch, true );
|
|
||||||
UpdateLocation( playerId, update, true );
|
|
||||||
}
|
|
||||||
|
|
||||||
void ReadOrientation() {
|
|
||||||
byte playerId = reader.ReadUInt8();
|
|
||||||
float yaw = (float)Utils.PackedToDegrees( reader.ReadUInt8() );
|
|
||||||
float pitch = (float)Utils.PackedToDegrees( reader.ReadUInt8() );
|
|
||||||
LocationUpdate update = LocationUpdate.MakeOri( yaw, pitch );
|
|
||||||
UpdateLocation( playerId, update, true );
|
|
||||||
}
|
|
||||||
|
|
||||||
void ReadRelativePosition() {
|
|
||||||
byte playerId = reader.ReadUInt8();
|
|
||||||
float x = reader.ReadInt8() / 32f;
|
|
||||||
float y = reader.ReadInt8() / 32f;
|
|
||||||
float z = reader.ReadInt8() / 32f;
|
|
||||||
LocationUpdate update = LocationUpdate.MakePos( x, y, z, true );
|
|
||||||
UpdateLocation( playerId, update, true );
|
|
||||||
}
|
|
||||||
|
|
||||||
void ReadAbsoluteLocation( byte playerId, bool interpolate ) {
|
void ReadAbsoluteLocation( byte playerId, bool interpolate ) {
|
||||||
float x = reader.ReadInt16() / 32f;
|
float x = reader.ReadInt16() / 32f;
|
||||||
float y = ( reader.ReadInt16() - 51 ) / 32f; // We have to do this.
|
float y = ( reader.ReadInt16() - 51 ) / 32f; // We have to do this.
|
||||||
if( playerId == 255 ) y += 22/32f;
|
if( playerId == 255 ) y += 22/32f;
|
||||||
|
|
||||||
float z = reader.ReadInt16() / 32f;
|
float z = reader.ReadInt16() / 32f;
|
||||||
float yaw = (float)Utils.PackedToDegrees( reader.ReadUInt8() );
|
float yaw = (float)Utils.PackedToDegrees( reader.ReadUInt8() );
|
||||||
float pitch = (float)Utils.PackedToDegrees( reader.ReadUInt8() );
|
float pitch = (float)Utils.PackedToDegrees( reader.ReadUInt8() );
|
||||||
@ -778,6 +433,29 @@ namespace ClassicalSharp {
|
|||||||
player.SetLocation( update, interpolate );
|
player.SetLocation( update, interpolate );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
Action[] handlers;
|
||||||
|
int maxHandledPacket;
|
||||||
|
|
||||||
|
void SetupHandlers() {
|
||||||
|
maxHandledPacket = (int)PacketId.Max;
|
||||||
|
handlers = new Action[] { HandleHandshake, HandlePing, HandleLevelInit,
|
||||||
|
HandleLevelDataChunk, HandleLevelFinalise, null, HandleSetBlock,
|
||||||
|
HandleAddEntity, HandleEntityTeleport, HandleRelPosAndOrientationUpdate,
|
||||||
|
HandleRelPositionUpdate, HandleOrientationUpdate, HandleRemoveEntity,
|
||||||
|
HandleMessage, HandleKick, HandleSetPermission,
|
||||||
|
|
||||||
|
HandleCpeExtInfo, HandleCpeExtEntry, HandleCpeSetClickDistance,
|
||||||
|
HandleCpeCustomBlockSupportLevel, HandleCpeHoldThis, null,
|
||||||
|
HandleCpeExtAddPlayerName, HandleCpeExtAddEntity, HandleCpeExtRemovePlayerName,
|
||||||
|
HandleCpeEnvColours, HandleCpeMakeSelection, HandleCpeRemoveSelection,
|
||||||
|
HandleCpeSetBlockPermission, HandleCpeChangeModel, HandleCpeEnvSetMapApperance,
|
||||||
|
HandleCpeEnvWeatherType, HandleCpeHackControl, HandleCpeExtAddEntity2,
|
||||||
|
null, HandleCpeDefineBlockOrLiquid, HandleCpeDefineBlockOrLiquid,
|
||||||
|
HandleCpeRemoveBlockDefinition
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -56,6 +56,7 @@ namespace ClassicalSharp {
|
|||||||
result.R = (byte)( value.R * t );
|
result.R = (byte)( value.R * t );
|
||||||
result.G = (byte)( value.G * t );
|
result.G = (byte)( value.G * t );
|
||||||
result.B = (byte)( value.B * t );
|
result.B = (byte)( value.B * t );
|
||||||
|
result.A = 50;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user