Combine NormalPlayerListWidget and ExtPlayerListWidget into one class

This commit is contained in:
UnknownShadow200 2018-01-12 15:28:06 +11:00
parent 9066bf55ae
commit d1c3f85518
10 changed files with 337 additions and 553 deletions

View File

@ -1,6 +1,6 @@

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
# SharpDevelop 4.4
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClassicalSharp", "ClassicalSharp\ClassicalSharp.csproj", "{BEB1C785-5CAD-48FF-A886-876BF0A318D4}"
EndProject

View File

@ -86,14 +86,10 @@ namespace ClassicalSharp.Gui.Screens {
hotbar.Dispose();
hotbar.Init();
if (!hadPlayerList) return;
if (game.Server.UsingExtPlayerList && !game.UseClassicTabList) {
playerList = new ExtPlayerListWidget(game, playerFont);
} else {
playerList = new NormalPlayerListWidget(game, playerFont);
}
if (!hadPlayerList) return;
bool extended = game.Server.UsingExtPlayerList && !game.UseClassicTabList;
playerList = new PlayerListWidget(game, playerFont, !extended);
playerList.Init();
playerList.RecalcYOffset();
playerList.Reposition();

View File

@ -138,12 +138,10 @@ namespace ClassicalSharp.Gui.Widgets {
List<string> matches = new List<string>();
game.Chat.Add(null, MessageType.ClientStatus3);
TabListEntry[] entries = game.TabList.Entries;
TabListEntry[] entries = TabList.Entries;
for (int i = 0; i < EntityList.MaxCount; i++) {
if (entries[i] == null) continue;
string rawName = entries[i].PlayerName;
string name = Utils.StripColours(rawName);
if (entries[i] == null) continue;
string name = entries[i].PlayerName;
if (Utils.CaselessStarts(name, part)) matches.Add(name);
}

View File

@ -1,190 +0,0 @@
// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
using System;
using System.Collections.Generic;
using System.Drawing;
using ClassicalSharp.Entities;
using ClassicalSharp.Events;
namespace ClassicalSharp.Gui.Widgets {
public class ExtPlayerListWidget : PlayerListWidget {
public ExtPlayerListWidget(Game game, Font font) : base(game, font) {
textures = new Texture[512];
elementOffset = 10;
}
PlayerInfo[] info = new PlayerInfo[512];
class PlayerInfo {
public string ListName;
public string PlayerName;
public string GroupName;
public byte GroupRank;
public byte NameId;
public bool IsGroup = false;
public PlayerInfo(TabListEntry p, byte id) {
ListName = Utils.StripColours(p.ListName);
PlayerName = Utils.StripColours(p.PlayerName);
NameId = id;
GroupName = p.GroupName;
GroupRank = p.GroupRank;
}
public PlayerInfo(string groupName) {
GroupName = groupName;
IsGroup = true;
}
}
PlayerInfoComparer comparer = new PlayerInfoComparer();
class PlayerInfoComparer : IComparer<PlayerInfo> {
public bool JustComparingGroups = true;
public int Compare(PlayerInfo x, PlayerInfo y) {
if (JustComparingGroups)
return x.GroupName.CompareTo(y.GroupName);
int rankOrder = x.GroupRank.CompareTo(y.GroupRank);
return rankOrder != 0 ? rankOrder :
x.ListName.CompareTo(y.ListName);
}
}
protected override bool ShouldOffset(int i) {
return info[i] == null || !info[i].IsGroup;
}
public override void Init() {
base.Init();
game.EntityEvents.TabListEntryAdded += TabEntryAdded;
game.EntityEvents.TabListEntryRemoved += TabEntryRemoved;
game.EntityEvents.TabListEntryChanged += TabEntryChanged;
}
public override void Dispose() {
base.Dispose();
game.EntityEvents.TabListEntryAdded -= TabEntryAdded;
game.EntityEvents.TabListEntryChanged -= TabEntryChanged;
game.EntityEvents.TabListEntryRemoved -= TabEntryRemoved;
}
void TabEntryChanged(object sender, IdEventArgs e) {
for (int i = 0; i < namesCount; i++) {
PlayerInfo pInfo = info[i];
if (!pInfo.IsGroup && pInfo.NameId == e.Id) {
Texture tex = textures[i];
gfx.DeleteTexture(ref tex);
AddPlayerInfo(game.TabList.Entries[e.Id], e.Id, i);
SortPlayerInfo();
return;
}
}
}
void TabEntryRemoved(object sender, IdEventArgs e) {
for (int i = 0; i < namesCount; i++) {
PlayerInfo pInfo = info[i];
if (!pInfo.IsGroup && pInfo.NameId == e.Id) {
RemoveItemAt(info, i);
RemoveTextureAt(i);
return;
}
}
}
void TabEntryAdded(object sender, IdEventArgs e) {
AddPlayerInfo(game.TabList.Entries[e.Id], e.Id, -1);
SortPlayerInfo();
}
protected override void CreateInitialPlayerInfo() {
TabListEntry[] entries = game.TabList.Entries;
for (int i = 0; i < entries.Length; i++) {
TabListEntry e = entries[i];
if (e != null) AddPlayerInfo(e, (byte)i, -1);
}
}
public override string GetNameUnder(int mouseX, int mouseY) {
for (int i = 0; i < namesCount; i++) {
Texture tex = textures[i];
if (tex.IsValid && tex.Bounds.Contains(mouseX, mouseY) && !info[i].IsGroup) {
return Utils.StripColours(info[i].PlayerName);
}
}
return null;
}
void AddPlayerInfo(TabListEntry player, byte id, int index) {
DrawTextArgs args = new DrawTextArgs(player.ListName, font, true);
Texture tex = game.Drawer2D.MakeTextTexture(ref args, 0, 0);
game.Drawer2D.ReducePadding(ref tex, Utils.Floor(font.Size), 3);
if (index < 0) {
info[namesCount] = new PlayerInfo(player, id);
textures[namesCount] = tex;
namesCount++;
} else {
info[index] = new PlayerInfo(player, id);
textures[index] = tex;
}
}
protected override void SortInfoList() {
if (namesCount == 0) return;
// Sort the list into groups
for (int i = 0; i < namesCount; i++) {
if (info[i].IsGroup) DeleteGroup(ref i);
}
comparer.JustComparingGroups = true;
Array.Sort(info, textures, 0, namesCount, comparer);
// Sort the entries in each group
comparer.JustComparingGroups = false;
int index = 0;
while (index < namesCount) {
AddGroup(info[index].GroupName, ref index);
int count = GetGroupCount(index);
Array.Sort(info, textures, index, count, comparer);
index += count;
}
}
void DeleteGroup(ref int i) {
gfx.DeleteTexture(ref textures[i]);
RemoveItemAt(info, i);
RemoveItemAt(textures, i);
namesCount--;
i--;
}
void AddGroup(string group, ref int index) {
DrawTextArgs args = new DrawTextArgs(group, font, true);
Texture tex = game.Drawer2D.MakeTextTexture(ref args, 0, 0);
game.Drawer2D.ReducePadding(ref tex, Utils.Floor(font.Size), 3);
for (int i = info.Length - 1; i > index; i--) {
info[i] = info[i - 1];
textures[i] = textures[i - 1];
}
info[index] = new PlayerInfo(group);
textures[index] = tex;
index++;
namesCount++;
}
int GetGroupCount(int startIndex) {
string group = info[startIndex].GroupName;
int count = 0;
while (startIndex < namesCount && info[startIndex++].GroupName == group) {
count++;
}
return count;
}
}
}

View File

@ -1,123 +0,0 @@
// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
using System;
using System.Collections.Generic;
using System.Drawing;
using ClassicalSharp.Entities;
using ClassicalSharp.Events;
namespace ClassicalSharp.Gui.Widgets {
public class NormalPlayerListWidget : PlayerListWidget {
public NormalPlayerListWidget(Game game, Font font) : base(game, font) {
textures = new Texture[256];
}
PlayerInfo[] info = new PlayerInfo[256];
protected class PlayerInfo {
public string Name, ColouredName;
public byte Id;
public PlayerInfo(TabListEntry p, byte id) {
ColouredName = p.PlayerName;
Name = Utils.StripColours(p.PlayerName);
Id = id;
}
}
public override string GetNameUnder(int mouseX, int mouseY) {
for (int i = 0; i < namesCount; i++) {
Texture texture = textures[i];
if (texture.IsValid && texture.Bounds.Contains(mouseX, mouseY))
return Utils.StripColours(info[i].Name);
}
return null;
}
public override void Init() {
base.Init();
game.EntityEvents.TabListEntryAdded += TabEntryAdded;
game.EntityEvents.TabListEntryRemoved += TabEntryRemoved;
game.EntityEvents.TabListEntryChanged += TabEntryChanged;
}
public override void Dispose() {
base.Dispose();
game.EntityEvents.TabListEntryAdded -= TabEntryAdded;
game.EntityEvents.TabListEntryChanged -= TabEntryChanged;
game.EntityEvents.TabListEntryRemoved -= TabEntryRemoved;
}
protected override void CreateInitialPlayerInfo() {
TabListEntry[] entries = game.TabList.Entries;
for (int i = 0; i < entries.Length; i++) {
TabListEntry e = entries[i];
if (e != null)
AddPlayerInfo(new PlayerInfo(e, (byte)i), -1);
}
}
void AddPlayerInfo(PlayerInfo pInfo, int index) {
Texture tex = DrawName(pInfo);
if (index < 0) {
info[namesCount] = pInfo;
textures[namesCount] = tex;
namesCount++;
} else {
info[index] = pInfo;
textures[index] = tex;
}
}
Texture DrawName(PlayerInfo pInfo) {
string name = pInfo.ColouredName;
if (game.PureClassic) name = Utils.StripColours(name);
DrawTextArgs args = new DrawTextArgs(name, font, false);
Texture tex = game.Drawer2D.MakeTextTexture(ref args, 0, 0);
game.Drawer2D.ReducePadding(ref tex, Utils.Floor(font.Size), 3);
return tex;
}
void TabEntryAdded(object sender, IdEventArgs e) {
AddPlayerInfo(new PlayerInfo(game.TabList.Entries[e.Id], e.Id), -1);
SortPlayerInfo();
}
void TabEntryChanged(object sender, IdEventArgs e) {
for (int i = 0; i < namesCount; i++) {
PlayerInfo pInfo = info[i];
if (pInfo.Id != e.Id) continue;
Texture tex = textures[i];
gfx.DeleteTexture(ref tex);
AddPlayerInfo(new PlayerInfo(game.TabList.Entries[e.Id], e.Id), i);
SortPlayerInfo();
return;
}
}
void TabEntryRemoved(object sender, IdEventArgs e) {
for (int i = 0; i < namesCount; i++) {
PlayerInfo pInfo = info[i];
if (pInfo.Id == e.Id) {
RemoveItemAt(info, i);
RemoveTextureAt(i);
return;
}
}
}
PlayerInfoComparer comparer = new PlayerInfoComparer();
class PlayerInfoComparer : IComparer<PlayerInfo> {
public int Compare(PlayerInfo x, PlayerInfo y) {
return x.Name.CompareTo(y.Name);
}
}
protected override void SortInfoList() {
Array.Sort(info, textures, 0, namesCount, comparer);
}
}
}

View File

@ -1,201 +0,0 @@
// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
using System;
using System.Drawing;
namespace ClassicalSharp.Gui.Widgets {
public abstract class PlayerListWidget : Widget {
protected readonly Font font;
public PlayerListWidget(Game game, Font font) : base(game) {
HorizontalAnchor = Anchor.Centre;
VerticalAnchor = Anchor.Centre;
this.font = font;
}
protected const int columnPadding = 5;
protected const int boundsSize = 10;
protected const int namesPerColumn = 20;
protected int elementOffset = 0;
protected int namesCount = 0;
protected Texture[] textures;
protected int columns;
protected int xMin, xMax, yHeight;
static FastColour topCol = new FastColour(0, 0, 0, 180);
static FastColour bottomCol = new FastColour(50, 50, 50, 205);
TextWidget overview;
public override void Init() {
overview = TextWidget.Create(game, "Connected players:", font)
.SetLocation(Anchor.Centre, Anchor.LeftOrTop, 0, 0);
CreateInitialPlayerInfo();
SortPlayerInfo();
}
public abstract string GetNameUnder(int mouseX, int mouseY);
public override void Render(double delta) {
gfx.Texturing = false;
int offset = overview.Height + 10;
int height = Math.Max(300, Height + overview.Height);
gfx.Draw2DQuad(X, Y - offset, Width, height, topCol, bottomCol);
gfx.Texturing = true;
overview.YOffset = Y - offset + 5;
overview.Reposition();
overview.Render(delta);
for (int i = 0; i < namesCount; i++) {
Texture tex = textures[i];
int texY = tex.Y;
tex.Y1 -= 10;
if (tex.IsValid) tex.Render(gfx);
tex.Y1 = texY;
}
}
public override void Dispose() {
for (int i = 0; i < namesCount; i++) {
Texture tex = textures[i];
gfx.DeleteTexture(ref tex);
textures[i] = tex;
}
overview.Dispose();
}
protected void UpdateTableDimensions() {
int width = xMax - xMin;
X = xMin - boundsSize;
Y = game.Height / 2 - yHeight / 2 - boundsSize;
Width = width + boundsSize * 2;
Height = yHeight + boundsSize * 2;
}
protected void CalcMaxColumnHeight() {
yHeight = 0;
for (int col = 0; col < columns; col++) {
yHeight = Math.Max(GetColumnHeight(col), yHeight);
}
}
protected int GetColumnWidth(int column) {
int i = column * namesPerColumn;
int maxWidth = 0;
int maxIndex = Math.Min(namesCount, i + namesPerColumn);
for (; i < maxIndex; i++)
maxWidth = Math.Max(maxWidth, textures[i].Width);
return maxWidth + columnPadding + elementOffset;
}
protected int GetColumnHeight(int column) {
int i = column * namesPerColumn;
int total = 0;
int maxIndex = Math.Min(namesCount, i + namesPerColumn);
for (; i < maxIndex; i++)
total += textures[i].Height + 1;
return total;
}
protected void SetColumnPos(int column, int x, int y) {
int i = column * namesPerColumn;
int maxIndex = Math.Min(namesCount, i + namesPerColumn);
for (; i < maxIndex; i++) {
Texture tex = textures[i];
tex.X1 = x; tex.Y1 = y;
y += tex.Height + 1;
if (ShouldOffset(i))
tex.X1 += elementOffset;
textures[i] = tex;
}
}
protected virtual bool ShouldOffset(int i) { return true; }
public void RecalcYOffset() {
YOffset = -Math.Max(0, game.Height / 4 - Height / 2);
}
public override void Reposition() {
int oldX = X, oldY = Y;
base.Reposition();
for (int i = 0; i < namesCount; i++) {
textures[i].X1 += X - oldX;
textures[i].Y1 += Y - oldY;
}
}
protected abstract void CreateInitialPlayerInfo();
protected abstract void SortInfoList();
protected void RemoveTextureAt(int i) {
Texture tex = textures[i];
gfx.DeleteTexture(ref tex);
RemoveItemAt(textures, i);
namesCount--;
SortPlayerInfo();
}
protected void RemoveItemAt<T>(T[] array, int index) {
for (int i = index; i < namesCount - 1; i++) {
array[i] = array[i + 1];
}
array[namesCount - 1] = default(T);
}
protected void SortPlayerInfo() {
columns = Utils.CeilDiv(namesCount, namesPerColumn);
SortInfoList();
columns = Utils.CeilDiv(namesCount, namesPerColumn);
CalcMaxColumnHeight();
int y = game.Height / 2 - yHeight / 2;
int midCol = columns / 2;
int centreX = game.Width / 2;
int offset = 0;
if (columns % 2 != 0) {
// For an odd number of columns, the middle column is centred.
offset = Utils.CeilDiv(GetColumnWidth(midCol), 2);
}
xMin = centreX - offset;
for (int col = midCol - 1; col >= 0; col--) {
xMin -= GetColumnWidth(col);
SetColumnPos(col, xMin, y);
}
xMax = centreX - offset;
for (int col = midCol; col < columns; col++) {
SetColumnPos(col, xMax, y);
xMax += GetColumnWidth(col);
}
OnSort();
UpdateTableDimensions();
RecalcYOffset();
Reposition();
}
protected virtual void OnSort() {
int width = 0, centreX = game.Width / 2;
for (int col = 0; col < columns; col++)
width += GetColumnWidth(col);
if (width < 480) width = 480;
xMin = centreX - width / 2;
xMax = centreX + width / 2;
int x = xMin, y = game.Height / 2 - yHeight / 2;
for (int col = 0; col < columns; col++) {
SetColumnPos(col, x, y);
x += GetColumnWidth(col);
}
}
}
}

View File

@ -0,0 +1,313 @@
// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
using System;
using System.Collections.Generic;
using System.Drawing;
using ClassicalSharp.Entities;
using ClassicalSharp.Events;
namespace ClassicalSharp.Gui.Widgets {
public class PlayerListWidget : Widget {
readonly Font font;
bool classic;
public PlayerListWidget(Game game, Font font, bool classic) : base(game) {
HorizontalAnchor = Anchor.Centre;
VerticalAnchor = Anchor.Centre;
this.font = font;
this.classic = classic;
elementOffset = classic ? 0 : 10;
}
const int columnPadding = 5;
const int boundsSize = 10;
const int namesPerColumn = 20;
int elementOffset, namesCount = 0;
Texture[] textures = new Texture[512];
short[] IDs = new short[512];
int xMin, xMax, yHeight;
static FastColour topCol = new FastColour(0, 0, 0, 180);
static FastColour bottomCol = new FastColour(50, 50, 50, 205);
TextWidget overview;
public override void Init() {
TabListEntry[] entries = TabList.Entries;
for (int id = 0; id < entries.Length; id++) {
TabListEntry e = entries[id];
if (e != null) AddPlayerInfo((byte)id, -1);
}
SortAndReposition();
overview = TextWidget.Create(game, "Connected players:", font)
.SetLocation(Anchor.Centre, Anchor.LeftOrTop, 0, 0);
game.EntityEvents.TabListEntryAdded += TabEntryAdded;
game.EntityEvents.TabListEntryRemoved += TabEntryRemoved;
game.EntityEvents.TabListEntryChanged += TabEntryChanged;
}
public override void Render(double delta) {
gfx.Texturing = false;
int offset = overview.Height + 10;
int height = Math.Max(300, Height + overview.Height);
gfx.Draw2DQuad(X, Y - offset, Width, height, topCol, bottomCol);
gfx.Texturing = true;
overview.YOffset = Y - offset + 5;
overview.Reposition();
overview.Render(delta);
for (int i = 0; i < namesCount; i++) {
Texture tex = textures[i];
int texY = tex.Y;
tex.Y1 -= 10;
if (tex.IsValid) tex.Render(gfx);
tex.Y1 = texY;
}
}
public override void Dispose() {
for (int i = 0; i < namesCount; i++) {
Texture tex = textures[i];
gfx.DeleteTexture(ref tex);
textures[i] = tex;
}
overview.Dispose();
game.EntityEvents.TabListEntryAdded -= TabEntryAdded;
game.EntityEvents.TabListEntryChanged -= TabEntryChanged;
game.EntityEvents.TabListEntryRemoved -= TabEntryRemoved;
}
public string GetNameUnder(int mouseX, int mouseY) {
for (int i = 0; i < namesCount; i++) {
Texture tex = textures[i];
if (tex.IsValid && tex.Bounds.Contains(mouseX, mouseY) && IDs[i] >= 0) {
return TabList.Entries[IDs[i]].PlayerName;
}
}
return null;
}
void RepositionColumns() {
int width = 0, centreX = game.Width / 2;
yHeight = 0;
int columns = Utils.CeilDiv(namesCount, namesPerColumn);
for (int col = 0; col < columns; col++) {
width += GetColumnWidth(col);
yHeight = Math.Max(GetColumnHeight(col), yHeight);
}
if (width < 480) width = 480;
xMin = centreX - width / 2;
xMax = centreX + width / 2;
int x = xMin, y = game.Height / 2 - yHeight / 2;
for (int col = 0; col < columns; col++) {
SetColumnPos(col, x, y);
x += GetColumnWidth(col);
}
}
void UpdateTableDimensions() {
int width = xMax - xMin;
X = xMin - boundsSize;
Y = game.Height / 2 - yHeight / 2 - boundsSize;
Width = width + boundsSize * 2;
Height = yHeight + boundsSize * 2;
}
int GetColumnWidth(int column) {
int i = column * namesPerColumn;
int maxWidth = 0;
int maxIndex = Math.Min(namesCount, i + namesPerColumn);
for (; i < maxIndex; i++)
maxWidth = Math.Max(maxWidth, textures[i].Width);
return maxWidth + columnPadding + elementOffset;
}
int GetColumnHeight(int column) {
int i = column * namesPerColumn;
int total = 0;
int maxIndex = Math.Min(namesCount, i + namesPerColumn);
for (; i < maxIndex; i++)
total += textures[i].Height + 1;
return total;
}
void SetColumnPos(int column, int x, int y) {
int i = column * namesPerColumn;
int maxIndex = Math.Min(namesCount, i + namesPerColumn);
for (; i < maxIndex; i++) {
Texture tex = textures[i];
tex.X1 = x; tex.Y1 = y;
y += tex.Height + 1;
// offset player names a bit, compared to group name
if (!classic && IDs[i] >= 0) {
tex.X1 += elementOffset;
}
textures[i] = tex;
}
}
public void RecalcYOffset() {
YOffset = -Math.Max(0, game.Height / 4 - Height / 2);
}
public override void Reposition() {
int oldX = X, oldY = Y;
base.Reposition();
for (int i = 0; i < namesCount; i++) {
textures[i].X1 += X - oldX;
textures[i].Y1 += Y - oldY;
}
}
void AddPlayerInfo(byte id, int index) {
string name = TabList.Entries[id].ListName;
Texture tex = DrawName(name);
// insert at end of list
if (index == -1) { index = namesCount; namesCount++; }
IDs[index] = id;
textures[index] = tex;
}
void TabEntryAdded(object sender, IdEventArgs e) {
AddPlayerInfo(e.Id, -1);
SortAndReposition();
}
void TabEntryChanged(object sender, IdEventArgs e) {
for (int i = 0; i < namesCount; i++) {
if (IDs[i] != e.Id) continue;
Texture tex = textures[i];
gfx.DeleteTexture(ref tex);
AddPlayerInfo(e.Id, i);
SortAndReposition();
return;
}
}
void TabEntryRemoved(object sender, IdEventArgs e) {
for (int i = 0; i < namesCount; i++) {
if (IDs[i] != e.Id) continue;
RemoveAt(i);
SortAndReposition();
return;
}
}
void RemoveAt(int i) {
Texture tex = textures[i];
gfx.DeleteTexture(ref tex);
for (; i < namesCount - 1; i++) {
IDs[i] = IDs[i + 1];
textures[i] = textures[i + 1];
}
IDs[namesCount] = 0;
textures[namesCount] = default(Texture);
namesCount--;
}
void SortAndReposition() {
SortEntries();
RepositionColumns();
UpdateTableDimensions();
RecalcYOffset();
Reposition();
}
Texture DrawName(string name) {
if (game.PureClassic) name = Utils.StripColours(name);
DrawTextArgs args = new DrawTextArgs(name, font, false);
Texture tex = game.Drawer2D.MakeTextTexture(ref args, 0, 0);
game.Drawer2D.ReducePadding(ref tex, Utils.Floor(font.Size), 3);
return tex;
}
IComparer<short> comparer = new PlayerComparer();
class PlayerComparer : IComparer<short> {
public int Compare(short x, short y) {
byte xRank = TabList.Entries[x].GroupRank;
byte yRank = TabList.Entries[y].GroupRank;
int rankOrder = xRank.CompareTo(yRank);
if (rankOrder != 0) return rankOrder;
string xName = TabList.Entries[x].ListNameColourless;
string yName = TabList.Entries[y].ListNameColourless;
return xName.CompareTo(yName);
}
}
IComparer<short> grpComparer = new GroupComparer();
class GroupComparer : IComparer<short> {
public int Compare(short x, short y) {
string xGroup = TabList.Entries[x].Group;
string yGroup = TabList.Entries[y].Group;
return xGroup.CompareTo(yGroup);
}
}
void SortEntries() {
if (namesCount == 0) return;
if (classic) {
Array.Sort(IDs, textures, 0, namesCount, grpComparer);
return;
}
// Sort the list into groups
for (int i = 0; i < namesCount; i++) {
if (IDs[i] < 0) DeleteGroup(ref i);
}
Array.Sort(IDs, textures, 0, namesCount, grpComparer);
// Sort the entries in each group
int index = 0;
while (index < namesCount) {
short id = IDs[index];
AddGroup(id, ref index);
int count = GetGroupCount(id, index);
Array.Sort(IDs, textures, index, count, comparer);
index += count;
}
}
void DeleteGroup(ref int i) { RemoveAt(i); i--; }
void AddGroup(short id, ref int index) {
for (int i = IDs.Length - 1; i > index; i--) {
IDs[i] = IDs[i - 1];
textures[i] = textures[i - 1];
}
IDs[index] = (short)-id;
string group = TabList.Entries[id].Group;
textures[index] = DrawName(group);
index++;
namesCount++;
}
int GetGroupCount(short id, int idx) {
string group = TabList.Entries[id].Group;
int count = 0;
while (idx < namesCount && TabList.Entries[IDs[idx]].Group == group) {
idx++; count++;
}
return count;
}
}
}

View File

@ -127,9 +127,7 @@
<Compile Include="2D\Widgets\Menu\MenuInputValidator.cs" />
<Compile Include="2D\Widgets\Menu\MenuInputWidget.cs" />
<Compile Include="2D\Widgets\ButtonWidget.cs" />
<Compile Include="2D\Widgets\PlayerList\ExtPlayerListWidget.cs" />
<Compile Include="2D\Widgets\PlayerList\NormalPlayerListWidget.cs" />
<Compile Include="2D\Widgets\PlayerList\PlayerListWidget.cs" />
<Compile Include="2D\Widgets\PlayerListWidget.cs" />
<Compile Include="2D\Widgets\ScrollbarWidget.cs" />
<Compile Include="2D\Widgets\SurvivalHotbarWidget.cs" />
<Compile Include="2D\Widgets\TableWidget.cs" />
@ -330,7 +328,6 @@
<Folder Include="2D\Widgets" />
<Folder Include="2D\Widgets\Menu" />
<Folder Include="2D\Widgets\Chat" />
<Folder Include="2D\Widgets\PlayerList" />
<Folder Include="Blocks" />
<Folder Include="Entities\Components" />
<Folder Include="Entities\Mobs" />

View File

@ -3,7 +3,7 @@
namespace ClassicalSharp.Entities {
public sealed class TabList : IGameComponent {
public TabListEntry[] Entries = new TabListEntry[256];
public static TabListEntry[] Entries = new TabListEntry[256];
public void Init(Game game) { }
public void Ready(Game game) { }
@ -17,30 +17,24 @@ namespace ClassicalSharp.Entities {
}
}
public sealed class TabListEntry {
/// <summary> Unformatted name of the player for autocompletion, etc. </summary>
/// <remarks> Colour codes are always removed from this. </remarks>
public string PlayerName;
public sealed class TabListEntry {
/// <summary> Plain name of the player for autocompletion, etc. </summary>
public string PlayerName;
/// <summary> Formatted name for display in the player list. </summary>
/// <remarks> Can include colour codes. </remarks>
public string ListName;
public string ListNameColourless;
/// <summary> Name of the group this player is in. </summary>
/// <remarks> Can include colour codes. </remarks>
public string GroupName;
public string Group;
/// <summary> Player's rank within the group. (0 is highest) </summary>
/// <remarks> Multiple group members can share the same rank,
/// so a player's group rank is not a unique identifier. </remarks>
/// <remarks> Multiple players can share the same rank, so this is not a unique identifier. </remarks>
public byte GroupRank;
public TabListEntry(string playerName, string listName,
string groupName, byte groupRank) {
PlayerName = playerName;
PlayerName = Utils.StripColours(playerName);
ListName = listName;
GroupName = groupName;
ListNameColourless = Utils.StripColours(listName);
Group = groupName;
GroupRank = groupRank;
}
}

View File

@ -98,14 +98,14 @@ namespace ClassicalSharp.Network {
internal void AddTablistEntry(byte id, string playerName, string listName,
string groupName, byte groupRank) {
TabListEntry oldInfo = game.TabList.Entries[id];
TabListEntry oldInfo = TabList.Entries[id];
TabListEntry info = new TabListEntry(playerName, listName, groupName, groupRank);
game.TabList.Entries[id] = info;
TabList.Entries[id] = info;
if (oldInfo != null) {
// Only redraw the tab list if something changed.
if (info.PlayerName != oldInfo.PlayerName || info.ListName != oldInfo.ListName ||
info.GroupName != oldInfo.GroupName || info.GroupRank != oldInfo.GroupRank) {
info.Group != oldInfo.Group || info.GroupRank != oldInfo.GroupRank) {
game.EntityEvents.RaiseTabListEntryChanged(id);
}
} else {
@ -115,7 +115,7 @@ namespace ClassicalSharp.Network {
internal void RemoveTablistEntry(byte id) {
game.EntityEvents.RaiseTabEntryRemoved(id);
game.TabList.Entries[id] = null;
TabList.Entries[id] = null;
}
internal void DisableAddEntityHack() {