mirror of
https://github.com/ClassiCube/MCGalaxy.git
synced 2025-09-25 22:30:52 -04:00
Use BulkBlockUpdate to reduce bandwidth consumption, also create a BulkBlockSender class for future usage elsewhere.
This commit is contained in:
parent
aa85421070
commit
5f0146da3e
@ -1,19 +1,19 @@
|
||||
/*
|
||||
Copyright 2010 MCSharp team (Modified for use with MCZall/MCLawl/MCGalaxy)
|
||||
Copyright 2010 MCSharp team (Modified for use with MCZall/MCLawl/MCGalaxy)
|
||||
|
||||
Dual-licensed under the Educational Community License, Version 2.0 and
|
||||
the GNU General Public License, Version 3 (the "Licenses"); you may
|
||||
not use this file except in compliance with the Licenses. You may
|
||||
obtain a copy of the Licenses at
|
||||
|
||||
http://www.opensource.org/licenses/ecl2.php
|
||||
http://www.gnu.org/licenses/gpl-3.0.html
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the Licenses are distributed on an "AS IS"
|
||||
BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
or implied. See the Licenses for the specific language governing
|
||||
permissions and limitations under the Licenses.
|
||||
Dual-licensed under the Educational Community License, Version 2.0 and
|
||||
the GNU General Public License, Version 3 (the "Licenses"); you may
|
||||
not use this file except in compliance with the Licenses. You may
|
||||
obtain a copy of the Licenses at
|
||||
|
||||
http://www.opensource.org/licenses/ecl2.php
|
||||
http://www.gnu.org/licenses/gpl-3.0.html
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the Licenses are distributed on an "AS IS"
|
||||
BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
or implied. See the Licenses for the specific language governing
|
||||
permissions and limitations under the Licenses.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@ -22,64 +22,64 @@ using MCGalaxy.Commands;
|
||||
|
||||
namespace MCGalaxy
|
||||
{
|
||||
public abstract partial class Command
|
||||
{
|
||||
public abstract string name { get; }
|
||||
public abstract string shortcut { get; }
|
||||
public abstract string type { get; }
|
||||
public abstract bool museumUsable { get; }
|
||||
public abstract LevelPermission defaultRank { get; }
|
||||
public abstract void Use(Player p, string message);
|
||||
public abstract void Help(Player p);
|
||||
public virtual CommandPerm[] AdditionalPerms { get { return null; } }
|
||||
public abstract partial class Command
|
||||
{
|
||||
public abstract string name { get; }
|
||||
public abstract string shortcut { get; }
|
||||
public abstract string type { get; }
|
||||
public abstract bool museumUsable { get; }
|
||||
public abstract LevelPermission defaultRank { get; }
|
||||
public abstract void Use(Player p, string message);
|
||||
public abstract void Help(Player p);
|
||||
public virtual CommandPerm[] AdditionalPerms { get { return null; } }
|
||||
|
||||
public static CommandList all = new CommandList();
|
||||
public static CommandList core = new CommandList();
|
||||
|
||||
public static void InitAll() {
|
||||
public static CommandList all = new CommandList();
|
||||
public static CommandList core = new CommandList();
|
||||
|
||||
public static void InitAll() {
|
||||
all.AddOtherPerms = true;
|
||||
Type[] types = Assembly.GetExecutingAssembly().GetTypes();
|
||||
for (int i = 0; i < types.Length; i++) {
|
||||
Type type = types[i];
|
||||
if (!type.IsSubclassOf(typeof(Command)) || type.IsAbstract) continue;
|
||||
all.Add((Command)Activator.CreateInstance(type));
|
||||
Type type = types[i];
|
||||
if (!type.IsSubclassOf(typeof(Command)) || type.IsAbstract) continue;
|
||||
all.Add((Command)Activator.CreateInstance(type));
|
||||
}
|
||||
core.commands = new List<Command>(all.commands);
|
||||
Scripting.Autoload();
|
||||
}
|
||||
|
||||
protected static void RevertAndClearState(Player p, ushort x, ushort y, ushort z) {
|
||||
p.ClearBlockchange();
|
||||
p.RevertBlock(x, y, z);
|
||||
}
|
||||
|
||||
protected void MessageInGameOnly(Player p) {
|
||||
Player.SendMessage(p, "/" + name + " can only be used in-game.");
|
||||
}
|
||||
}
|
||||
|
||||
public struct CommandPerm {
|
||||
public LevelPermission Perm;
|
||||
public string Description;
|
||||
public int Number;
|
||||
|
||||
public CommandPerm(LevelPermission perm, string desc) {
|
||||
Perm = perm; Description = desc; Number = 1;
|
||||
}
|
||||
|
||||
public CommandPerm(LevelPermission perm, string desc, int num) {
|
||||
Perm = perm; Description = desc; Number = num;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class CommandTypes {
|
||||
public const string Building = "build";
|
||||
public const string Chat = "chat";
|
||||
public const string Economy = "economy";
|
||||
public const string Games = "game";
|
||||
public const string Information = "information";
|
||||
public const string Moderation = "mod";
|
||||
public const string Other = "other";
|
||||
public const string World = "world";
|
||||
}
|
||||
|
||||
protected static void RevertAndClearState(Player p, ushort x, ushort y, ushort z) {
|
||||
p.ClearBlockchange();
|
||||
p.RevertBlock(x, y, z);
|
||||
}
|
||||
|
||||
protected void MessageInGameOnly(Player p) {
|
||||
Player.SendMessage(p, "/" + name + " can only be used in-game.");
|
||||
}
|
||||
}
|
||||
|
||||
public struct CommandPerm {
|
||||
public LevelPermission Perm;
|
||||
public string Description;
|
||||
public int Number;
|
||||
|
||||
public CommandPerm(LevelPermission perm, string desc) {
|
||||
Perm = perm; Description = desc; Number = 1;
|
||||
}
|
||||
|
||||
public CommandPerm(LevelPermission perm, string desc, int num) {
|
||||
Perm = perm; Description = desc; Number = num;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class CommandTypes {
|
||||
public const string Building = "build";
|
||||
public const string Chat = "chat";
|
||||
public const string Economy = "economy";
|
||||
public const string Games = "game";
|
||||
public const string Information = "information";
|
||||
public const string Moderation = "mod";
|
||||
public const string Other = "other";
|
||||
public const string World = "world";
|
||||
}
|
||||
}
|
||||
|
@ -1,19 +1,19 @@
|
||||
/*
|
||||
Copyright 2010 MCSharp team (Modified for use with MCZall/MCLawl/MCGalaxy)
|
||||
|
||||
Dual-licensed under the Educational Community License, Version 2.0 and
|
||||
the GNU General Public License, Version 3 (the "Licenses"); you may
|
||||
not use this file except in compliance with the Licenses. You may
|
||||
obtain a copy of the Licenses at
|
||||
|
||||
http://www.opensource.org/licenses/ecl2.php
|
||||
http://www.gnu.org/licenses/gpl-3.0.html
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the Licenses are distributed on an "AS IS"
|
||||
BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
or implied. See the Licenses for the specific language governing
|
||||
permissions and limitations under the Licenses.
|
||||
Copyright 2010 MCSharp team (Modified for use with MCZall/MCLawl/MCGalaxy)
|
||||
|
||||
Dual-licensed under the Educational Community License, Version 2.0 and
|
||||
the GNU General Public License, Version 3 (the "Licenses"); you may
|
||||
not use this file except in compliance with the Licenses. You may
|
||||
obtain a copy of the Licenses at
|
||||
|
||||
http://www.opensource.org/licenses/ecl2.php
|
||||
http://www.gnu.org/licenses/gpl-3.0.html
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the Licenses are distributed on an "AS IS"
|
||||
BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
or implied. See the Licenses for the specific language governing
|
||||
permissions and limitations under the Licenses.
|
||||
*/
|
||||
using System;
|
||||
using System.Data;
|
||||
@ -24,7 +24,7 @@ namespace MCGalaxy.Commands
|
||||
{
|
||||
public override string name { get { return "unbanip"; } }
|
||||
public override string shortcut { get { return ""; } }
|
||||
public override string type { get { return CommandTypes.Moderation; } }
|
||||
public override string type { get { return CommandTypes.Moderation; } }
|
||||
public override bool museumUsable { get { return true; } }
|
||||
public override LevelPermission defaultRank { get { return LevelPermission.Operator; } }
|
||||
public CmdUnbanip() { }
|
||||
@ -37,7 +37,7 @@ namespace MCGalaxy.Commands
|
||||
message = message.Remove(0, 1).Trim();
|
||||
Player who = PlayerInfo.Find(message);
|
||||
if (who == null) {
|
||||
DatabaseParameterisedQuery query = DatabaseParameterisedQuery.Create();
|
||||
DatabaseParameterisedQuery query = DatabaseParameterisedQuery.Create();
|
||||
query.AddParam("@Name", message);
|
||||
DataTable ip = Database.fillData(query, "SELECT IP FROM Players WHERE Name = @Name");
|
||||
if (ip.Rows.Count > 0) {
|
||||
|
@ -407,7 +407,7 @@ namespace MCGalaxy.Commands {
|
||||
static void ReloadMap(Player p, bool global) {
|
||||
Player[] players = PlayerInfo.Online;
|
||||
foreach (Player pl in players) {
|
||||
if (!pl.HasCpeExt(CpeExt.BlockDefinitions)) continue;
|
||||
if (!pl.hasBlockDefs) continue;
|
||||
if (!global && p.level != pl.level) continue;
|
||||
if (pl.level == null || !pl.level.HasCustomBlocks) continue;
|
||||
|
||||
|
@ -1,19 +1,19 @@
|
||||
/*
|
||||
Copyright 2011 MCForge
|
||||
|
||||
Dual-licensed under the Educational Community License, Version 2.0 and
|
||||
the GNU General Public License, Version 3 (the "Licenses"); you may
|
||||
not use this file except in compliance with the Licenses. You may
|
||||
obtain a copy of the Licenses at
|
||||
|
||||
http://www.opensource.org/licenses/ecl2.php
|
||||
http://www.gnu.org/licenses/gpl-3.0.html
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the Licenses are distributed on an "AS IS"
|
||||
BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
or implied. See the Licenses for the specific language governing
|
||||
permissions and limitations under the Licenses.
|
||||
Copyright 2011 MCForge
|
||||
|
||||
Dual-licensed under the Educational Community License, Version 2.0 and
|
||||
the GNU General Public License, Version 3 (the "Licenses"); you may
|
||||
not use this file except in compliance with the Licenses. You may
|
||||
obtain a copy of the Licenses at
|
||||
|
||||
http://www.opensource.org/licenses/ecl2.php
|
||||
http://www.gnu.org/licenses/gpl-3.0.html
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the Licenses are distributed on an "AS IS"
|
||||
BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
or implied. See the Licenses for the specific language governing
|
||||
permissions and limitations under the Licenses.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@ -237,19 +237,19 @@ namespace MCGalaxy
|
||||
|
||||
public static void executeQuery(string queryString, bool createDB = false) {
|
||||
if (Server.useMySQL) executeQuery(MySQL.query, queryString, createDB);
|
||||
else executeQuery(SQLite.query, queryString, createDB);
|
||||
else executeQuery(SQLite.query, queryString, createDB);
|
||||
}
|
||||
|
||||
public static void executeQuery(DatabaseParameterisedQuery query, string queryString, bool createDB = false) {
|
||||
Exception e = null;
|
||||
for (int i = 0; i < 10; i++) {
|
||||
try {
|
||||
query.Execute(queryString, createDB);
|
||||
query.ClearParams();
|
||||
return;
|
||||
} catch (Exception ex) {
|
||||
e = ex; // try yet again
|
||||
}
|
||||
try {
|
||||
query.Execute(queryString, createDB);
|
||||
query.ClearParams();
|
||||
return;
|
||||
} catch (Exception ex) {
|
||||
e = ex; // try yet again
|
||||
}
|
||||
}
|
||||
|
||||
File.AppendAllText("MySQL_error.log", DateTime.Now + " " + queryString + "\r\n");
|
||||
@ -258,29 +258,29 @@ namespace MCGalaxy
|
||||
}
|
||||
|
||||
public static DataTable fillData(string queryString, bool skipError = false) {
|
||||
if (Server.useMySQL) return fillData(MySQL.query, queryString, skipError);
|
||||
else return fillData(SQLite.query, queryString, skipError);
|
||||
if (Server.useMySQL) return fillData(MySQL.query, queryString, skipError);
|
||||
else return fillData(SQLite.query, queryString, skipError);
|
||||
}
|
||||
|
||||
public static DataTable fillData(DatabaseParameterisedQuery query, string queryString, bool skipError = false) {
|
||||
using (DataTable results = new DataTable("toReturn")) {
|
||||
Exception e = null;
|
||||
for (int i = 0; i < 10; i++) {
|
||||
try {
|
||||
query.Fill(queryString, results);
|
||||
query.ClearParams();
|
||||
return results;
|
||||
} catch (Exception ex) {
|
||||
e = ex; // try yet again
|
||||
}
|
||||
}
|
||||
|
||||
if (skipError) return results;
|
||||
File.AppendAllText("MySQL_error.log", DateTime.Now + " " + queryString + "\r\n");
|
||||
Server.ErrorLog(e);
|
||||
query.ClearParams();
|
||||
return results;
|
||||
}
|
||||
using (DataTable results = new DataTable("toReturn")) {
|
||||
Exception e = null;
|
||||
for (int i = 0; i < 10; i++) {
|
||||
try {
|
||||
query.Fill(queryString, results);
|
||||
query.ClearParams();
|
||||
return results;
|
||||
} catch (Exception ex) {
|
||||
e = ex; // try yet again
|
||||
}
|
||||
}
|
||||
|
||||
if (skipError) return results;
|
||||
File.AppendAllText("MySQL_error.log", DateTime.Now + " " + queryString + "\r\n");
|
||||
Server.ErrorLog(e);
|
||||
query.ClearParams();
|
||||
return results;
|
||||
}
|
||||
}
|
||||
|
||||
internal static void fillDatabase(Stream stream)
|
||||
|
@ -144,7 +144,7 @@ namespace MCGalaxy {
|
||||
Player[] players = PlayerInfo.Online;
|
||||
foreach (Player pl in players) {
|
||||
if (!global && pl.level != level) continue;
|
||||
if (!pl.HasCpeExt(CpeExt.BlockDefinitions)) continue;
|
||||
if (!pl.hasBlockDefs) continue;
|
||||
if (global && pl.level.CustomBlockDefs[id] != GlobalDefs[id]) continue;
|
||||
|
||||
if (pl.HasCpeExt(CpeExt.BlockDefinitionsExt, 2) && def.Shape != 0)
|
||||
@ -176,7 +176,7 @@ namespace MCGalaxy {
|
||||
if (!global && pl.level != level) continue;
|
||||
if (global && pl.level.CustomBlockDefs[id] != null) continue;
|
||||
|
||||
if (pl.HasCpeExt(CpeExt.BlockDefinitions))
|
||||
if (pl.hasBlockDefs)
|
||||
pl.SendRaw(Opcode.CpeRemoveBlockDefinition, id);
|
||||
}
|
||||
Save(global, level);
|
||||
|
138
Levels/BufferedBlockSender.cs
Normal file
138
Levels/BufferedBlockSender.cs
Normal file
@ -0,0 +1,138 @@
|
||||
/*
|
||||
Copyright 2015 MCGalaxy
|
||||
|
||||
Dual-licensed under the Educational Community License, Version 2.0 and
|
||||
the GNU General Public License, Version 3 (the "Licenses"); you may
|
||||
not use this file except in compliance with the Licenses. You may
|
||||
obtain a copy of the Licenses at
|
||||
|
||||
http://www.opensource.org/licenses/ecl2.php
|
||||
http://www.gnu.org/licenses/gpl-3.0.html
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the Licenses are distributed on an "AS IS"
|
||||
BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
or implied. See the Licenses for the specific language governing
|
||||
permissions and limitations under the Licenses.
|
||||
*/
|
||||
using System;
|
||||
|
||||
namespace MCGalaxy {
|
||||
|
||||
public sealed class BufferedBlockSender {
|
||||
|
||||
int[] indices = new int[256];
|
||||
byte[] types = new byte[256];
|
||||
int count = 0;
|
||||
Level level;
|
||||
|
||||
public BufferedBlockSender(Level level) {
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
public void Add(int index, byte type, byte extType) {
|
||||
indices[count] = index;
|
||||
if (type == Block.custom_block) types[count] = extType;
|
||||
else types[count] = Block.Convert(type);
|
||||
count++;
|
||||
}
|
||||
|
||||
public void CheckIfSend(bool force) {
|
||||
if (count > 0 && (force || count == 256)) {
|
||||
byte[] bulk = null, normal = null, noBlockDefs = null, original = null;
|
||||
Player[] players = PlayerInfo.Online;
|
||||
|
||||
foreach (Player p in players) {
|
||||
if (p.level != level) continue;
|
||||
|
||||
// Different clients support varying types of blocks
|
||||
byte[] packet = null;
|
||||
if (p.HasCpeExt(CpeExt.BulkBlockUpdate) && p.hasCustomBlocks && p.hasBlockDefs && count >= 1600) {
|
||||
if (bulk == null) bulk = MakeBulkPacket();
|
||||
packet = bulk;
|
||||
} else if (p.hasCustomBlocks && p.hasBlockDefs) {
|
||||
if (normal == null) normal = MakeNormalPacket();
|
||||
packet = normal;
|
||||
} else if (p.hasCustomBlocks) {
|
||||
if (noBlockDefs == null) noBlockDefs = MakeNoBlockDefsPacket();
|
||||
packet = noBlockDefs;
|
||||
} else {
|
||||
if (original == null) original = MakeOriginalOnlyPacket();
|
||||
packet = original;
|
||||
}
|
||||
p.SendRaw(packet);
|
||||
}
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#region Packet construction
|
||||
|
||||
byte[] MakeBulkPacket() {
|
||||
byte[] data = new byte[2 + 256 * 5];
|
||||
data[0] = Opcode.CpeBulkBlockUpdate;
|
||||
data[1] = (byte)(count - 1);
|
||||
for (int i = 0, j = 2; i < count; i++) {
|
||||
int index = indices[i];
|
||||
data[j++] = (byte)(index >> 24); data[j++] = (byte)(index >> 16);
|
||||
data[j++] = (byte)(index >> 8); data[j++] = (byte)index;
|
||||
}
|
||||
for (int i = 0, j = 2 + 256 * sizeof(int); i < count; i++)
|
||||
data[j++] = types[i];
|
||||
return data;
|
||||
}
|
||||
|
||||
byte[] MakeNormalPacket() {
|
||||
byte[] data = new byte[count * 8];
|
||||
for (int i = 0, j = 0; i < count; i++) {
|
||||
int index = indices[i];
|
||||
int x = (index % level.Width);
|
||||
int y = (index / level.Width) / level.Length;
|
||||
int z = (index / level.Width) % level.Length;
|
||||
|
||||
data[j++] = Opcode.SetBlock;
|
||||
data[j++] = (byte)(x >> 8); data[j++] = (byte)x;
|
||||
data[j++] = (byte)(y >> 8); data[j++] = (byte)y;
|
||||
data[j++] = (byte)(z >> 8); data[j++] = (byte)z;
|
||||
data[j++] = types[i];
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
byte[] MakeNoBlockDefsPacket() {
|
||||
byte[] data = new byte[count * 8];
|
||||
for (int i = 0, j = 0; i < count; i++) {
|
||||
int index = indices[i];
|
||||
int x = (index % level.Width);
|
||||
int y = (index / level.Width) / level.Length;
|
||||
int z = (index / level.Width) % level.Length;
|
||||
|
||||
data[j++] = Opcode.SetBlock;
|
||||
data[j++] = (byte)(x >> 8); data[j++] = (byte)x;
|
||||
data[j++] = (byte)(y >> 8); data[j++] = (byte)y;
|
||||
data[j++] = (byte)(z >> 8); data[j++] = (byte)z;
|
||||
data[j++] = types[i] < Block.CpeCount ? types[i] : level.GetFallback(types[i]);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
byte[] MakeOriginalOnlyPacket() {
|
||||
byte[] data = new byte[count * 8];
|
||||
for (int i = 0, j = 0; i < count; i++) {
|
||||
int index = indices[i];
|
||||
int x = (index % level.Width);
|
||||
int y = (index / level.Width) / level.Length;
|
||||
int z = (index / level.Width) % level.Length;
|
||||
|
||||
data[j++] = Opcode.SetBlock;
|
||||
data[j++] = (byte)(x >> 8); data[j++] = (byte)x;
|
||||
data[j++] = (byte)(y >> 8); data[j++] = (byte)y;
|
||||
data[j++] = (byte)(z >> 8); data[j++] = (byte)z;
|
||||
data[j++] = types[i] < Block.CpeCount ? Block.ConvertCPE(types[i])
|
||||
: Block.ConvertCPE(level.GetFallback(types[i]));
|
||||
}
|
||||
return data;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
@ -168,26 +168,23 @@ namespace MCGalaxy {
|
||||
RemoveExpiredChecks();
|
||||
|
||||
lastUpdate = ListUpdate.Count;
|
||||
int* pendingIndices = stackalloc int[256];
|
||||
byte* pendingTypes = stackalloc byte[256];
|
||||
int pendingCount = 0;
|
||||
if (ListUpdate.Count > 0 && bulkSender == null)
|
||||
bulkSender = new BufferedBlockSender(this);
|
||||
|
||||
for (int i = 0; i < ListUpdate.Count; i++) {
|
||||
Update C = ListUpdate.Items[i];
|
||||
try {
|
||||
string info = C.data as string;
|
||||
if (info == null) info = "";
|
||||
if (DoPhysicsBlockchange(C.b, C.type, false,info, 0, true)) {
|
||||
pendingIndices[pendingCount] = C.b;
|
||||
pendingTypes[pendingCount] = C.type;
|
||||
pendingCount++;
|
||||
}
|
||||
if (DoPhysicsBlockchange(C.b, C.type, false, info, 0, true))
|
||||
bulkSender.Add(C.b, C.type, 0);
|
||||
} catch {
|
||||
Server.s.Log("Phys update issue");
|
||||
}
|
||||
SendUpdates(pendingIndices, pendingTypes, ref pendingCount, false);
|
||||
bulkSender.CheckIfSend(false);
|
||||
}
|
||||
SendUpdates(pendingIndices, pendingTypes, ref pendingCount, true);
|
||||
if (bulkSender != null)
|
||||
bulkSender.CheckIfSend(true);
|
||||
ListUpdate.Clear(); listUpdateExists.Clear();
|
||||
} catch (Exception e) {
|
||||
Server.s.Log("Level physics error");
|
||||
@ -195,35 +192,6 @@ namespace MCGalaxy {
|
||||
}
|
||||
}
|
||||
|
||||
unsafe void SendUpdates(int* pendingIndices, byte* pendingTypes, ref int pendingCount, bool force) {
|
||||
try {
|
||||
if (pendingCount > 0 && (force || pendingCount == 256)) {
|
||||
byte[] data = new byte[pendingCount * 8];
|
||||
for (int i = 0; i < pendingCount; i++) {
|
||||
int index = pendingIndices[i];
|
||||
int x = (index % Width);
|
||||
int y = (index / Width) / Length;
|
||||
int z = (index / Width) % Length;
|
||||
|
||||
data[(i << 3)] = Opcode.SetBlock;
|
||||
data[(i << 3) + 1] = (byte)(x >> 8); data[(i << 3) + 2] = (byte)x;
|
||||
data[(i << 3) + 3] = (byte)(y >> 8); data[(i << 3) + 4] = (byte)y;
|
||||
data[(i << 3) + 5] = (byte)(z >> 8); data[(i << 3) + 6] = (byte)z;
|
||||
// TODO: do we need conversion for non-CPE block clients?
|
||||
data[(i << 3) + 7] = Block.Convert(pendingTypes[i]);
|
||||
}
|
||||
Player[] players = PlayerInfo.Online;
|
||||
foreach (Player p in players) {
|
||||
if (p.level == this) p.SendRaw(data);
|
||||
}
|
||||
pendingCount = 0;
|
||||
}
|
||||
} catch {
|
||||
Server.s.Log("Phys update issue");
|
||||
pendingCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void DoNormalPhysics(ushort x, ushort y, ushort z, Random rand, Check C) {
|
||||
switch (blocks[C.b])
|
||||
{
|
||||
|
@ -199,6 +199,7 @@ namespace MCGalaxy
|
||||
public bool bufferblocks = Server.bufferblocks;
|
||||
public List<BlockQueue.block> blockqueue = new List<BlockQueue.block>();
|
||||
private readonly object physThreadLock = new object();
|
||||
BufferedBlockSender bulkSender;
|
||||
|
||||
public List<C4.C4s> C4list = new List<C4.C4s>();
|
||||
|
||||
|
@ -420,6 +420,7 @@
|
||||
<Compile Include="Levels\Block.Convert.cs" />
|
||||
<Compile Include="Levels\Block.ID.cs" />
|
||||
<Compile Include="Levels\Block.Permissions.cs" />
|
||||
<Compile Include="Levels\BufferedBlockSender.cs" />
|
||||
<Compile Include="Levels\Generator\MapGen.cs" />
|
||||
<Compile Include="Levels\Generator\NoiseGen.cs" />
|
||||
<Compile Include="Levels\Generator\MapGenParams.cs" />
|
||||
|
@ -72,7 +72,7 @@ namespace MCGalaxy {
|
||||
}
|
||||
}
|
||||
|
||||
public bool hasCpe = false, hasCustomBlocks = false, hasTextColors, finishedCpeLogin = false;
|
||||
public bool hasCpe, hasCustomBlocks, hasBlockDefs, hasTextColors, finishedCpeLogin = false;
|
||||
public string appName;
|
||||
public int extensionCount;
|
||||
public List<string> extensions = new List<string>();
|
||||
@ -304,7 +304,7 @@ namespace MCGalaxy {
|
||||
int usedLength = 0;
|
||||
byte[] buffer = CompressRawMap(out usedLength);
|
||||
|
||||
if (HasCpeExt(CpeExt.BlockDefinitions)) {
|
||||
if (hasBlockDefs) {
|
||||
if (oldLevel != null && oldLevel != level)
|
||||
RemoveOldLevelCustomBlocks(oldLevel);
|
||||
BlockDefinition.SendLevelCustomBlocks(this);
|
||||
@ -365,7 +365,6 @@ namespace MCGalaxy {
|
||||
byte[] buffer = new byte[bufferSize];
|
||||
MemoryStream temp = new MemoryStream();
|
||||
int bIndex = 0;
|
||||
bool hasBlockDefs = HasCpeExt(CpeExt.BlockDefinitions);
|
||||
|
||||
using (GZipStream compressor = new GZipStream(temp, CompressionMode.Compress, true)) {
|
||||
NetUtils.WriteI32(level.blocks.Length, buffer, 0);
|
||||
@ -478,7 +477,7 @@ namespace MCGalaxy {
|
||||
NetUtils.WriteU16(z, buffer, 5);
|
||||
|
||||
if (type == Block.custom_block) {
|
||||
if (HasCpeExt(CpeExt.BlockDefinitions))
|
||||
if (hasBlockDefs)
|
||||
buffer[7] = level.GetExtTile(x, y, z);
|
||||
else
|
||||
buffer[7] = level.GetFallbackExtTile(x, y, z);
|
||||
@ -502,7 +501,7 @@ namespace MCGalaxy {
|
||||
NetUtils.WriteU16(z, buffer, 5);
|
||||
|
||||
if (type == Block.custom_block) {
|
||||
if (HasCpeExt(CpeExt.BlockDefinitions))
|
||||
if (hasBlockDefs)
|
||||
buffer[7] = extType;
|
||||
else
|
||||
buffer[7] = level.GetFallback(extType);
|
||||
|
@ -131,7 +131,8 @@ namespace MCGalaxy
|
||||
case CpeExt.FullCP437:
|
||||
FullCP437 = version; break;
|
||||
case CpeExt.BlockDefinitions:
|
||||
BlockDefinitions = version; break;
|
||||
BlockDefinitions = version;
|
||||
hasBlockDefs = true; break;
|
||||
case CpeExt.BlockDefinitionsExt:
|
||||
BlockDefinitionsExt = version; break;
|
||||
case CpeExt.TextColors:
|
||||
@ -191,9 +192,9 @@ namespace MCGalaxy
|
||||
|
||||
public void SendCurrentMapAppearance() {
|
||||
byte edgeBlock = level.EdgeBlock, horBlock = level.HorizonBlock;
|
||||
if (edgeBlock >= Block.CpeCount && !HasCpeExt(CpeExt.BlockDefinitions))
|
||||
if (edgeBlock >= Block.CpeCount && !hasBlockDefs)
|
||||
edgeBlock = level.GetFallback(edgeBlock);
|
||||
if (horBlock >= Block.CpeCount && !HasCpeExt(CpeExt.BlockDefinitions))
|
||||
if (horBlock >= Block.CpeCount && !hasBlockDefs)
|
||||
horBlock = level.GetFallback(horBlock);
|
||||
|
||||
if (EnvMapAppearance == 2) {
|
||||
@ -239,7 +240,7 @@ namespace MCGalaxy
|
||||
SendSetBlockPermission(i, canPlace, canDelete);
|
||||
}
|
||||
|
||||
if (!HasCpeExt(CpeExt.BlockDefinitions)) return;
|
||||
if (!hasBlockDefs) return;
|
||||
for (int i = count; i < 256; i++) {
|
||||
if (level.CustomBlockDefs[i] == null) continue;
|
||||
SendSetBlockPermission((byte)i, level.Buildable, level.Deletable);
|
||||
|
@ -351,7 +351,7 @@ namespace MCGalaxy {
|
||||
if (type == 0x42) {
|
||||
hasCpe = true;
|
||||
|
||||
SendExtInfo(16);
|
||||
SendExtInfo(18);
|
||||
SendExtEntry(CpeExt.ClickDistance, 1);
|
||||
SendExtEntry(CpeExt.CustomBlocks, 1);
|
||||
SendExtEntry(CpeExt.HeldBlock, 1);
|
||||
@ -373,6 +373,8 @@ namespace MCGalaxy {
|
||||
SendExtEntry(CpeExt.BlockDefinitions, 1);
|
||||
|
||||
SendExtEntry(CpeExt.BlockDefinitionsExt, 2);
|
||||
SendExtEntry(CpeExt.TextColors, 1);
|
||||
SendExtEntry(CpeExt.BulkBlockUpdate, 1);
|
||||
}
|
||||
|
||||
try { left.Remove(name.ToLower()); }
|
||||
@ -656,7 +658,7 @@ namespace MCGalaxy {
|
||||
}
|
||||
|
||||
if (type >= Block.CpeCount) {
|
||||
if (!HasCpeExt(CpeExt.BlockDefinitions) || level.CustomBlockDefs[type] == null) {
|
||||
if (!hasBlockDefs || level.CustomBlockDefs[type] == null) {
|
||||
SendMessage("Invalid block type: " + type);
|
||||
RevertBlock(x, y, z); return;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user