1 /* 2 * Copyright (c) 2017-2019 sel-project 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a copy 5 * of this software and associated documentation files (the "Software"), to deal 6 * in the Software without restriction, including without limitation the rights 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 * copies of the Software, and to permit persons to whom the Software is 9 * furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in all 12 * copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 * SOFTWARE. 21 * 22 */ 23 /** 24 * Copyright: Copyright (c) 2017-2019 sel-project 25 * License: MIT 26 * Authors: Kripth 27 * Source: $(HTTP github.com/sel-project/selery/source/selery/item/slot.d, selery/item/slot.d) 28 */ 29 module selery.item.slot; 30 31 import std.conv : to; 32 33 import selery.about; 34 import selery.item.item : Item; 35 import selery.item.items : Items; 36 37 /** 38 * Container for an item stack that has always a value. 39 * If the slot is not empty, an Item instance and the count 40 * can be stored. 41 * 42 * Conventionally an empty slot is always constructed using Slot(null) 43 */ 44 struct Slot { 45 46 private Item n_item; 47 public ubyte count; 48 49 /** 50 * Creates a slot with an item and its highest value as count. 51 * Example: 52 * --- 53 * assert(Slot(new Items.DiamondSword()).count == 1); 54 * assert(Slot(new Items.Snowball()).count == 16); 55 * assert(Slot(null).count == 0); 56 * --- 57 */ 58 public @safe @nogc this(Item item) { 59 if(item !is null) { 60 this.n_item = item; 61 this.count = this.item.max; 62 } 63 } 64 65 /** 66 * Creates a slot giving an item and a count in range 0..255 (unsigned byte). 67 * Setting an higher value it's impossible due to protocol's limitations. 68 * Example: 69 * --- 70 * assert(Slot(new Items.DiamondSword(), 22).count == 22); 71 * assert(Slot(new Items.Snowball(), 2).count == 2); 72 * assert(Slot(null, 100).count == 0); 73 * --- 74 */ 75 public @safe @nogc this(Item item, ubyte count) { 76 this(item); 77 if(this.item !is null) this.count = count; 78 } 79 80 /** 81 * Gets the slot's item. 82 */ 83 public pure nothrow @property @safe @nogc Item item() { 84 return this.n_item; 85 } 86 87 /** 88 * Checks whether or not the slot is empty. 89 * A slot is considered empty when its count is equal to 0 or 90 * when its item is null. 91 * Example: 92 * --- 93 * Slot slot = Slot(null); 94 * assert(slot.empty); 95 * 96 * slot = Slot(new Items.Snowball(), 1); 97 * assert(!slot.empty); 98 * 99 * slot.count--; 100 * assert(slot.empty); 101 * --- 102 */ 103 public pure nothrow @property @safe @nogc bool empty() { 104 return this.count == 0 || this.item is null; 105 } 106 107 /** 108 * Checks whether or not the slot is full. 109 * The slot is considered full when its count is equals or 110 * higher than the item's max stackable size. 111 * Example: 112 * --- 113 * assert(Slot(new Items.DiamondSword(), 1).full); 114 * assert(!Slot(new Items.Snowball(), 15).full); 115 * --- 116 * 117 * This property should be called only if the slot isn't empty due 118 * to its call on the item's property, that can be null. 119 * --- 120 * if(!slot.empty && slot.full) { ... } 121 * --- 122 */ 123 public pure nothrow @property @safe @nogc bool full() { 124 return this.count >= this.item.max; 125 } 126 127 /** 128 * Fills the slot setting the count as the max stacking value 129 * of the item. 130 * Example: 131 * --- 132 * Slot slot = Slot(new Item.Snowball(), 1); 133 * assert(slot.count == 1); 134 * slot.fill(); 135 * assert(slot.count == 16); 136 * --- 137 * 138 * Like full, this function requires item to not be null due to 139 * its call on its max property. 140 * --- 141 * if(slot.item !is null) { 142 * slot.fill(); 143 * } 144 * --- 145 */ 146 public pure nothrow @safe @nogc void fill() { 147 this.count = this.item.max; 148 } 149 150 public bool opEquals(Slot slot) { 151 return this.empty == slot.empty && (this.empty || this.count == slot.count && this.item == slot.item); 152 } 153 154 public bool opEquals(Item item) { 155 return this.empty == !!(item is null) && (this.empty || this.item == item); 156 } 157 158 public bool opEquals(item_t item) { 159 return this.empty == (item == Items.air) && (this.empty || this.item == item); 160 } 161 162 public string toString() { 163 return "Slot(" ~ (this.empty ? "null" : (this.item.toString() ~ " x" ~ this.count.to!string)) ~ ")"; 164 } 165 166 }