]> git.lizzy.rs Git - dragonblocks.git/blob - engine/map_interaction.js
Abstract MapDisplay from Map
[dragonblocks.git] / engine / map_interaction.js
1 /*
2  * map_interaction.js
3  *
4  * Copyright 2020 Elias Fleckenstein <eliasfleckenstein@web.de>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19  * MA 02110-1301, USA.
20  *
21  *
22  */
23
24 dragonblocks.MapInteraction = {
25         initMapInteraction()
26         {
27                 this.tmp.crackDisplay = this.map.entityContainer.appendChild(document.createElement("div"));
28                 this.tmp.crackDisplay.style.position = "absolute";
29                 this.tmp.crackDisplay.style.visibility = "hidden";
30                 this.tmp.crackDisplay.style.backgroundSize = "cover";
31                 this.tmp.crackDisplay.style.height = dragonblocks.settings.mapDisplay.scale + "px";
32                 this.tmp.crackDisplay.style.width = dragonblocks.settings.mapDisplay.scale + "px";
33                 this.tmp.crackDisplay.style.boxShadow = "0 0 0 1px black inset";
34
35                 let self = this;
36
37                 this.tmp.crackDisplay.addEventListener("mouseleave", event => {
38                         self.digStop();
39                         dragonblocks.mapDisplay.getNode(event.srcElement.offsetLeft / dragonblocks.settings.mapDisplay.scale - dragonblocks.mapDisplay.left, event.srcElement.offsetTop / dragonblocks.settings.mapDisplay.scale - dragonblocks.mapDisplay.top).style.boxShadow = "none";
40                 });
41
42                 this.tmp.crackDisplay.addEventListener("mouseover", event => {
43                         dragonblocks.mapDisplay.getNode(event.srcElement.offsetLeft / dragonblocks.settings.mapDisplay.scale - dragonblocks.mapDisplay.left, event.srcElement.offsetTop / dragonblocks.settings.mapDisplay.scale - dragonblocks.mapDisplay.top).style.boxShadow = "0 0 0 1px black inset";
44                 });
45         },
46
47         updateMapInteractionMap()
48         {
49                 this.tmp.crackDisplay = this.map.entityContainer.appendChild(this.tmp.crackDisplay);
50         },
51
52         dig(map, x, y)
53         {
54                 let node = map.getNode(x, y);
55
56                 if (! node)
57                         return false;
58
59                 let nodeDef = node.toNode();
60                 if (nodeDef.ondig && nodeDef.ondig(map, x, y) == false)
61                         return false;
62
63                 nodeDef.playSound("dug");
64
65                 map.setNode(x, y, "air");
66                 map.activate(map, x, y);
67
68                 return true;
69         },
70
71         digStart(x, y)
72         {
73                 let node = this.map.getNode(x, y);
74                 let nodeDef = node.toNode();
75
76                 node.meta.hardness = nodeDef.hardness;
77                 node.meta.causedDamage = 0;
78
79                 if (! this.canReach(x, y))
80                         return;
81
82                 this.tmp.crackDisplay.style.visibility = "inherit";
83                 this.tmp.crackDisplay.style.left = x * dragonblocks.settings.mapDisplay.scale + "px";
84                 this.tmp.crackDisplay.style.top = y * dragonblocks.settings.mapDisplay.scale + "px";
85
86                 dragonblocks.log("Punched Node at (" + x + ", " + y + ")");
87
88                 nodeDef.onpunch && nodeDef.onpunch(this.map, x,y);
89
90                 this.map.activate(x, y);
91
92                 this.digTick(x, y);
93         },
94
95         digTick(x, y)
96         {
97                 let self = this;
98
99                 let node = this.map.getNode(x, y);
100                 if (! node)
101                         return;
102
103                 let nodeDef = node.toNode();
104
105                 let damage = this.tool.calculateDamage(nodeDef);
106                 if (damage == -1)
107                         damage = this.tmp.defaultTool.calculateDamage(nodeDef);
108
109                 node.meta.hardness -= damage;
110                 node.meta.causedDamage += damage;
111
112                 if (isNaN(node.meta.hardness) || node.meta.hardness <= 0) {
113                         this.digEnd(x, y);
114                 } else {
115                         nodeDef.playSound("dig");
116
117                         this.tmp.crackDisplay.style.background = dragonblocks.getTexture("crack" + Math.floor(node.meta.causedDamage / nodeDef.hardness * 5) + ".png");
118                         this.tmp.crackDisplay.style.backgroundSize = "cover";
119                         this.tmp.crackDisplay.style.zIndex = nodeDef.zIndex || "1";
120
121                         this.tmp.digTimeout = setTimeout(_ => {
122                                 self.digTick(x, y);
123                         }, this.tool.interval);
124                 }
125         },
126
127         digEnd(x, y)
128         {
129                 let node = this.map.getNode(x, y);
130
131                 if (! node)
132                         return;
133
134                 let nodeDef = node.toNode();
135
136                 if (this.dig(this.map, x, y))
137                         dragonblocks.handleNodeDrop(this.tmp.mainInventory, nodeDef, this.map, x, y);
138
139                 this.tmp.crackDisplay.style.visibility = "hidden";
140         },
141
142         digStop()
143         {
144                 clearTimeout(this.tmp.digTimeout);
145                 this.tmp.crackDisplay.style.visibility = "hidden";
146         },
147
148         place(map, x, y, node)
149         {
150                 let oldNode = this.map.getNode(x, y);
151
152                 if (! oldNode || oldNode.stable)
153                         return false;
154
155                 if (node.onplace && node.onplace(map, x, y) == false)
156                         return false;
157
158                 map.setNode(x, y, node);
159                 map.activate(x, y);
160
161                 node.playSound("place");
162
163                 return true;
164         },
165
166         build(x, y)
167         {
168                 if (this.canReach(x, y)) {
169                         let oldNodeDef = this.map.getNode(x, y).toNode();
170                         oldNodeDef.onclick && oldNodeDef.onclick(this.map, x, y);
171
172                         if (this.touch(this.map, x, y))
173                                 return;
174
175                         let wielded = this.getWieldedItem();
176                         let itemstack = new dragonblocks.ItemStack();
177
178                         if(! itemstack.addOne(wielded))
179                                 return;
180
181                         let itemDef = itemstack.toItem();
182
183                         if (itemDef instanceof dragonblocks.Node) {
184                                 if (! this.place(this.map, x, y, itemDef) || this.meta.creative)
185                                         wielded.add(itemstack);
186                         } else {
187                                 if (! itemDef.onuse || ! itemDef.onuse(this.map, x, y))
188                                         wielded.add(itemstack);
189                                 else if (this.meta.creative)
190                                         wielded.add(itemstack);
191                         }
192                 }
193         },
194
195         canReach(x, y)
196         {
197                 return this.meta.creative || Math.sqrt(Math.pow(x - this.x, 2) + Math.pow(y - this.y, 2)) <= this.tool.range;
198         }
199 };
200
201 dragonblocks.handleNodeDrop = (inventory, nodeDef, map, x, y) => {
202         dragonblocks.dropItem(inventory.add((nodeDef.drops instanceof Function) ? nodeDef.drops() : nodeDef.drops), map, x + 0.2, y + 0.2);
203 };