Created
September 28, 2018 10:07
-
-
Save HurricanKai/e5f484233652e5728aa67b9cb5538cc7 to your computer and use it in GitHub Desktop.
malformed byte around byte 1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using AutoSerialize; | |
using SM2.Core.BaseTypes; | |
using SM2.Core.Server; | |
using SM2.Dimensions; | |
using System; | |
using System.Collections.Generic; | |
using System.Text; | |
using Microsoft.Extensions.DependencyInjection; | |
using System.Threading.Tasks; | |
using System.IO; | |
using SM2.Blocks; | |
namespace SM2.Packets | |
{ | |
public class ChunkData : Packet | |
{ | |
public override ConnectionState RequiredState { get; } = ConnectionState.Play; | |
public override ConnectionSide WritingSide { get; } = ConnectionSide.Server; | |
public override VarInt Id { get; } = 0x22; | |
[AutoSerialize(0)] | |
public int ChunkX; | |
[AutoSerialize(1)] | |
public int ChunkZ; | |
[AutoSerialize(2)] | |
public bool GroundUpContinous; | |
[AutoSerialize(4)] | |
[NoLength] | |
public byte[] Data; | |
//TODO: Implement NBT Entities | |
const int CHUNK_HEIGHT = Chunk.ChunkSizeY; | |
const int SECTION_HEIGHT = Chunk.SectionHeight; | |
const int SECTION_WIDTH = Chunk.ChunkSizeX; // or ChunkSizeZ it doesnt matter | |
public override async Task PreWrite() | |
{ | |
if (!GroundUpContinous) | |
throw new NotImplementedException("Ouuh, pls no"); | |
var chunkPos = new Vector2(ChunkX, ChunkZ); | |
Console.WriteLine($"Writing ChunkData {ChunkX}, {ChunkZ}"); | |
var uByte = _ctx.Provider.GetService<ITypeAccessor<Byte>>(); | |
var VarInt = _ctx.Provider.GetService<ITypeAccessor<VarInt>>(); | |
var Int = _ctx.Provider.GetService<ITypeAccessor<int>>(); | |
var chunk = _ctx.Player.Dimension.GetChunk(chunkPos); | |
using (var data = new MemoryStream()) | |
{ | |
int mask = 0; | |
using (var columnBuffer = new MemoryStream()) | |
{ | |
for (int sectionY = 0; sectionY < (CHUNK_HEIGHT / SECTION_HEIGHT); sectionY++) | |
{ | |
if (chunk[sectionY].AnyOther<Air>()) | |
{ | |
mask |= (1 << sectionY); // Set that bit to true in the mask | |
WriteChunkSection(chunk[sectionY], columnBuffer); | |
} | |
} | |
if (GroundUpContinous) | |
{ | |
var biomes = new int[256]; | |
for (int z = 0; z < SECTION_WIDTH - 1; z++) | |
{ | |
for (int x = 0; x < SECTION_WIDTH - 1; x++) | |
{ | |
biomes[z * 16 | x] = 127; | |
} | |
} | |
Int.WriteArray(columnBuffer, biomes); | |
} | |
VarInt.Write(data, mask); | |
VarInt.Write(data, (int)columnBuffer.Position); | |
columnBuffer.Position = 0; | |
columnBuffer.CopyTo(data); | |
} | |
// If you don't support block entities yet, use 0 | |
// If you need to implement it by sending block entities later with the update block entity packet, | |
// do it that way and send 0 as well. (Note that 1.10.1 (not 1.10 or 1.10.2) will not accept that) | |
VarInt.Write(data, 0); | |
Data = data.ToArray(); | |
} | |
await base.PreWrite(); | |
} | |
private void WriteChunkSection(ChunkSection section, MemoryStream buf) | |
{ | |
var uByte = _ctx.Provider.GetService<ITypeAccessor<Byte>>(); | |
var VarInt = _ctx.Provider.GetService<ITypeAccessor<VarInt>>(); | |
var Int = _ctx.Provider.GetService<ITypeAccessor<int>>(); | |
var ULong = _ctx.Provider.GetService<ITypeAccessor<ulong>>(); | |
byte bitsPerBlock = 14; | |
uByte.Write(buf, bitsPerBlock); | |
uByte.Write(buf, 9); | |
int dataLength = (16 * 16 * 16) * bitsPerBlock / 64; // See tips section for an explanation of this calculation | |
UInt64[] data = new UInt64[dataLength]; | |
// A bitmask that contains bitsPerBlock set bits | |
uint individualValueMask = (uint)((1 << bitsPerBlock) - 1); | |
for (int y = 0; y < SECTION_HEIGHT - 1; y++) | |
{ | |
for (int z = 0; z < SECTION_WIDTH - 1; z++) | |
{ | |
for (int x = 0; x < SECTION_WIDTH - 1; x++) | |
{ | |
var relPos = new Position(x, y, z); | |
int blockNumber = (((relPos.Y * SECTION_HEIGHT) + relPos.Z) * SECTION_WIDTH) + relPos.X; | |
int startLong = (blockNumber * bitsPerBlock) / 64; | |
int startOffset = (blockNumber * bitsPerBlock) % 64; | |
int endLong = ((blockNumber + 1) * bitsPerBlock - 1) / 64; | |
UInt64 value = (ulong)section[relPos].GetState(); | |
value &= individualValueMask; | |
data[startLong] |= (value << startOffset); | |
if (startLong != endLong) | |
{ | |
data[endLong] = (value >> (64 - startOffset)); | |
} | |
} | |
} | |
} | |
VarInt.Write(buf, dataLength); | |
ULong.WriteArray(buf, data); | |
for (int y = 0; y < SECTION_HEIGHT; y++) | |
{ | |
for (int z = 0; z < SECTION_WIDTH; z++) | |
{ | |
for (int x = 0; x < SECTION_WIDTH; x += 2) | |
{ | |
// Note: x += 2 above; we read 2 values along x each time | |
//byte value = section.GetBlockLight(x, y, z) | (section.GetBlockLight(x + 1, y, z) << 4); | |
byte value = (12) | ((12) << 4); | |
uByte.Write(buf, value); | |
} | |
} | |
} | |
if (/*currentDimension.HasSkylight()*/true) | |
{ // IE, current dimension is overworld / 0 | |
for (int y = 0; y < SECTION_HEIGHT; y++) | |
{ | |
for (int z = 0; z < SECTION_WIDTH; z++) | |
{ | |
for (int x = 0; x < SECTION_WIDTH; x += 2) | |
{ | |
// Note: x += 2 above; we read 2 values along x each time | |
//byte value = section.GetSkyLight(x, y, z) | (section.GetSkyLight(x + 1, y, z) << 4); | |
byte value = (12) | ((12) << 4); | |
uByte.Write(buf, value); | |
} | |
} | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment