1 /*
2  * Copyright (c) 2017-2018 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: 2017-2018 sel-project
25  * License: MIT
26  * Authors: Kripth
27  * Source: $(HTTP github.com/sel-project/selery/source/selery/item/placeable.d, selery/item/placeable.d)
28  */
29 module selery.item.placeable;
30 
31 import selery.about : block_t, item_t;
32 import selery.block.block : compareBlock;
33 import selery.block.blocks : Blocks;
34 import selery.item.item;
35 import selery.math.vector;
36 import selery.player.player : Player;
37 import selery.world.world : World;
38 
39 static import sul.items;
40 
41 class GenericPlaceableItem : Item {
42 
43 	//TODO ctor
44 
45 	public override pure nothrow @property @safe @nogc bool placeable() {
46 		return true;
47 	}
48 
49 	public override block_t place(World world, BlockPosition position, uint face) {
50 		return this.block;
51 	}
52 
53 	public abstract pure nothrow @property @safe @nogc block_t block();
54 
55 }
56 
57 class PlaceableOnBlockItem : GenericPlaceableItem {
58 
59 	//TODO ctor
60 
61 	public override block_t place(World world, BlockPosition position, uint face) {
62 		if(world[position - [0, 1, 0]] == this.supportBlocks) {
63 			return super.place(world, position, face);
64 		} else {
65 			return 0;
66 		}
67 	}
68 
69 	public abstract pure nothrow @property @safe block_t[] supportBlocks();
70 
71 }
72 
73 template PlaceableItem(sul.items.Item _data, block_t _block, E...) {
74 
75 	static if(E.length == 0) {
76 
77 		class PlaceableItem : GenericPlaceableItem {
78 
79 			public override pure nothrow @property @safe @nogc const sul.items.Item data() {
80 				return _data;
81 			}
82 
83 			public override pure nothrow @property @safe @nogc block_t block() {
84 				return _block;
85 			}
86 
87 			alias slot this;
88 
89 		}
90 
91 	} else static if(is(typeof(E[0]) == block_t[])) {
92 		
93 		class PlaceableItem : PlaceableOnBlockItem {
94 			
95 			public override pure nothrow @property @safe @nogc const sul.items.Item data() {
96 				return _data;
97 			}
98 			
99 			public override pure nothrow @property @safe @nogc block_t block() {
100 				return _block;
101 			}
102 			
103 			public override pure nothrow @property @safe block_t[] supportBlocks() {
104 				return E[0];
105 			}
106 			
107 			alias slot this;
108 			
109 		}
110 
111 	} else {
112 
113 		class PlaceableItem : GenericPlaceableItem {
114 
115 			public override pure nothrow @property @safe @nogc const sul.items.Item data() {
116 				return _data;
117 			}
118 
119 			public override block_t place(World world, BlockPosition position, uint face) {
120 				auto down = world[position - [0, 1, 0]];
121 				if(mixin((){
122 					import std.string : join;
123 					string[] ret;
124 					foreach(cmp ; E) {
125 						ret ~= "down." ~ cmp;
126 					}
127 					return ret.join("&&");
128 				}())) {
129 					return super.place(world, position, face);
130 				} else {
131 					return 0;
132 				}
133 
134 			}
135 			
136 			public override pure nothrow @property @safe @nogc block_t block() {
137 				return _block;
138 			}
139 
140 		}
141 
142 	}
143 
144 }
145 
146 alias PlaceableOnSolidItem(sul.items.Item _data, block_t _block) = PlaceableItem!(_data, _block, "fullUpperShape", "solid", "opacity==15");
147 
148 class WoodItem(sul.items.Item si, block_t[] blocks) : SimpleItem!(si) if(blocks.length == 4) {
149 
150 	alias sul = si;
151 	
152 	public @safe this(E...)(E args) {
153 		super(args);
154 	}
155 	
156 	public override pure nothrow @property @safe @nogc bool placeable() {
157 		return true;
158 	}
159 	
160 	public override block_t place(World world, BlockPosition position, uint face) {
161 		switch(face) {
162 			case Face.EAST:
163 			case Face.WEST:
164 				return blocks[1];
165 			case Face.NORTH:
166 			case Face.SOUTH:
167 				return blocks[2];
168 			default:
169 				return blocks[0];
170 		}
171 	}
172 	
173 	alias slot this;
174 
175 }
176 
177 class TorchItem(sul.items.Item si, block_t[] blocks) : SimpleItem!(si) if(blocks.length == 5) {
178 
179 	alias sul = si;
180 	
181 	public @safe this(E...)(E args) {
182 		super(args);
183 	}
184 	
185 	public override pure nothrow @property @safe @nogc bool placeable() {
186 		return true;
187 	}
188 	
189 	public override block_t place(World world, BlockPosition position, uint face) {
190 		//TODO place if valid surface
191 		return blocks[0];
192 	}
193 	
194 	alias slot this;
195 
196 }
197 
198 class BeansItem(sul.items.Item si, block_t[] blocks) : SimpleItem!(si) if(blocks.length == 4) {
199 
200 	alias sul = si;
201 	
202 	public @safe this(E...)(E args) {
203 		super(args);
204 	}
205 	
206 	public override pure nothrow @property @safe @nogc bool placeable() {
207 		return true;
208 	}
209 	
210 	public override block_t place(World world, BlockPosition position, uint face) {
211 		//TODO place if valid surface
212 		return blocks[0];
213 	}
214 	
215 	alias slot this;
216 
217 }
218 
219 class SlabItem(sul.items.Item si, block_t down, block_t up, block_t doubl) : SimpleItem!(si) {
220 	
221 	alias sul = si;
222 	
223 	public @safe this(E...)(E args) {
224 		super(args);
225 	}
226 	
227 	public override pure nothrow @property @safe @nogc bool placeable() {
228 		return true;
229 	}
230 	
231 	public override block_t place(World world, BlockPosition position, uint face) {
232 		//TODO override onPlaced
233 		return down;
234 	}
235 	
236 	alias slot this;
237 	
238 }
239 
240 class StairsItem(sul.items.Item si, block_t[] orientations) : SimpleItem!(si) if(orientations.length == 8) {
241 
242 	// [east, west, south, north, upper east, upper west, upper south, upper north]
243 
244 	alias sul = si;
245 	
246 	public @safe this(E...)(E args) {
247 		super(args);
248 	}
249 	
250 	public override pure nothrow @property @safe @nogc bool placeable() {
251 		return true;
252 	}
253 	
254 	public override block_t place(World world, BlockPosition position, uint face) {
255 		//TODO override onPlaced
256 		return orientations[0];
257 	}
258 	
259 	alias slot this;
260 	
261 }