Skip to content

Commit 401aa73

Browse files
committed
fix: avoid jackpots on changed slot collection sizes
1 parent 10c44b7 commit 401aa73

File tree

24 files changed

+398
-226
lines changed

24 files changed

+398
-226
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
namespace Intersect.Collections.Slotting;
2+
3+
4+
public interface ISlot
5+
{
6+
7+
int Slot { get; }
8+
9+
bool IsEmpty { get; }
10+
11+
}
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
using System.Collections;
2+
3+
namespace Intersect.Collections.Slotting;
4+
5+
public class SlotList<TSlot> : IList<TSlot> where TSlot : ISlot
6+
{
7+
private readonly SortedList<int, TSlot> _slots;
8+
private readonly Func<int, TSlot> _factory;
9+
10+
public SlotList(int capacity, Func<int, TSlot> factory)
11+
{
12+
_slots = new SortedList<int, TSlot>(capacity);
13+
_factory = factory;
14+
}
15+
16+
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
17+
18+
public IEnumerator<TSlot> GetEnumerator() => _slots.Values.GetEnumerator();
19+
20+
public void Add(TSlot slot)
21+
{
22+
if (_slots.TryGetValue(slot.Slot, out var existingSlot))
23+
{
24+
if (existingSlot.IsEmpty)
25+
{
26+
_slots[slot.Slot] = slot;
27+
}
28+
else
29+
{
30+
throw new ArgumentException($"Slot {slot.Slot} is already filled with a non-empty slot.", nameof(slot));
31+
}
32+
}
33+
else
34+
{
35+
_slots.Add(slot.Slot, slot);
36+
}
37+
}
38+
39+
public void Clear() => _slots.Clear();
40+
41+
public bool Contains(TSlot slot) => _slots.ContainsValue(slot);
42+
43+
public void CopyTo(TSlot[] array, int arrayIndex) =>
44+
_slots.Select(kvp => kvp.Value).ToArray().CopyTo(array, arrayIndex);
45+
46+
public bool Remove(TSlot slot) => _slots.Remove(slot.Slot);
47+
48+
public int Capacity
49+
{
50+
get => _slots.Capacity;
51+
set => _slots.Capacity = value;
52+
}
53+
54+
public int Count => _slots.Count;
55+
56+
public bool IsReadOnly => ((IDictionary)_slots).IsReadOnly;
57+
58+
public int IndexOf(TSlot slot) => _slots.IndexOfValue(slot);
59+
60+
public void Insert(int slotIndex, TSlot slot)
61+
{
62+
if (slotIndex != slot.Slot)
63+
{
64+
throw new ArgumentException($"Tried to insert slot {slot.Slot} to slot index {slotIndex}", nameof(slotIndex));
65+
}
66+
67+
_slots.Add(slotIndex, slot);
68+
}
69+
70+
public void RemoveAt(int slotIndex) => _slots.Remove(slotIndex);
71+
72+
public TSlot this[int slotIndex]
73+
{
74+
get
75+
{
76+
if (_slots.TryGetValue(slotIndex, out var slot))
77+
{
78+
return slot;
79+
}
80+
81+
slot = _factory(slotIndex);
82+
_slots[slotIndex] = slot;
83+
return slot;
84+
}
85+
set => _slots[slotIndex] = value;
86+
}
87+
88+
public int FindIndex(Func<TSlot, bool> predicate)
89+
{
90+
var copy = this.ToArray();
91+
for (var index = 0; index < copy.Length; ++index)
92+
{
93+
if (predicate(copy[index]))
94+
{
95+
return index;
96+
}
97+
}
98+
99+
return -1;
100+
}
101+
}

Intersect (Core)/Config/Options.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,6 @@ public static ushort ServerPort
119119

120120
public static int MaxInvItems => Instance.PlayerOpts.MaxInventory;
121121

122-
public static int MaxPlayerSkills => Instance.PlayerOpts.MaxSpells;
123-
124122
public static int MaxCharacters => Instance.PlayerOpts.MaxCharacters;
125123

126124
public static int ItemDropChance => Instance.PlayerOpts.ItemDropChance;

Intersect.Client.Core/Entities/Entity.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ public Guid SpellCast
173173
}
174174
}
175175

176-
public Spell[] Spells { get; set; } = new Spell[Options.MaxPlayerSkills];
176+
public Spell[] Spells { get; set; } = new Spell[Options.Instance.PlayerOpts.MaxSpells];
177177

178178
IReadOnlyList<Guid> IEntity.Spells => Spells.Select(x => x.Id).ToList();
179179

@@ -233,7 +233,7 @@ public Entity(Guid id, EntityPacket? packet, EntityType entityType)
233233
Inventory[i] = new Item();
234234
}
235235

236-
for (var i = 0; i < Options.MaxPlayerSkills; i++)
236+
for (var i = 0; i < Options.Instance.PlayerOpts.MaxSpells; i++)
237237
{
238238
Spells[i] = new Spell();
239239
}

Intersect.Client.Core/Interface/Game/Spells/SpellItem.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ void pnl_RightClicked(Base sender, ClickedEventArgs arguments)
8686
else
8787
{
8888
Globals.Me.TryForgetSpell(mYindex);
89-
}
89+
}
9090
}
9191

9292
void pnl_HoverLeave(Base sender, EventArgs arguments)
@@ -263,7 +263,7 @@ public void Update()
263263
//Check spell first.
264264
if (mSpellWindow.RenderBounds().IntersectsWith(dragRect))
265265
{
266-
for (var i = 0; i < Options.MaxInvItems; i++)
266+
for (var i = 0; i < Options.Instance.PlayerOpts.MaxSpells; i++)
267267
{
268268
if (i < mSpellWindow.Items.Count &&
269269
mSpellWindow.Items[i].RenderBounds().IntersectsWith(dragRect))

Intersect.Client.Core/Interface/Game/Spells/SpellsWindow.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ public void Update()
120120

121121
X = mSpellWindow.X;
122122
Y = mSpellWindow.Y;
123-
for (var i = 0; i < Options.MaxPlayerSkills; i++)
123+
for (var i = 0; i < Options.Instance.PlayerOpts.MaxSpells; i++)
124124
{
125125
var spell = SpellBase.Get(Globals.Me.Spells[i].Id);
126126
Items[i].Pnl.IsHidden = spell == null || Items[i].IsDragging;
@@ -133,7 +133,7 @@ public void Update()
133133

134134
private void InitItemContainer()
135135
{
136-
for (var i = 0; i < Options.MaxPlayerSkills; i++)
136+
for (var i = 0; i < Options.Instance.PlayerOpts.MaxSpells; i++)
137137
{
138138
Items.Add(new SpellItem(this, i));
139139
Items[i].Container = new ImagePanel(mItemContainer, "Spell");

Intersect.Server.Core/Database/DbInterface.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -522,8 +522,7 @@ public static Player GetUserCharacter(User user, Guid playerId, bool explicitLoa
522522
try
523523
{
524524
using var playerContext = CreatePlayerContext(readOnly: true, explicitLoad: false);
525-
player.LoadRelationships(playerContext);
526-
_ = Player.Validate(player);
525+
_ = player.LoadRelationships(playerContext);
527526
}
528527
catch (Exception exception)
529528
{

Intersect.Server.Core/Database/Item.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
namespace Intersect.Server.Database;
1212

13-
public class Item: IItem
13+
public class Item : IItem
1414
{
1515
[JsonIgnore][NotMapped] public double DropChance { get; set; } = 100;
1616

Intersect.Server.Core/Database/PlayerData/Players/BagSlot.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
using System.ComponentModel.DataAnnotations.Schema;
2-
2+
using Intersect.Collections.Slotting;
33
using Newtonsoft.Json;
44

55
// ReSharper disable UnusedAutoPropertyAccessor.Local
@@ -23,12 +23,13 @@ public BagSlot(int slot)
2323
[DatabaseGenerated(DatabaseGeneratedOption.Identity), JsonIgnore]
2424
public Guid Id { get; private set; }
2525

26+
public bool IsEmpty => ItemId == default;
27+
2628
[JsonIgnore]
2729
public Guid ParentBagId { get; private set; }
2830

2931
[JsonIgnore]
3032
public virtual Bag ParentBag { get; private set; }
3133

3234
public int Slot { get; private set; }
33-
3435
}

Intersect.Server.Core/Database/PlayerData/Players/BankSlot.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
using System.ComponentModel.DataAnnotations.Schema;
2-
2+
using Intersect.Collections.Slotting;
33
using Intersect.Server.Entities;
44

55
using Newtonsoft.Json;
@@ -12,6 +12,7 @@ namespace Intersect.Server.Database.PlayerData.Players;
1212

1313
public partial class BankSlot : Item, ISlot, IPlayerOwned
1414
{
15+
public static BankSlot Create(int slotIndex) => new(slotIndex);
1516

1617
public BankSlot()
1718
{
@@ -25,6 +26,8 @@ public BankSlot(int slot)
2526
[DatabaseGenerated(DatabaseGeneratedOption.Identity), JsonIgnore]
2627
public Guid Id { get; private set; }
2728

29+
public bool IsEmpty => ItemId == default;
30+
2831
[JsonIgnore]
2932
public Guid PlayerId { get; private set; }
3033

0 commit comments

Comments
 (0)