· 9 years ago · Jan 30, 2017, 04:26 AM
1package net.cerberusstudios.llama.runecraft;
2
3/*
4 * Thus far have created the three types of waypoint classes
5 * Thus far have created a save method and a collection for these waypoints
6 * Thus far Have created a conversion method.
7 * Have not created initialization methods for each type of class
8 * Have not updated existing WPs to generate new WP classes
9 * Have not updated existing TP/WP checkers to utilize new WPs
10 */
11
12import static net.cerberusstudios.llama.runecraft.EnAction.TP_ALL;
13import static net.cerberusstudios.llama.runecraft.EnAction.TP_ARROWLAUNCH;
14import static net.cerberusstudios.llama.runecraft.EnAction.TP_BROKEN;
15import static net.cerberusstudios.llama.runecraft.EnAction.TP_CATCHALL;
16import static net.cerberusstudios.llama.runecraft.EnAction.TP_DIGGING;
17import static net.cerberusstudios.llama.runecraft.EnAction.TP_INV_HOLDING;
18import static net.cerberusstudios.llama.runecraft.EnAction.TP_PASSIVE;
19import static net.cerberusstudios.llama.runecraft.EnAction.TP_PLACED;
20import static net.cerberusstudios.llama.runecraft.EnAction.TP_RIGHTCLICK;
21import static net.cerberusstudios.llama.runecraft.EnAction.TP_SPEAK;
22import static net.cerberusstudios.llama.runecraft.EnAction.TP_SWING;
23import static net.cerberusstudios.llama.runecraft.EnAction.TP_TELEPORT;
24
25import java.io.BufferedReader;
26import java.io.BufferedWriter;
27import java.io.DataInputStream;
28import java.io.DataOutputStream;
29import java.io.File;
30import java.io.FileInputStream;
31import java.io.FileOutputStream;
32import java.io.FileReader;
33import java.io.FileWriter;
34import java.io.IOException;
35import java.io.InputStreamReader;
36import java.io.ObjectInputStream;
37import java.io.ObjectOutputStream;
38import java.io.PrintWriter;
39import java.util.ArrayList;
40import java.util.Arrays;
41import java.util.Collection;
42import java.util.Collections;
43import java.util.HashMap;
44import java.util.HashSet;
45import java.util.Iterator;
46import java.util.LinkedHashSet;
47import java.util.LinkedList;
48import java.util.List;
49import java.util.Map;
50import java.util.Map.Entry;
51import java.util.Random;
52import java.util.Set;
53import java.util.Timer;
54import java.util.Vector;
55import java.util.logging.Level;
56import java.util.logging.Logger;
57
58import net.cerberusstudios.llama.runecraft.ResidenceChecker.ResFlags;
59
60import org.apache.commons.lang.ArrayUtils;
61
62/**
63 *
64 * @author SuperLlama
65 * @author Zeerix
66 */
67public class Runecraft_MAIN {
68 public static final int WHAT_ARE_YOU_DOING_IN_HERE_YOU_HAXOR = 1337;
69
70 private final String version;
71 public static final int ANIMATION_TICK_RATE = 7; //decrease this for improved performance, increase for faster FTP/Pegasusing.
72 static final int MAX_TIER = 7;
73
74 // *** static data (runes, patterns, etc.) ***
75 public static final int WAYPOINT = 1;
76 public static final int TELEPORTER = 2;
77 // quick TP used to be here
78 public static final int MINESHAFT = 4;
79 int[] fyofs = { 64, 100, 136, 172, 208, 208, 208, 256 - 14 }; // Faith
80 // height
81 // offsets
82
83 public static final int FAITH = 142; // to avoid collisions, Faith is
84 // searched for AFTER the FTP,
85 // Salvation, and Redemption runes.
86 public static final int FREEZER = 6;
87 public static final int SCORCHER = 7;
88 public static final int TIMECONTROL = 8;
89 public static final int COMPASS = 9;
90 public static final int IDENTIFIER = 10;
91 public static final int PASSAGE = 11; // 11-14 (floor), 15-16 (wall)
92 public static final int LEVITATE = 17;
93 public static final int WARPZONE = 18;
94 public static final int FIRETURRET = 20;
95 public static final int TOGGLER = 21;
96 public static final int DISPENSER = 23;
97 public static final int RECALL = 24;
98 public static final int GREENTHUMB = 25;
99 public static final int ORACLE = 26;
100 public static final int FIREPICK = 27;
101 public static final int ICEPICK = 28;
102 public static final int SHIELD = 29;
103 public static final int SHRUB = 30;
104 public static final int LEAFBLOWER = 31;
105 public static final int FARMERCHARM = 32;
106 public static final int POWERHOE = 34;
107 public static final int FIREBLAST = 35;
108 public static final int FIRESWORD = 36;
109 public static final int UNCRAFTER = 37;
110 public static final int DOUBT = 39;
111 public static final int FLP = 40;
112 public static final int MOUND = 42;
113 public static final int DISPEL = 43;
114 public static final int POWERPICK = 45;
115 public static final int EMBEDDER = 46;
116 public static final int WALLMASTER = 48;
117 public static final int BRIDGEMASTER = 55;
118 public static final int STAIRMASTER = 53;
119 public static final int COLDFEET = 50;
120 public static final int DIVERHELM = 52;
121 public static final int WATERPICK = 54;
122 public static final int UNDERWATERPICK = 57;
123 public static final int UNUSED_2 = 58; // 58-59
124 public static final int DEPTHPAPER = 60;
125 public static final int SECRETCHEST = 61; // 61-62
126 public static final int MOUSETRAP = 63; // 63-64
127 public static final int PHASEBLOCKS = 65; // 65
128 public static final int BEACON = 66; // 66-67
129 public static final int PHANTOMTORCH = 68; // 68-69
130 public static final int REDTORCH = 70; // 70-71
131 public static final int SURFACE_TENSION = 72;
132 public static final int ACCELERATOR = 73;
133 public static final int INITIATOR = 74;
134 public static final int ADMINPICK = 75;
135 public static final int SPRINGSTRING = 76; // 76-77
136 public static final int FAIRYBOOTS = 78;
137 public static final int FORCEFIELD = 80;
138 public static final int ENCHANTMENTSWAP = 81; // 81-82
139 public static final int JUDGEMENT = 83;
140 public static final int WALLTELEPORTER = 84; // 84-85
141 public static final int ENDURANCE = 86; // 86-87
142 public static final int LOCKBLOCKS = 88; // 88
143 public static final int LOGRED = 89;
144 public static final int LOGDST = 90;
145 public static final int LOGPAD = 91;
146 public static final int FLARE = 92;
147 public static final int LOGHIT = 93;
148
149 public static final int LOGBLOCK = 94;
150 public static final int LASSO = 95;
151 public static final int FLOTILLA = 96; // 96-97
152 public static final int LIGHTBOW = 98;
153 public static final int MULTIBOW = 99;
154 public static final int REDLIGHTBOW = 100; // redstone version of 98
155 public static final int SPLEEFBLOCKS = 101;
156 public static final int ENGRAVER = 102;
157 public static final int CAULDRON = 103;
158 public static final int POWERDRILL = 104; // 104-105
159 public static final int GLOWARROWBOW = 106;
160 public static final int OVICAPTOR = 107;
161 public static final int TRANSLOCATOR = 108;
162
163 public static final int VFLPNS = 111; // standing version of 40
164 public static final int VFLPEW = 112; // 90' roation of 111
165 public static final int TUNNELSHOVEL = 113; // 113-114 two versions
166 public static final int FTP = 5; // faith teleporter - altered to be 5 to
167 // avoid collisions with the Faith
168 // pattern.
169 public static final int FAITHPOINT = 116; // faith waypoint
170 public static final int PERMANENCE = 118;
171 public static final int LAVAGEL = 119;
172 public static final int SPIDERTOUCH = 120;
173 public static final int PROMETHEUS = 122;
174 public static final int MAGICCAKE = 124;
175 public static final int SPAWNER = 125;
176 public static final int LIGHTSWORD = 126;
177 //
178 public static final int PEGASUS = 128;
179 public static final int BUTTERCURSE = 129; // 129 & 130 slippery fingers
180 // curse and counter
181
182 public static final int CTRI = 110;
183 public static final int CTRI2 = 138;
184 public static final int XYVAZ = 117;
185
186 public static final int TOUCHHEX = 131;
187 public static final int DAMAGEHEX = 132;
188 public static final int PORTALHEX = 133;
189 public static final int QUICKTP = 134;
190 public static final int WHISPERCURSE = 135; // no counter curse.
191 public static final int SUPERSECRETCHEST = 136;
192 public static final int LOGHITE = 139;
193
194 public static final int FAITHIN = 140;
195 public static final int FAITHOUT = 141;
196
197 public static final int WARDLIGHT = 143; // global blanket on Aether Runes
198 // (not established TP/FTP, or
199 // Pegasus runes)
200 public static final int WARDDARK = 144; // global blanket on Void runes
201 public static final int WARDTOOL = 145; // disable all RCTs with a task
202 // below 0 //tool,tp,dngr
203 public static final int WARDTP = 146; // disable TPing into and out of an
204 // area
205 public static final int WARDNGR = 147; // disable Solar Flare, Topsy Turvy,
206 // Faith, embedder tool
207 public static final int TOGGLEBLOCKS = 148;
208 public static final int WALLWPOINT = 149; // North - south
209 public static final int WALLFPOINT = 151; // north - south
210 public static final int TRUENAME = 153; // True name rune with four
211 // orientations 153-156
212 public static final int BABELCURSE = 157; // Babel curse and counter curse
213 // 157 - 158
214 // NOTE, IF YOU CHANGE BABELCURSE'S NUMBER, UPDATE RUNECRAFT.JAVA TO REFLECT
215 // THIS
216 public static final int SMITETRAP = 159;
217 public static final int WARDTRUNAME = 160;
218
219 public static final int LOGSRED = 161;
220 public static final int COMMPEARL = 162;
221 public static final int COMMTOWER = 163;
222
223 public static final int TEMPRUNE = 164;
224
225 public static final int REALITYANCHOR = 165; // The pattern buffer, tells
226 // the linked reality
227 // masters what to copy
228 public static final int REALITYMASTER = 166; // Copies the pattern from the
229 // linked reality anchor
230 public static final int FREIGHTTP = 167;
231 public static final int FREIGHTPOINT = 168; // a WP for moving items between
232 // chests.
233 public static final int MEMENTO = 169;
234 public static final int WARDFLIGHT = 170;
235 public static final int WALLFTP = 171;
236 public static final int HELLMAW = 173;
237 // WALLFTP + 1 = 172
238 public static final int TRUENAMEALTAR = 175;
239 public static final int GENESIS = 178;
240 boolean APRIL_FOOLS = false;
241 // tier list
242 // block tier map
243 static final int[] bt_blockTier = {
244 0, // Air
245 0, // Smooth Stone
246 0, // Grass
247 0, // Dirt
248 1, // Cobblestone
249 1, // Wooden Plank
250 2, // Sapling
251 1, // Bedrock
252 2, // Water
253 2, // Stationary Water
254 3, // Lava
255 3, // Stationary Lava
256 1, // Sand
257 1, // Gravel
258 4, // Gold Ore
259 3, // Iron Ore
260 3, // Coal Ore
261 2, // Wood Log
262 1, // Leaves
263 3, // Sponge
264 2, // Glass
265 4, // Lapis Lazuli Ore
266 5, // Lapis Lazuli Block
267 3, // Dispenser
268 1, // Sandstone
269 3, // Note Block
270 3, // Bed
271 4, // Powered Rail
272 3, // Detector Rail
273 3, // Sticky Piston
274 3, // Cobweb
275 0, // Tall Grass
276 0, // Dead Bush
277 3, // Piston
278 1, // Piston Head
279 2, // Wool
280 0, // Moving Block
281 2, // Dandelion
282 2, // Rose
283 2, // Brown Mushroom
284 2, // Red Mushroom
285 6, // Gold Block
286 4, // Iron Block
287 2, // Double Slab
288 2, // Stone Slab
289 3, // Brick Block
290 4, // TNT
291 3, // Bookshelf
292 3, // Mossy Cobblestone
293 3, // Obsidian
294 1, // Torch
295 1, // Fire
296 6, // Monster Spawner
297 1, // Wooden Stairs
298 2, // Chest
299 3, // Redstone
300 5, // Diamond Ore
301 6, // Diamond Block
302 2, // Crafting Table
303 2, // Wheat
304 1, // Soil
305 1, // Furnace
306 1, // Burning Furnace
307 0, // Sign
308 2, // Wooden Door
309 1, // Ladder
310 3, // Rails
311 1, // Cobblestone Stairs
312 0, // Sign
313 1, // Lever
314 1, // Stone Pressure Plate
315 4, // Iron Door
316 1, // Wooden Pressure Plate
317 3, // Redstone Ore
318 3, // Glowing Redstone Ore
319 3, // Redstone Torch (off)
320 3, // Redstone Torch
321 1, // Stone Button
322 0, // Snow layers
323 1, // Ice
324 1, // Snow
325 1, // Cactus
326 3, // Clay Block
327 2, // Sugar Cane
328 5, // Jukebox
329 1, // Fence
330 3, // Pumpkin
331 1, // Netherrack
332 2, // Soul Sand
333 4, // Glowstone
334 2, // Portal
335 3, // JackOLantern
336 3, // Cake
337 3, // Redstone Repeater (off)
338 3, // Redstone Repeater
339 2, // Locked Chest
340 2, // Trapdoor
341 2, // Stone (Silverfish)
342 2, // Stone Brick
343 2, // Red Mushroom Cap
344 2, // Brown Mushroom Cap
345 3, // Iron Bars
346 1, // Glass Pane
347 2, // Melon Block
348 2, // Pumpkin Stem
349 2, // Melon Stem
350 2, // Vines
351 2, // Fence Gate
352 2, // Brick Stairs
353 2, // Stone Brick Stairs
354 2, // Mycelium
355 2, // Lily Pad
356 2, // Nether Brick
357 2, // Nether Brick Fence
358 2, // Nether Brick Stairs
359 2, // Nether Wart
360 5, // Enchantment Table
361 4, // Brewing Stand
362 4, // Cauldron
363 4, // End Portal
364 6, // End Portal Frame
365 1, // End Stone
366 7, // Dragon Egg
367 4, // Redstone Lamp
368 4, // Redstone Lamp (on)
369 1, // Double Wooden Slab
370 1, // Wooden Slab
371 2, // Cocoa Plant
372 1, // Sandstone Stairs
373 5, // Emerald Ore
374 4, // Ender Chest
375 3, // Tripwire Hook
376 1, // Tripwire
377 6, // Emerald Block
378 1, // Stairs
379 1, // Stairs
380 1, // Stairs
381 1, // Command Block
382 7, // Beacon
383 1, // Cobblestone Wall
384 3, // Flower Pot
385 2, // Carrots
386 2, // Potatoes
387 1, // Wooden Button
388 2, // Head
389 5, // Anvil
390
391 3, // trapped chest
392 4, // gold pressure plate
393 3, // iron pressure plate
394 3, // comparator
395 3, // comparator
396 3, // daylight sensor
397 4, // redstone block
398 2, // quartz ore
399 3, // hopper
400 2, // quartz block
401 2, // quartz stairs
402 3, // activator rail
403 3, // dropper
404 1, // stained clay
405 1, // stained glass pane
406 1, // leaves 2
407 2, // log 2
408 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
409 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
410 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
411 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
412 1, 1, 1, 1, 1, 1, 1, // 251-255:
413 };
414
415 static HashMap<String, List<Integer>> runeUsesTable = new HashMap<String, List<Integer>>();
416 static HashMap<Integer, String> runeIdToRuneNameTable = new HashMap<Integer, String>();
417 // block meta tier map
418 static HashMap<Integer, List<Integer>> bmt = new HashMap<Integer, List<Integer>>();
419 public Set<rcm> precs = Collections.synchronizedSet(new HashSet<rcm>());
420
421 // OLD NORTH IS THIS WAY IN ARRAYS
422 // <-----------
423 // ^ NEW NORTH IS THIS WAY
424 // |
425 // |
426 // |
427
428 // rune patterns
429 // # :block id
430 // 0 :any tier zero
431 // 1 :ink
432 // 2 :signature
433 // -odd :Rune dimensions
434 // -2 :up
435 // -4 :down
436 // -6 :return to start
437 // -8 :decrement
438 // -10 :new layer dimension
439 // -12 :stone?
440 // -14 :air, or anything
441 // -16 :keystone?
442 // -18 :Start repetition
443 // -20 :End repetition
444 // -22 :New line for repetition?
445 // -24 :Tool identify
446 // -26 :Block identify?
447 // -28 :arbitrary parameter?
448 // -30 :end start parameters
449 static int[][] wr_runeTemplateArray = {
450 { -5, -5, -28, 2, -30, 0, 1, 1, 1, 0, 1, 1, 2, 1, 1, 1, 2, 1, 2, 1,
451 1, 1, 2, 1, 1, 0, 1, 1, 1, 0 }, // 1, waypoint
452 { -5, -5, -28, 2, -30, 0, 1, 2, 1, 0, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2,
453 1, 1, 1, 1, 1, 0, 1, 2, 1, 0 }, // 2, teleporter
454 { -1, -1, 9001 }, // 3, consumable teleporter
455 { -7, -7, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 0, 55, 55, 0,
456 55, 55, 55, 0, 55, 55, 0, 55, 1, 55, 0, 55, 55, 0, 55, 55,
457 55, 0, 55, 55, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55,
458 55, -2, -10, 3, 3, -6, 0, 4, 0, 4, 4, 4, 0, 4, 0, -2, -10,
459 5, 5, -6, 0, 0, 4, 0, 0, 0, 0, 4, 0, 0, 4, 4, 4, 4, 4, 0,
460 0, 4, 0, 0, 0, 0, 4, 0, 0, -2, -10, 3, 3, -6, 0, 0, 0, 0,
461 4, 0, 0, 0, 0, -2,
462
463 -6, 0, 0, 0, 0, 4, 0, 0, 0, 0 }, // 4, mine shaft digger ^
464 { -7, -7, -28, 2, -30, 0, 0, 1, 2, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1,
465 1, 41, 1, 41, 1, 1, 2, 1, 1, 41, 1, 1, 2, 1, 1, 41, 1, 41,
466 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 2, 1, 0, 0 }, // 5,
467 // Faith
468 // teleport.
469 // Old
470 // Faith
471 // now
472 // 115
473 { -5, -5, 76, 20, 20, 20, 76, 20, 8, 8, 8, 20, 20, 8, 14, 8, 20,
474 20, 8, 8, 8, 20, 76, 20, 20, 20, 76 }, // 6, flash freeze ^
475 { -5, -5, 55, 55, 20, 55, 55, 55, 20, 10, 20, 55, 20, 10, 41, 10,
476 20, 55, 20, 10, 20, 55, 55, 55, 20, 55, 55 }, // 7, solar
477 // flare ^
478 { -3, -3, 41, 41, 41, 41, 57, -8, -4, 42, -8, -4, 42, -2, -2, // stem
479 49, 49, 49, 49 }, // 8, time controller
480 { -3, -3, -28, 2, -30, 1, -14, 1, -14, 1, -14, 1, -14, 1 }, // 9,
481 // compass
482 { -3, -3, -28, 2, -30, 55, 55, 55, 55, 20, 55, 55, 55, 55, -2,
483
484 -6, 0, 0, 0, 0, 20, 0, 0, 0, 0 }, // 10, identifier
485 { -3, -3, 1, 15, 1, 15, -16, 15, 1, 1, 1 },
486 { -3, -3, 1, 15, 1, 1, -16, 15, 1, 15, 1 },
487 { -3, -3, 1, 1, 1, 15, -16, 15, 1, 15, 1 },
488 { -3, -3, 1, 15, 1, 15, -16, 1, 1, 15, 1 }, // 11-14, secret floor
489 // passageways
490 { -1, -3, -4, 1, 15, 1, -2, -6, 15, -16, 15, -2, -6, 1, 1, 1, -4,
491 -4, -18, -4, // start the downward progression
492 -6, 15, 1, 15, -22, -4, -6, 1, 15, 1, -20 },
493 { -3, -1, -4, 1, 15, 1, -2, -6, 15, -16, 15, -2, -6, 1, 1, 1, -4,
494 -4, -18, -4, // start the downward progression
495 -6, 15, 1, 15, -22, -4, -6, 1, 15, 1, -20 }, // 15-16,
496 // secret
497 // wall
498 // passageways
499 { -3, -3, 0, 1, 0, 1, 0, 1, 0, 1, 0, -2,
500
501 -6, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2,
502
503 -6, 0, 0, 0, 0, 1, 0, 0, 0, 0, -2,
504
505 -6, 0, 0, 0, 0, 76, 0, 0, 0, 0 }, // 17, hover bacon ^
506 { -3, -3, 0, 4, 0, 4, 0, 4, 0, 4, 0, -2,
507
508 -6, 4, 4, 4, 4, 0, 4, 4, 4, 4 }, // 18, Warp Zone ^
509 { -3, -3, -4, 0, 4, 0, 4, 0, 4, 0, 4, 0, -4,
510
511 -6, 4, 4, 4, 4, 0, 4, 4, 4, 4 }, // 19, Warp Zone bottom ^
512 { -5, -5, 75, 187, 44, 44, 76, 44, 42, 146, -8, -16, 42, 187, 44,
513 42, -8, -16, 20, 42, 44, 187, 146, 42, 42, 44, 76, 44, 44,
514 187, -8, -16, 75 }, // 20, LAZOR TURRET ^
515 { -3, -3, -28, 2, -30, 15, 1, 15, 1, 2, 1, 15, 1, 15 }, // 21,
516 // Toggler ^
517 { -1, -3, 87, -28, 2, -30, -4, 15, 1, 15, -2, -6, 1, 2, 1, -2, -6,
518 15, 1, 15, },
519 { -3, -1, 87, -28, 2, -30, -4, 15, 1, 15, -2, -6, 1, 2, 1, -2, -6,
520 15, 1, 15 }, // 22-23, Wall Togglers ^
521 { -5, -5, -28, 2, -30, 0, 55, 55, 55, 0, 55, 0, 0, 0, 55, 55, 0,
522 76, 0, 55, 55, 0, 0, 0, 55, 0, 55, 55, 55, 0 }, // 24,
523 // recall
524 { -3, -3, -24, 284, -24, 256, -24, 277, -30, 55, 37, 55, 37, 1, 37,
525 55, 37, 55 }, // 25, green thumb
526 { -3, -3, -28, 2, -30, 55, 55, 55, 55, 1, 55, 55, 55, 55, -2,
527
528 -6, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 26, oracle
529 { -5, -5, -24, 257, -24, 285, -24, 278, -30, 50, 55, 55, 55, 50,
530 55, 55, 50, 55, 55, 55, 50, 1, 50, 55, 55, 55, 50, 55, 55,
531 50, 55, 55, 55, 50 }, // 27, fire pick
532 { -5, -5, -24, 257, -24, 285, -24, 278, -30, 0, 55, 20, 55, 0, 55,
533 80, 55, 80, 55, 20, 55, 1, 55, 20, 55, 80, 55, 80, 55, 0,
534 55, 20, 55, 0 }, // 28, ice pick
535 { -5, -5, -24, 283, -24, 276, -24, 267, -30, 0, 55, 55, 55, 0, 55,
536 20, 0, 20, 55, 55, 0, 76, 0, 55, 55, 20, 0, 20, 55, 0, 55,
537 55, 55, 0 }, // 29, shield
538 { -3, -3, -24, 6, -30, 17, 18, 17, 18, 1, 18, 17, 18, 17 }, // 30,
539 // shrub
540 // growth
541 { -5, -5, -24, 258, -24, 286, -24, 279, -30, 0, 55, 55, 55, 0, 55,
542 17, 55, 17, 55, 55, 55, 1, 55, 55, 55, 17, 55, 17, 55, 0,
543 55, 55, 55, 0 }, // 31, leafblower
544 { -5, -5, -24, 292, -24, 293, -24, 294, -30, 0, 0, 76, 0, 0, 0, 55,
545 59, 55, 0, 55, 59, 17, 59, 55, 0, 55, 59, 55, 0, 0, 0, 76,
546 0, 0 },
547 { -5, -5, -24, 292, -24, 293, -24, 294, -30, 0, 0, 55, 0, 0, 0, 55,
548 59, 55, 0, 76, 59, 17, 59, 76, 0, 55, 59, 55, 0, 0, 0, 55,
549 0, 0 }, // 32-33, farmer's charm
550 { -3, -3, -24, 292, -24, 293, -24, 294, -30, 1, 55, 1, 55, 59, 55,
551 1, 55, 1 }, // 34, power hoe
552 { -5, -5, -24, 283, -24, 276, -24, 267, -30, 76, 55, 0, 55, 76, 55,
553 55, 50, 55, 55, 0, 50, 1, 50, 0, 55, 55, 50, 55, 55, 76,
554 55, 0, 55, 76 }, // 35, pyrokinesis
555 { -5, -5, -24, 283, -24, 276, -24, 267, -30, 55, 55, 87 - 87, 55,
556 55, 55, 50, 1, 50, 55, 0, 1, 1, 1, 0, 55, 50, 1, 50, 55,
557 55, 55, 0, 55, 55 }, // 36, fire sword
558 { -5, -5, -24, 257, -24, 285, -24, 278, -30, 0, 0, 55, 0, 0, 0, 55,
559 1, 1, 0, 1, 55, 76, 55, 1, 0, 1, 1, 55, 0, 0, 0, 55, 0, 0 },
560 { -5, -5, -24, 257, -24, 285, -24, 278, -30, 0, 0, 1, 0, 0, 0, 1,
561 55, 55, 0, 55, 1, 76, 1, 55, 0, 55, 55, 1, 0, 0, 0, 1, 0, 0 }, // 37-38,
562 // uncrafter
563 { -3, -3, -28, 2, -30, 0, 0, 0, 0, 75, 0, 0, 0, 0, -4, -6, 88, 1,
564 88, 1, 88, 1, 88, 1, 88, }, // 39, doubt (faith removal)
565 { -5,
566 -5,// -28,2,-30,
567 0, 0, 1, 0, 0, 0, 42, 0, 42, 0, 1, 0, 41, 0, 1, 0, 42, 0,
568 42, 0, 0, 0, 1, 0, 0 }, // 40, topsy turvy
569 { -5,
570 -5,// -28,2,-30,
571 0, 0, 42, 0, 0, 0, 1, 0, 1, 0, 42, 0, 41, 0, 42, 0, 1, 0,
572 1, 0, 0, 0, 42, 0, 0 }, // 41, topsy turvy
573 { -5, -5, 55, 55, 1, 55, 55, 55, 0, 0, 0, 55, 1, 0, 1, -8, -2, 76,
574 -4, 0, 1, 55, 0, 0, 0, 55, 55, 55, 1, 55, 55 }, // 42, mound
575 { -5, -5, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1,
576 1, 0, 1, 1, 1, 0, },
577 { -5, -5, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0,
578 1, 0, 1, 1, 1, 0, }, // 43-44, dispel
579 { -5, -5, -24, 257, -24, 285, -24, 278, -24, 284, -24, 256, -24,
580 277, -24, 286, -24, 279, -24, 258, -24, 359, -30, 55, 0,
581 76, 0, 55, 0, 1, 55, 1, 0, 76, 55, 0, 55, 76, 0, 1, 55, 1,
582 0, 55, 0, 76, 0, 55, }, // 45, power pick
583 { -5, -5, -28, 3, -26, 338, -26, 259, -30, 0, 0, 55, 0, 0, 55, 0,
584 55, 0, 55, 55, 0, 1, 0, 55, 55, 0, 55, 0, 55, 0, 0, 55, 0,
585 0, },
586 { -5, -5, -28, 3, -26, 338, -26, 259, -30, 0, 55, 55, 55, 0, 0, 0,
587 0, 0, 0, 55, 55, 1, 55, 55, 0, 0, 0, 0, 0, 0, 55, 55, 55,
588 0, }, // 46-47, embedder
589 { -5, -5, 0, 55, 2, 55, 0, 55, 55, 1, 55, 55, 0, 55, 76, 55, 0, 55,
590 55, 1, 55, 55, 0, 55, 2, 55, 0, },
591 { -5, -5, 0, 55, 0, 55, 0, 55, 55, 55, 55, 55, 2, 1, 76, 1, 2, 55,
592 55, 55, 55, 55, 0, 55, 0, 55, 0, }, // 48-49, wallmaster
593 { -3, -3, -24, 309, -24, 313, -24, 317, -30, 79, 55, 79, 1, 55, 1,
594 79, 55, 79, },
595 { -3, -3, -24, 309, -24, 313, -24, 317, -30, 79, 1, 79, 55, 55, 55,
596 79, 1, 79, }, // 50-51, cold feet
597 { -5, -5, -24, 306, -24, 310, -24, 314, -30, 1, 8, 8, 8, 1, 8, 8,
598 20, 8, 8, 8, 20, 0, 20, 8, 8, 8, 20, 8, 8, 1, 8, 8, 8, 1 }, // 52,
599 // diver's
600 // helmet
601 { -5, -5, 76, 0, 0, 0, 76, 0, 44, 44, 44, 0, 0, 44, 1, 44, 0, 0,
602 44, 44, 44, 0, 76, 0, 0, 0, 76, }, // 53, stair master
603 { -5, -5, -24, 257, -24, 285, -24, 278, -30, 0, 55, 76, 55, 0, 55,
604 55, 1, 55, 55, 76, 1, 8, 1, 76, 55, 55, 1, 55, 55, 0, 55,
605 76, 55, 0, }, // 54, water pick
606 { -5, -5, 0, 55, 2, 55, 0, 55, 55, 55, 55, 55, 0, 1, 76, 1, 0, 55,
607 55, 55, 55, 55, 0, 55, 2, 55, 0 }, // 55, bridge master
608 { -5, -5, 0, 55, 0, 55, 0, 55, 55, 1, 55, 55, 2, 55, 76, 55, 2, 55,
609 55, 1, 55, 55, 0, 55, 0, 55, 0 }, // 56, bridge m. (2)
610 { -5, -5, -24, 257, -24, 285, -24, 278, -24, 284, -24, 256, -24,
611 277, -30, 0, 55, 76, 55, 0, 55, 55, 1, 55, 55, 76, 1, 20,
612 1, 76, 55, 55, 1, 55, 55, 0, 55, 76, 55, 0 }, // 57,
613 // underwater
614 // pick
615 { -3, -3, -30 },
616 { -3, -3, -30 }, // 58-59, unused (deactivated)
617 { -5, -5, -24, 339, -30, 0, 35, 1, 35, 0, 35, 55, 55, 55, 35, 1,
618 55, 0, 55, 1, 35, 55, 55, 55, 35, 0, 35, 1, 35, 0 }, // 60,
619 // depth
620 // paper
621 { -1, -3, -24, 280, -30, -4, 1, 54, 1, -2, -6, 14, 1, 14, -2, -6,
622 0, 1, 0 },
623 { -3, -1, -24, 280, -30, -4, 1, 54, 1, -2, -6, 14, 1, 14, -2, -6,
624 0, 1, 0 }, // 61-62, secret/zeerix' chest
625 { -5, -5, -28, 2, -30, 1, 0, 49, 49, 0, 0, 0, 49, 0, 76, 55, 55,
626 55, 55, 55, 76, 0, 49, 0, 0, 0, 49, 49, 0, 1 },
627 { -5, -5, -28, 2, -30, 0, 76, 55, 0, 1, 49, 0, 55, 0, 0, 49, 49,
628 55, 49, 49, 0, 0, 55, 0, 49, 1, 0, 55, 76, 0 }, // 63-64,
629 // mouse
630 // trap.
631 { -5, -5, -28, 3, -26, 331, -26, 295, -26, 326, -26, 327, -26, 338,
632 -26, 259, -26, 54, -30, 0, 1, 1, 1, 0, 1, 2, 15, 2, 1, 1,
633 15, 1, 15, 1, 1, 2, 15, 2, 1, 0, 1, 1, 1, 0, }, // 65, phase
634 // blocks
635 { -3, -3, -28, 2, -30, 0, 1, 0, 55, 50, 55, 0, 1, 0 },
636 { -3, -3, -28, 2, -30, 0, 55, 0, 1, 50, 1, 0, 55, 0 }, // 66-67
637 // beacon
638 { -3, -3, 55, 50, 55, 0, 1, 0, 55, 50, 55 },
639 { -3, -3, 55, 0, 55, 50, 1, 50, 55, 0, 55 }, // 68-69, phantom torch
640 { -3, -3, 55, 76, 55, 0, 1, 0, 55, 76, 55 },
641 { -3, -3, 55, 0, 55, 76, 1, 76, 55, 0, 55 }, // 70-71, phantom torch
642 // (red)
643 { -3, -3, -24, 341, -30, 20, 80, 20, 80, 8, -4, -8, 1, -2, 80, 20,
644 80, 20 }, // 72, surface tension
645 { -5, -5, -28, 2, -30, 50, 55, 23, 55, 50, 55, 35, 35, 35, 55, 23,
646 35, 1, 35, 23, 55, 35, 35, 35, 55, 50, 55, 23, 55, 50 }, // 73,
647 // accelerator
648 { -5, -5, 7, 7, 0, 7, 7, 7, 50, 7, 50, 7, 0, 7, 10, 7, 0, 7, 50, 7,
649 50, 7, 7, 7, 0, 7, 7 }, // 74, initiator
650 { -5, -5, 7, 0, 7, 0, 7, 0, 7, 0, 7, 0, 7, 0, 1, 0, 7, 0, 7, 0, 7,
651 0, 7, 0, 7, 0, 7 }, // 75, admin pick
652 { -3, -3, -24, 287, -30, 76, 55, 55, 0, 1, 0, 55, 55, 76 },
653 { -3, -3, -24, 287, -30, 55, 0, 76, 55, 1, 55, 76, 0, 55 }, // 76-77,
654 // spring
655 // string
656 { -3, -3, -24, 309, -24, 313, -24, 317, -30, 35, 55, 35, 1, 55, 1,
657 35, 55, 35, },
658 { -3, -3, -24, 309, -24, 313, -24, 317, -30, 35, 1, 35, 55, 55, 55,
659 35, 1, 35, }, // 78-79, fairy boots (UNFINISHED)
660 { -3, -3, 20, 55, 20, 55, 1, -2, -8, 2, -2, -8, 2, -4, -4, 55, 20,
661 55, 20 }, // 80, force field
662 { -7, -5, 0, 50, 0, 0, 0, 50, 0, 1, 1, 1, 0, 1, 1, 1, 1, 55, 55,
663 76, 55, 55, 1, 1, 1, 1, 0, 1, 1, 1, 0, 50, 0, 0, 0, 50, 0 },
664 { -5, -7, 0, 1, 1, 1, 0, 50, 1, 55, 1, 50, 0, 1, 55, 1, 0, 0, 0,
665 76, 0, 0, 0, 1, 55, 1, 0, 50, 1, 55, 1, 50, 0, 1, 1, 1, 0 }, // 81-82,
666 // enchantment
667 // swap
668 { -3, -3, 7, 7, 41, 7, 10, 7, 7, 7, 41, -2,
669
670 -6, 7, 7, 2, 7, 0, 0, 7, 7, 2, -2,
671
672 -6, 41, 0, 0, 7, -2, -8, 50, -4, 7, 0, 41, 0, 0 }, // 83, altar of
673 // judgment
674 { -5, -1, -28, 2, -30, -4, -4, 0, 1, 2, 1, 0, -2, -6, 1, 1, 1, 1,
675 1, -2, -6, 2, 1, 2, 1, 2, -2, -6, 1, 1, 1, 1, 1, -2, -6, 0,
676 1, 2, 1, 0 }, // 84, N/S vertical teleporter
677 { -1, -5, -28, 2, -30, -4, -4, 0, 1, 2, 1, 0, -2, -6, 1, 1, 1, 1,
678 1, -2, -6, 2, 1, 2, 1, 2, -2, -6, 1, 1, 1, 1, 1, -2, -6, 0,
679 1, 2, 1, 0 }, // 85, E/W vertical teleporter
680 { -5, -5, 0, 55, 0, 55, 0, 0, 0, 50, 0, 0, 55, 50, 1, 50, 55, 0, 0,
681 50, 0, 0, 0, 55, 0, 55, 0 },
682 { -5, -5, 0, 0, 55, 0, 0, 55, 0, 50, 0, 55, 0, 50, 1, 50, 0, 55, 0,
683 50, 0, 55, 0, 0, 55, 0, 0 }, // 86-87, endurance
684 { -5, -5, -28, 3, -26, 331, -26, 295, -26, 326, -26, 327, -26, 338,
685 -26, 259, -30, 0, 1, 1, 1, 0, 1, 2, 14, 2, 1, 1, 14, 2, 14,
686 1, 1, 2, 14, 2, 1, 0, 1, 1, 1, 0, }, // 88, lock blocks
687 { -3, -3, -28, 2, -30, -4, 0, 2, 0, 2, 42, 2, 0, 2, 0, -2,
688
689 -6, 0, 55, 0, 55, 2, -2, -8, 33, -4, 55, 0, 55, 0 }, // 89, logic
690 // transmitter
691 // (RS)
692 { -3, -3, -28, 2, -30, 14, 2, 14, 2, 55, 2, 14, 2, 14, -2,
693
694 -6, 0, 55, 0, 55, 2, 55, 0, 55, 0 }, // 90, logic receiver
695 { -5, -5, -28, 2, -30, 42, 35, 35, 35, 42, 35, 1, 2, 1, 35, 35, 2,
696 2, 2, 35, 35, 1, 2, 1, 35, 42, 35, 35, 35, 42, -2,
697
698 -6, 76, 0, 55, 0, 76, 0, 0, 55, 0, 0, 55, 55, 55, 55, 55,
699 0, 0, 55, 0, 0, 76, 0, 55, 0, 76 }, // 91, logic pad
700 { -5, -5, -28, 2, -30, 0, 0, 51, 0, 0, 0, 1, 55, 1, 0, 51, 55, 2,
701 55, 51, 0, 1, 55, 1, 0, 0, 0, 51, 0, 0 }, // 92, flare
702 { -5, -5, -28, 2, -30, 0, 0, 2, 0, 0, 0, 55, 55, 55, 0, 2, 55, 76,
703 -2, -8, 1, -2, -8, 1, -2, -8, 2, -4, -4, -4, 55, 2, 0, 55,
704 55, 55, 0, 0, 0, 2, 0, 0 }, // 93, logic transmitter (on
705 // hit)
706 { -3, -3, -28, 2, -30, -4, 1, 2, 1, 2, 2, 2, 1, 2, 1, -2,
707
708 -6, 55, 42, 55, 42, -16, 42, 55, 42, 55 }, // 94, logic transmitter
709 // (block place)
710 { -5, -5, -24, 287, -30, 76, 0, 55, 0, 76, 0, 55, 55, 55, 0, 55,
711 55, 1, -2, -8, 55, -4, 55, 55, 0, 55, 55, 55, 0, 76, 0, 55,
712 0, 76 }, // 95, lasso rune
713 { -3, -3, -24, 281, -30, 55, 0, 55, 17, 17, 17, 55, 0, 55, -2,
714
715 -6, 0, 0, 0, 17, 0, 17, 0, 0, 0 },
716 { -3, -3, -24, 281, -30, 55, 17, 55, 0, 17, 0, 55, 17, 55, -2,
717
718 -6, 0, 17, 0, 0, 0, 0, 0, 17, 0 }, // 96-97, flotilla rune
719 { -3, -3, -24, 261, -30, 1, 55, 1, 55, 50, 55, 1, 55, 1 }, // 98,
720 // light
721 // bow
722 { -5, -5, -24, 261, -30, 0, 0, 55, 0, 0, 0, 1, 55, 1, 0, 55, 55, 0,
723 55, 55, 0, 1, 55, 1, 0, 0, 0, 55, 0, 0 }, // 99, multishot
724 // bow
725 { -3, -3, -24, 261, -30, 1, 55, 1, 55, 76, 55, 1, 55, 1 }, // 100,
726 // red
727 // light
728 // bow
729 { -5, -5, -28, 3, -26, 331, -26, 295, -26, 326, -26, 327, -26, 338,
730 -26, 259, -26, 54, -30, 0, 1, 1, 1, 0, 1, 2, 80, 2, 1, 1,
731 80, 1, 80, 1, 1, 2, 80, 2, 1, 0, 1, 1, 1, 0, }, // 101,
732 // spleef
733 // blocks
734 { -3, -3, -28, 2, -30, 55, 49, 55, 49, 22, 49, 55, 49, 55, -2,
735
736 -6, 0, 55, 0, 55, 0, 55, 0, 55, 0 }, // 102, engraver
737 { -3, -3, -28, 2, -30, 55, 80, 55, 80, 118, 80, 55, 80, 55 }, // 103,
738 // bottomless
739 // cauldron
740 { -3, -3, -24, 257, -24, 285, -24, 278, -24, 284, -24, 256, -24,
741 277, -24, 286, -24, 279, -24, 258, -30, 1, 76, 55, 76, 0,
742 76, 55, 76, 1, },
743 { -3, -3, -24, 257, -24, 285, -24, 278, -24, 284, -24, 256, -24,
744 277, -24, 286, -24, 279, -24, 258, -30, 55, 76, 1, 76, 0,
745 76, 1, 76, 55, }, // 104-105, power drill
746 { -3, -3, -24, 261, -30, 1, 55, 1, 55, 46, 55, 1, 55, 1, // */
747 }, // 106, Siege Bow
748 { -3, -3, -28, 2, -30, -16, -16, -16, -16, 111, -4, -6, 76, 121,
749 76, 121, 8, 121, 76, 121, 76 }, // 107, ovicaptor
750 { -5, -5, -24, 261, -30, 0, 55, 0, 0, 0, 87, 55, 0, 76, 0, 0, 55,
751 1, 55, 0, 0, 76, 0, 55, 87, 0, 0, 0, 55, 0 }, // 108-109,
752 // bow of
753 // translocation
754 { -5, -5, -24, 261, -30, 0, 0, 0, 87, 0, 0, 76, 55, 55, 55, 0, 0,
755 1, 0, 0, 55, 55, 55, 76, 0, 0, 87, 0, 0, 0 },// 109, bow of
756 // translocation
757 { -3, -3, -28, 2, -30,
758
759 0, 41, 0, 41, 9, 41, 0, 41, 0,
760
761 }, // 110, Immersion. Debug rune.
762 { -5,
763 -1,// -28,2,-30,
764 -4, -4, 0, 0, 1, 0, 0, -2, -6, 0, 42, 0, 42, 0, -2, -6, 1,
765 0, 41, 0, 1, -2, -6, 0, 42, 0, 42, 0, -2, -6, 0, 0, 1, 0, 0 }, // 111,
766 // N/S
767 // vertical
768 // TT
769 { -1,
770 -5,// -28,2,-30,
771 -4, -4, 0, 0, 1, 0, 0, -2, -6, 0, 42, 0, 42, 0, -2, -6, 1,
772 0, 41, 0, 1, -2, -6, 0, 42, 0, 42, 0, -2, -6, 0, 0, 1, 0, 0 }, // 112,
773 // E/W
774 // vertical
775 // TT
776 { -5, -5, -24, 257, -24, 285, -24, 278, -24, 284, -24, 256, -24,
777 277, -30, 0, 55, 76, 55, 0, 55, 55, 1, 55, 55, 76, 1, 12,
778 1, 76, 55, 55, 1, 55, 55, 0, 55, 76, 55, 0 }, // 113, Gravel
779 // Shovel
780 // (sand
781 // centre)
782 { -5, -5, -24, 257, -24, 285, -24, 278, -24, 284, -24, 256, -24,
783 277, -30, 0, 55, 76, 55, 0, 55, 55, 1, 55, 55, 76, 1, 13,
784 1, 76, 55, 55, 1, 55, 55, 0, 55, 76, 55, 0 }, // 114, Gravel
785 // Shovel
786 // (gravel
787 // centre)
788 { -1, -1, -1 }, // 115
789 { -7, -7, -28, 2, -30, 0, 0, 1, 1, 1, 0, 0, 0, 1, 2, 2, 2, 1, 0, 1,
790 2, 1, 2, 1, 2, 1, 1, 2, 2, 57, 2, 2, 1, 1, 2, 1, 2, 1, 2,
791 1, 0, 1, 2, 2, 2, 1, 0, 0, 0, 1, 1, 1, 0, 0 }, // 116 Faith
792 // WP. PH
793 // pattern
794 { -3, -3, -24, 257, -24, 285, -24, 278, -24, 284, -24, 256, -24,
795 277, -24, 286, -24, 279, -24, 258, -30, 0, 57, 0, 55, 122,
796 55, 76, 0, 76 }, // 117, Xyvaz's Tester Rune
797 { -11, -11, -28, 2, -30,
798 /*-24,257,-24,285,-24,278,-24,284,-24,256,-24,277,-24,286,-24,279,-24,258,-24,261,-24,283,-24,276,-24,267,-24,359,
799 -24,302,-24,303,-24,304,-24,305,-24,306,-24,307,-24,308,-24,309,-24,310,-24,311,-24,312,-24,313,-24,314,-24,315,-24,316,-24,317,-30, /**/
800 0, 0, 0, 76, 0, 57, 0, 76, 0, 0, 0, 0, 0, 0, 0, 0, 55, 0, 0, 0, 0,
801 0, 0, 57, 55, 55, 0, 55, 0, 55, 55, 57, 0, 0, 0, 0, 55, 55,
802 55, 55, 55, 0, 0, 0, 76, 0, 55, 55, 55, 0, 55, 55, 55, 0,
803 76, 0, 0, 55, 0, 55, 122, 55, 0, 55, 0, 0, 57, 55, 55, 55,
804 55, 55, 55, 55, 55, 55, 57, 0, 0, 0, 55, 55, 0, 55, 55, 0,
805 0, 0, 0, 76, 0, 55, 0, 0, 0, 55, 0, 76, 0, 0, 0, 0, 57, 0,
806 0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 76, 0, 0, 0, 0, 0 }, // 118,
807 // Permanence
808 { -3, -3, -24, 378, -30, 89, 112, 89, 112, 10, -4, -8, 1, -2, 112,
809 89, 112, 89 }, // 119, Lava Gel
810 { -5, -5, -24, 359, -30, 76, 1, 76, 1, 76, 1, 30, 30, 30, 1, 76,
811 85, 30, 85, 76, 1, 30, 30, 30, 1, 76, 1, 76, 1, 76 },
812 { -5, -5, -24, 359, -30, 76, 1, 76, 1, 76, 1, 30, 85, 30, 1, 76,
813 30, 30, 30, 76, 1, 30, 85, 30, 1, 76, 1, 76, 1, 76 }, // 120,121,
814 // Spider
815 // Touch
816 { -5, -5, 1, 1, 76, 101, 101, 1, 101, 101, 101, 101, 76, 101, 51,
817 101, 76, 101, 101, 101, 101, 1, 101, 101, 76, 1, 1 },
818 { -5, -5, 101, 101, 76, 1, 1, 101, 101, 101, 101, 1, 76, 101, 51,
819 101, 76, 1, 101, 101, 101, 101, 1, 1, 76, 101, 101 }, // 122,123
820 // Prometheus
821 { -3, -3, -24, 344, -30, 76, 76, 76, 83, 42, 83, 59, 59, 59 }, // 124,
822 // Magic
823 // Cake
824 { -5, -5, -24, 383, -30, 76, 55, 101, 55, 76, 55, 57, 101, 57, 55,
825 101, 101, 52, 101, 101, 55, 57, 101, 57, 55, 76, 55, 101,
826 55, 76, -2, -6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 0,
827 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 125 Spawner
828 { -5, -5, -24, 267, -24, 276, -24,
829 283, // swords
830 -24, 258, -24, 279, -24,
831 286, // axes
832 -24, 256, -24, 277, -24,
833 284, // spades
834 -24, 257, -24, 278, -24, 285,
835 -30, // picks
836 55, 55, 0, 55, 55, 55, 51, 1, 51, 55, 0, 1, 1, 1, 0, 55,
837 51, 1, 51, 55, 55, 55, 0, 55, 55 }, // 126, light sword
838 { -3, -3,
839
840 // require block in hand but disallow block placing tools
841 -28, 3, -26, 331, -26, 295, -26, 326, -26, 327, -26, 338,
842 -26, 259, -30,
843
844 -4, -6, // start on the bottom layer
845 42, 1, 42, 1, 0, 1, 42, 1, 42,
846
847 -2, -6, 1, 0, 1, 0, 41, 0, 1, 0, 1,
848
849 -2, -6, 42, 1, 42, 1, 0, 1, 42, 1, 42,
850
851 }, // 127 Pegasus without block in place (use block in hand)
852 { -3, -3, -28, 2, -30, -4, -6, // start on the bottom layer
853 42, 1, 42, 1, 2, 1, 42, 1, 42,
854
855 -2, -6, 1, 2, 1, 2, 41, 2, 1, 2, 1,
856
857 -2, -6, 42, 1, 42, 1, 2, 1, 42, 1, 42, }, // 128 Pegasus
858 // with block in
859 // place
860 { -5, -5, 76, 55, 85, 55, 76, 55, 55, 79, 55, 55, 85, 79, 1, 79,
861 85, 55, 55, 79, 55, 55, 76, 55, 85, 55, 76 }, // butterfingers
862 { -5, -5, 55, 55, 79, 55, 55, 55, 75, 85, 75, 55, 79, 85, 1, 85,
863 79, 55, 75, 85, 75, 55, 55, 55, 79, 55, 55 }, // butterfingers
864 // countercurse
865 // 130
866 { -5, -5, -24, 264, -30, 0, 55, 76, 55, 0, 55, 1, 77, 1, 55, 76,
867 77, 49, 77, 76, 55, 1, 77, 1, 55, 0, 55, 76, 55, 0 }, // 131
868 { -5, -5, -24, 264, -30, 0, 55, 76, 55, 0, 55, 1, 20, 1, 55, 76,
869 20, 49, 20, 76, 55, 1, 20, 1, 55, 0, 55, 76, 55, 0 }, // 132
870 { -5, -5, -24, 264, -30, 0, 55, 76, 55, 0, 55, 1, 87, 1, 55, 76,
871 87, 49, 87, 76, 55, 1, 87, 1, 55, 0, 55, 76, 55, 0 }, // 133
872
873 { -3, -3, -28, 2, -30, 76, 2, 76, 2, 1, 2, 76, 2, 76 // 134 quicktp
874 },
875 { -5, -5, 76, 55, 63, 55, 76, 55, 55, 35, 55, 55, 63, 35, 49, 35,
876 63, 55, 55, 35, 55, 55, 76, 55, 63, 55, 76 }, // whisperjynx
877 { -1, -3, -24, 280, -30, -4, 1, 130, 1, -2, -6, 14, 1, 14, -2, -6,
878 0, 1, 0 },
879 { -3, -1, -24, 280, -30, -4, 1, 130, 1, -2, -6, 14, 1, 14, -2, -6,
880 0, 1, 0 }, // 136-137, secret/zeerix' ENDER chest
881 { -3, -3, -24, 264, -30, -14, 1, -14, 1, 57, 1, -14, 1, -14 }, // 138,
882 // C'tri's
883 // faith
884 // offsetter.
885 { -5, -5, -28, 3, -30, -4, -4, 0, 0, 2, 0, 0, 0, 55, 55, 55, 0, 2,
886 55, 76, -2, -8, 1, -2, -8, 1, -4, -4, 55, 2, 0, 55, 55, 55,
887 0, 0, 0, 2, 0, 0 }, // 139 LoghitE
888 { -5, -5, -28, 2,
889 -30, // decrease Y by 2. Activated on top tier block
890 0, 7, 7, 7, 0, 7, 41, 2, 41, 7, 7, 2, 41, 2, 7, 7, 41, 2,
891 41, 7, 0, 7, 7, 7, 0 }, // 140 faith in
892 { -5, -5, -28, 2, -30, 0, 7, 7, 7, 0, 7, 7, 2, 7, 7, 7, 2, 57, 2,
893 7, 7, 7, 2, 7, 7, 0, 7, 7, 7, 0 }, // 141 faith out
894
895 { -3, -3, -28, 2, -30, 0, 0, 0, 0, 2, 0, 0, 0, 0, -4,
896
897 -6, 41, 1, 41, 1, 41, 1, 41, 1, 41 }, // 142, bp2008's "Faith" rune
898 // ^
899 { -3, -3, -28, 2, -30, -2, 0, 128, 0, 128, 1, 128, 0, 128, 0, -6,
900 -4, -14, -14, -14, -14, 133, -14, -14, -14, -14, -6, -4, 0,
901 128, 0, 128, 1, 128, 0, 128, 0, -6, -4
902
903 }, // 143, aether ward
904 { -3, -3, -28, 2, -30, -2, 0, 114, 0, 114, 1, 114, 0, 114, 0, -6,
905 -4, -14, -14, -14, -14, 133, -14, -14, -14, -14, -6, -4, 0,
906 114, 0, 114, 1, 114, 0, 114, 0, -6, -4
907
908 }, // 144, void ward
909 { -3, -3, -28, 2, -30, -2, 0, 109, 0, 109, 1, 109, 0, 109, 0, -6,
910 -4, -14, -14, -14, -14, 133, -14, -14, -14, -14, -6, -4, 0,
911 109, 0, 109, 1, 109, 0, 109, 0, -6, -4
912
913 }, // 145 //tool ward
914 { -3, -3, -28, 2, -30, -2, 0, 108, 0, 108, 1, 108, 0, 108, 0, -6,
915 -4, -14, -14, -14, -14, 133, -14, -14, -14, -14, -6, -4, 0,
916 108, 0, 108, 1, 108, 0, 108, 0, -6, -4
917
918 }, // 146 //TP ward
919
920 { -3, -3, -28, 2, -30, -2, 0, 67, 0, 67, 1, 67, 0, 67, 0, -6, -4,
921 -14, -14, -14, -14, 133, -14, -14, -14, -14, -6, -4, 0, 67,
922 0, 67, 1, 67, 0, 67, 0, -6, -4
923
924 }, // 147 danger ward
925 { -5, -5, -28, 3, -26, 331, -26, 295, -26, 326, -26, 327, -26, 338,
926 -26, 259, -26, 54, -30, 0, 1, 1, 1, 0, 1, 2, 33, 2, 1, 1,
927 33, 1, 33, 1, 1, 2, 33, 2, 1, 0, 1, 1, 1, 0, },
928 { -5, -1, -28, 2, -30, -4, -4, 0, 1, 1, 1, 0, -2, -6, 1, 1, 2, 1,
929 1, -2, -6, 1, 2, 1, 2, 1, -2, -6, 1, 1, 2, 1, 1, -2, -6, 0,
930 1, 1, 1, 0 }, // 149, N/S vertical waypoint
931 { -1, -5, -28, 2, -30, -4, -4, 0, 1, 1, 1, 0, -2, -6, 1, 1, 2, 1,
932 1, -2, -6, 1, 2, 1, 2, 1, -2, -6, 1, 1, 2, 1, 1, -2, -6, 0,
933 1, 1, 1, 0 }, // 150, E/W vertical waypoint
934 { -7, -1, -28, 2, -30, -4, -4, -4, 0, 0, 1, 1, 1, 0, 0, -2, -6, 0,
935 1, 2, 2, 2, 1, 0, -2, -6, 1, 2, 1, 2, 1, 2, 1, -2, -6, 1,
936 2, 2, 57, 2, 2, 1, -2, -6, 1, 2, 1, 2, 1, 2, 1, -2, -6, 0,
937 1, 2, 2, 2, 1, 0, -2, -6, 0, 0, 1, 1, 1, 0, 0, }, // 151,
938 // N/S
939 // vertical
940 // waypoint
941 { -1, -7, -28, 2, -30, -4, -4, -4, 0, 0, 1, 1, 1, 0, 0, -2, -6, 0,
942 1, 2, 2, 2, 1, 0, -2, -6, 1, 2, 1, 2, 1, 2, 1, -2, -6, 1,
943 2, 2, 57, 2, 2, 1, -2, -6, 1, 2, 1, 2, 1, 2, 1, -2, -6, 0,
944 1, 2, 2, 2, 1, 0, -2, -6, 0, 0, 1, 1, 1, 0, 0, }, // 152,
945 // E/W
946 // vertical
947 // waypoint
948 { -5, -5, -28, 2, -30, 0, 1, 1, 1, 0, 1, 51, 1, 51, 1, 1, 1, 2, 1,
949 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0 },// 153 TRUENAME
950 { -5, -5, -28, 2, -30, 0, 0, 1, 1, 0, 1, 1, 1, 51, 1, 0, 1, 2, 1,
951 1, 1, 1, 1, 51, 1, 0, 0, 1, 1, 0 },// 154 TRUENAME East
952 { -5, -5, -28, 2, -30, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 2, 1, 1,
953 1, 51, 1, 51, 1, 0, 1, 1, 1, 0 },// 153 TRUENAME South
954 { -5, -5, -28, 2, -30, 0, 1, 1, 0, 0, 1, 51, 1, 1, 1, 1, 1, 2, 1,
955 0, 1, 51, 1, 1, 1, 0, 1, 1, 0, 0 },// 153 TRUENAME West
956 { -5, -5, -28, 2, -30, 76, 55, 25, 55, 76, 55, 55, 47, 55, 55, 25,
957 47, 1, 47, 25, 55, 55, 47, 55, 55, 76, 55, 25, 55, 76, }, // BABEL
958 // CURSE
959 // 154
960 { -5, -5, -28, 2, -30, 55, 55, 47, 55, 55, 55, 75, 25, 75, 55, 47,
961 25, 1, 25, 47, 55, 75, 25, 75, 55, 55, 55, 47, 55, 55, }, // BABEL
962 // counter
963 // CURSE
964 // 155
965 { -5, -5, -28, 2, -30,
966 1 ,0 ,89,89, 0,
967 0 ,0 ,89, 0,76,
968 55,55,55,55,55,
969 76,0 ,89,0 ,0 ,
970 0 ,89,89,0 , 1}, // 159,
971 // smite
972 // trap
973
974 {
975
976 // 160, wood ward
977 -3, -3, -28, 2, -30, -2, 0, 53, 0, 53, 1, 53, 0, 53, 0, -6,
978 -4, -14, -14, -14, -14, 133, -14, -14, -14, -14, -6, -4, 0,
979 53, 0, 53, 1, 53, 0, 53, 0, -6, -4
980
981 },
982
983 { -3, -3, -28, 2, -30, -4, 0, 2, 0, 2, 42, 2, 0, 2, 0, -2,
984
985 -6, 0, 55, 0, 55, 2, -2, -8, 29, -4, 55, 0, 55, 0 }, // 161, logic
986 // transmitter
987 // (MultiWorld
988 // / Sticky
989 // RS)
990 { -5, -5, -24, 368,
991 -30,// */
992 76, 55, 55, 55, 76, 55, 55, 0, 55,
993 55, // back, down, key, back,up,up,key,down
994 55, 0, 1, -8, -4, 2, -8, -2, -2, 2, -4, /**/0, 55, 55, 55,
995 0, 55, 55, 76, 55, 55, 55, 76 }, // 162 communication pearl
996 { -3, -3, 119, 119, 119, 119, 119, 119, 119, 119, 119 }, // 163,
997 // should
998 // be
999 // com
1000 // tower,
1001 // NEI
1002 { -3, -3, -24, 399, -30,
1003
1004 0, 19, 0, 19, 9, 19, 0, 19, 0
1005
1006 }, // 164, Temp Rune. Currently, SFTP.
1007 { -7, -7, -28, 2, -30, 0, 0, 1, 1, 1, 0, 0, 0, 1, 42, 42, 42, 1, 0,
1008 1, 42, 2, 133, 2, 42, 1, 1, 42, 133, 133, 133, 42, 1, 1,
1009 42, 2, 133, 2, 42, 1, 0, 1, 42, 42, 42, 1, 0, 0, 0, 1, 1,
1010 1, 0, 0, -2, -6, 0, 0, 55, 0, 55, 0, 0, 0, 0, 55, 76, 55,
1011 0, 0, 55, 55, 0, 55, 0, 55, 55, 0, 76, 55, 0, 55, 76, 0,
1012 55, 55, 0, 55, 0, 55, 55, 0, 0, 55, 76, 55, 0, 0, 0, 0, 55,
1013 0, 55, 0, 0,
1014
1015 }, // 165, Reality Anchor
1016 { -7, -7, -28, 2, -30, 0, 0, 42, 2, 42, 0, 0, 0, 124, 42, 42, 42,
1017 124, 0, 42, 42, 2, 133, 2, 42, 42, 2, 42, 133, 2, 133, 42,
1018 2, 42, 42, 2, 133, 2, 42, 42, 0, 124, 42, 42, 42, 124, 0,
1019 0, 0, 42, 2, 42, 0, 0, -2, -6, 0, 0, 55, 0, 55, 0, 0, 0, 0,
1020 55, 76, 55, 0, 0, 55, 55, 0, 0, 0, 55, 55, 0, 76, 0, 2, 0,
1021 76, 0, 55, 55, 0, 0, 0, 55, 55, 0, 0, 55, 76, 55, 0, 0, 0,
1022 0, 55, 0, 55, 0, 0,
1023
1024 }, // 166, Reality Master
1025 { -5, -5, -28, 2, -30, 0, 0, 1, 0, 0, 0, 2, 154, 2, 0, 1, 154, 2,
1026 154, 1, 0, 2, 154, 2, 0, 0, 0, 1, 0, 0, -4, -6, 0, 0, 2, 0,
1027 0, 0, 0, 1, 0, 0, 2, 1, 2, 1, 2, 0, 0, 1, 0, 0, 0, 0, 2, 0,
1028 0, // */
1029 }, // 167, freightTP
1030
1031 { -5, -5, -28, 2, -30, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 1, 2, 2, 2, 1,
1032 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, -2, -6, 0, 0, 76, 0, 0, 0, 0,
1033 1, 0, 0, 76, 1, 2, 1, 76, 0, 0, 1, 0, 0, 0, 0, 76, 0, 0, },// freighttp
1034 { -3, -3, -28, 2, -30, 152, 156, 152, 156, 57, 156, 152, 156, 152,
1035 -2, -6, 1, 156, 1, 156, 0, 156, 1, 156, 1, -2, -6, 0, 55,
1036 0, 55, 0, 55, 0, 55, 0, // */
1037
1038 }, // Memento
1039 /*
1040 * -2 y++; -4 y--; -6 reset xz
1041 */
1042 { -3, -3, -28, 2, -30, -2, 0, 156, 0, 156, 1, 156, 0, 156, 0, -6,
1043 -4, -14, -14, -14, -14, 133, -14, -14, -14, -14, -6, -4, 0,
1044 156, 0, 156, 1, 156, 0, 156, 0, }, // flight ward
1045 { -7, -1, -28, 2, -30, -4, -4, -4, 0, 0, 1, 2, 1, 0, 0, -6, -2, 0,
1046 0, 1, 1, 1, 0, 0, -6, -2, 1, 1, 41, 1, 41, 1, 1, -6, -2, 2,
1047 1, 1, 41, 1, 1, 2, -6, -2, 1, 1, 41, 1, 41, 1, 1, -6, -2,
1048 0, 0, 1, 1, 1, 0, 0, -6, -2, 0, 0, 1, 2, 1, 0, 0, }, // wall
1049 // ftp
1050 // e/w
1051 // 171
1052 { -1, -7, -28, 2, -30, -4, -4, -4, 0, 0, 1, 2, 1, 0, 0, -6, -2, 0,
1053 0, 1, 1, 1, 0, 0, -6, -2, 1, 1, 41, 1, 41, 1, 1, -6, -2, 2,
1054 1, 1, 41, 1, 1, 2, -6, -2, 1, 1, 41, 1, 41, 1, 1, -6, -2,
1055 0, 0, 1, 1, 1, 0, 0, -6, -2, 0, 0, 1, 2, 1, 0, 0, }, // wall
1056 // ftp
1057 // n/s
1058 // 172
1059 { -5, -5, -24, 261,
1060 -30, // Hell Maw - 173 + 174
1061 0, 0, 49, 0, 0, 0, 49, 10, 49, 0, 49, 10, 41, 10, 49, 0,
1062 49, 10, 49, 0, 0, 0, 49, 0, 0, },
1063 { -5, -5, -24, 261,
1064 -30, // Hell Maw - 173 + 174
1065 0, 0, 49, 0, 0, 0, 49, 10, 49, 0, 49, 10, 14, 10, 49, 0,
1066 49, 10, 49, 0, 0, 0, 49, 0, 0, },
1067
1068
1069
1070 { -7, -7, //-28, 2, -30,
1071 -4,
1072 0, 0, 1, 1, 1, 0, 0,
1073 0, 0, 55,55,55,0, 0,
1074 1 ,55,55,2 ,55,55,1,
1075 1 ,55,2 ,57, 2, 55,1,
1076 1 ,55,55,2 ,55,55,1,
1077 0, 0, 55,55,55,0 ,0,
1078 0, 0, 1, 1, 1, 0, 0,
1079
1080 -2,-10,5,5, -6,/**/
1081
1082
1083 0, 1,152, 1, 0,
1084 1, 1, 55, 1, 1,
1085 152,55, 1,
1086 -8, -2, 55,
1087 -8, -2, 144,-4,-4,
1088
1089 55, 152,
1090 1, 1, 55, 1, 1,
1091 0, 1,152, 1, 0,
1092
1093 }, //TN altar 175
1094 { -7, -7, -28, 2, -30,
1095 -4,
1096 0, 0, 1, 1, 1, 0, 0,
1097 0, 0, 55,55,55,0, 0,
1098 1 ,55,55,2 ,55,55,1,
1099 1 ,55,2 ,1, 2, 55,1,
1100 1 ,55,55,2 ,55,55,1,
1101 0, 0, 55,55,55,0 ,0,
1102 0, 0, 1, 1, 1, 0, 0,
1103
1104 -2,-10,5,5, -6,/**/
1105
1106
1107 0, 1,152, 1, 0,
1108 1, 1, 55, 1, 1,
1109 152,55, 1,
1110 -8, -2, 55,
1111 -8, -2, 144,-4,-4,
1112
1113 55, 152,
1114 1, 1, 55, 1, 1,
1115 0, 1,152, 1, 0, /**/
1116
1117 }, //TN altar 176
1118 {-3,-3,
1119 0,55,0,
1120 55,170,55,
1121 0,55,0,
1122 }, //debug haybale rune, 177
1123 {
1124 -11,-11, -28,2,-30,
1125 57, 55, 55, 0, 55, 55, 55, 0, 55, 55, 57,
1126 55, 0, 55, 55, 55, 51, 55, 55, 55, 0, 55,
1127 55, 55, 57, 0, 55, 55, 55, 0, 57, 55, 55,
1128 0, 55, 0, 57, 0, 55, 0, 57, 0, 55, 0,
1129 55, 55, 55, 0, 57, 2, 57, 0, 55, 55, 55,
1130 55, 0, 55, 55, 2,138, 2, 55, 55, 0, 55,
1131 55, 55, 55, 0, 57, 2, 57, 0, 55, 55, 55,
1132 0, 55, 0, 57, 0, 55, 0, 57, 0, 55, 0,
1133 55, 55, 57, 0, 55, 55, 55, 0, 57, 55, 55,
1134 55, 0, 55, 55, 55, 9, 55, 55, 55, 0, 55,
1135 57, 55, 55, 0, 55, 55, 55, 0, 55, 55, 57,
1136
1137 -2,-10,-3,-3, -6,
1138
1139 -18,-18,-18,
1140 -18,-18,-18,
1141 -18,-18,-18,
1142
1143 -2,-10,-5,-5, -6,
1144
1145 -18,-18,-18,-18,-18,
1146 -18,-18,-18,-18,-18,
1147 -18,-18,-18,-18,-18,
1148 -18,-18,-18,-18,-18,
1149 -18,-18,-18,-18,-18,
1150
1151 -2,-10,-7,-7, -6,
1152
1153 -18,-18,-18,-18,-18,-18,-18,
1154 -18,-18,-18,-18,-18,-18,-18,
1155 -18,-18,-18,-18,-18,-18,-18,
1156 -18,-18,-18,-18,-18,-18,-18,
1157 -18,-18,-18,-18,-18,-18,-18,
1158 -18,-18,-18,-18,-18,-18,-18,
1159 -18,-18,-18,-18,-18,-18,-18,
1160
1161 -2,-10,9,9, -6,
1162
1163 -18,-18,-18,-18,-18,-18,-18,-18,-18,
1164 -18,-18,-18,-18,-18,-18,-18,-18,-16
1165 -18,-18,-18,-18,-18,-18,-18,-18,-18,
1166 -18,-18,-18,-18,-18,-18,-18,-18,-18,
1167 -18,-18,-18,-18,-18,-18,-18,-18,-18,
1168 -18,-18,-18,-18,-18,-18,-18,-18,-18,
1169 -18,-18,-18,-18,-18,-18,-18,-18,-18,
1170 -18,-18,-18,-18,-18,-18,-18,-18,-18,
1171 -18,-18,-18,-18,-18,-18,-18,-18,-18,
1172 //*/
1173 /*-3,-3,
1174 57,2,57,
1175 2,138,2,
1176 57,2,57, //*/
1177
1178 }// genesis
1179 };
1180
1181 // Compass block positions
1182 private static final rcm[][] compOldNorth = {
1183 { new rcm(0, 0, -1), new rcm(-1, 0, -1) },
1184 { new rcm(0, 0, 0), new rcm(-1, 0, 0) },
1185 { new rcm(0, 0, +1), new rcm(-1, 0, +1) } };
1186 private static final rcm[][] compNewNorth = {
1187 { new rcm(-1, 0, 0), new rcm(-1, 0, -1) },
1188 { new rcm(0, 0, 0), new rcm(0, 0, -1) },
1189 { new rcm(+1, 0, 0), new rcm(+1, 0, -1) } };
1190
1191 // Warpzone animation instructions (rn.b)
1192 static final int[] wz_half = { 1, 1, 1, 1, 0, 1, 1, 1, 1 };
1193
1194 private static final int[] mss = { -16, -12, -15, -15, -15, -15, -15, -15,
1195 -15, -15, -4, -6, -15, -12, -15, -15, -15, -15, -15, -15, -15, -4,
1196 -6, -15, -15, -12, -15, -15, -15, -15, -15, -15, -4, -6, -15, -15,
1197 -15, -15, -15, -12, -15, -15, -15, -4, -6, -15, -15, -15, -15, -15,
1198 -15, -15, -15, -12, -4, -6, -15, -15, -15, -15, -15, -15, -15, -12,
1199 -15, -4, -6, -15, -15, -15, -15, -15, -15, -12, -15, -15, -4, -6,
1200 -15, -15, -15, -12, -15, -15, -15, -15, -15 };
1201
1202 // Hidden Passage build instructions (rn.b)
1203 private static final int[][] opw = {
1204 { -3, -3, 0, 1, 0, 0, 1, 0, 1, 1, 1 },
1205 { -3, -3, 1, 0, 0, 1, 1, 1, 1, 0, 0 },
1206 { -3, -3, 1, 1, 1, 0, 1, 0, 0, 1, 0 },
1207 { -3, -3, 0, 0, 1, 1, 1, 1, 0, 0, 1 }, // 11-14, secret floor
1208 // passageways
1209 { -1, -3, -4, 0, 1, 0, -2, -6, 0, 1, 0, -2, -6, 1, 1, 1 },
1210 { -3, -1, -4, 0, 1, 0, -2, -6, 0, 1, 0, -2, -6, 1, 1, 1 } // 15-16,
1211 // secret
1212 // wall
1213 // passageways
1214 };
1215
1216 // Zeerix' Chest build instructions (rn.b)
1217 private static final int[][] opc = {
1218 { -1, -3, -4, 0, 54, 0, -2, -6, 0, 0, 0, -2, -6, 0, 0, 0 },
1219 { -3, -1, -4, 0, 54, 0, -2, -6, 0, 0, 0, -2, -6, 0, 0, 0 }, // 61-62,
1220 // secret
1221 // chest
1222 { -1, -3, -4, 0, Runecraft_MAIN.ENDERCHEST, 0, -2, -6, 0, 0, 0, -2, -6, 0, 0,
1223 0 },
1224 { -3, -1, -4, 0, Runecraft_MAIN.ENDERCHEST, 0, -2, -6, 0, 0, 0, -2, -6, 0, 0,
1225 0 } };
1226
1227 // for Hidden Passage
1228 private static final int[] hpx = { 0, 1, 0 };
1229
1230 // build instructions for Mound
1231 private static final int[] mnda = { -16, -4, -4, -12, -12, -12, -12, -12,
1232 -12, -12, -12, -12, -14, -14, -14, -12, -12, -12, -12, -14, -14,
1233 -14, -12, -12, -12, -12, -14, -14, -14, -12, -12, -12, -12, -14,
1234 -14, -14, -12, -12, -12, -12, -14, -12, -14, -12, -12, -12, -12,
1235 -12, -12, -12, -12, -12, -2, -6, -12, -12, -12, -12, -12, -12, -12,
1236 -12, -12, -14, -14, -14, -12, -12, -12, -14, -14, -14, -14, -14,
1237 -12, -12, -14, -14, -14, -14, -14, -12, -12, -14, -14, -14, -14,
1238 -14, -12, -12, -12, -14, -14, -14, -12, -12, -12, -12, -12, -14,
1239 -12, -12, -12, -2, -6, 0, 0, 1, 1, 1, 0, 0, 0, 1, -14, -14, -14, 1,
1240 0, 1, -14, -14, -14, -14, -14, 1, 1, -14, -14, -14, -14, -14, 1, 1,
1241 -14, -14, -14, -14, -14, 1, 0, 1, -14, -14, -14, 1, 0, 0, 0, 1,
1242 -14, 1, 0, 0, -2, -6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0,
1243 1, 1, -14, 1, 1, 0, 0, 1, -14, -14, -14, 1, 0, 0, 1, 1, -14, 1, 1,
1244 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, -6, 0, 0, 0, 0, 0,
1245 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0,
1246 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };
1247
1248 // for Bridge/Wall Master and other positional runes
1249 static final int[] tf = { 1, 2, 4, 4, 4, 4 };
1250
1251 // *** some game data ***
1252
1253 // named block types
1254 static final int AIR = 0;
1255 static final int STONE = 1;
1256 static final int GRASS = 2;
1257 static final int DIRT = 3;
1258 static final int COBBLESTONE = 4;
1259 static final int PLANK = 5;
1260 static final int SAPLING = 6;
1261 static final int BEDROCK = 7;
1262 static final int WATER = 8;
1263 static final int STAT_WATER = 9;
1264 static final int LAVA = 10;
1265 static final int STAT_LAVA = 11;
1266 static final int SAND = 12;
1267 static final int GRAVEL = 13;
1268 static final int GOLD_ORE = 14;
1269 static final int IRON_ORE = 15;
1270 static final int COAL_ORE = 16;
1271 static final int WOOD = 17;
1272 static final int LEAVES = 18;
1273 static final int SPONGE = 18;
1274 static final int GLASS = 20;
1275 static final int LAPIS_ORE = 21;
1276 static final int LAPIS_BLOCK = 22;
1277 static final int SANDSTONE = 24;
1278 static final int NOTE_BLOCK = 25;
1279 static final int TALL_GRASS = 31;
1280 static final int DEAD_BUSH = 32;
1281 static final int PISTON_HEAD = 34;
1282 static final int WOOL = 35;
1283 static final int GOLD_BLOCK = 41;
1284 static final int IRON_BLOCK = 42;
1285 static final int BRICK_BLOCK = 45;
1286 static final int OBSIDIAN = 49;
1287 static final int TORCH = 50;
1288 static final int FIRE = 51;
1289 static final int MOB_SPAWNER = 52;
1290 static final int CHEST = 54;
1291 static final int RS_WIRE = 55;
1292 static final int DIAMOND_ORE = 56;
1293 static final int SIGN_POST = 63;
1294 static final int WALL_SIGN = 68;
1295 static final int LEVER = 69;
1296 static final int RS_TORCH_OFF = 75;
1297 static final int RS_TORCH = 76;
1298 static final int BUTTON = 77;
1299 static final int SNOW = 78;
1300 static final int ICE = 79;
1301 static final int SNOW_BLOCK = 80;
1302 static final int CACTUS = 81;
1303 static final int CLAY_BLOCK = 82;
1304 static final int SUGAR_CANE = 83;
1305 static final int JUKEBOX = 84;
1306 static final int SOULSAND = 88;
1307 static final int GLOWSTONE = 89;
1308 static final int RS_REPEATER_OFF = 93;
1309 static final int RS_REPEATER = 94;
1310 static final int STONEBRICK = 98;
1311 static final int VINE = 106;
1312 static final int MYCEL = 110;
1313 static final int CAULDRON_BLOCK = 118;
1314 static final int ENDER_EGG = 122;
1315 static final int EMERALD_ORE = 129;
1316 static final int ENDERCHEST = 130;
1317 static final int TRIPWIRE_HOOK = 131;
1318 static final int SPRUCE_WOOD_STAIRS = 134;
1319 static final int BIRCH_WOOD_STAIRS = 135;
1320 static final int JUNGLE_WOOD_STAIRS = 136;
1321 static final int ACACIA_WOOD_STAIRS = 163;
1322 static final int DARK_OAK_WOOD_STAIRS = 164;
1323 static final int BEACONBLOCK = 138;
1324 static final int WOOD_BUTTON = 143;
1325 static final int SKULLBLOCK = 144;
1326 static final int RS_COMPARATOR_OFF = 149;
1327 static final int RS_COMPARATOR = 150;
1328 static final int LEAVES2 = 161;
1329 static final int WOOD2 = 162;
1330 static final int HAY_BALE = 170;
1331 static final int COAL_BLOCK = 173;
1332 static final int SKULLITEM = 397;
1333
1334 static final int WHEAT = 59;
1335 static final int PUMPKIN = 86;
1336 static final int MELON = 103;
1337 static final int CARROTS = 141;
1338 static final int POTATOES = 142;
1339
1340 // named item types (>=256)
1341
1342 static final int BOW = 261;
1343 static final int ARROW = 262;
1344 static final int COAL = 263;
1345 static final int DIAMOND = 264;
1346 static final int IRON = 265;
1347 static final int GOLD = 266;
1348 static final int STICK = 280;
1349 static final int BOWL = 281;
1350 static final int STRING = 287;
1351 static final int WHEAT_ITEM = 296;
1352 static final int FLINT = 318;
1353 static final int BUCKET = 325;
1354 static final int WATER_BUCKET = 326;
1355 static final int LAVA_BUCKET = 327;
1356 static final int REDSTONE_DUST = 331;
1357 static final int BOOK = 340;
1358 static final int DYE = 351;
1359 static final int BOTTLE = 374;
1360 static final int SHEARS = 359;
1361
1362 // special groups of blocks and items
1363 // static final List<Integer> blanks = Arrays.asList(AIR, STONE, GRASS,
1364 // DIRT, PISTON_HEAD, SIGN_POST, WALL_SIGN, SNOW, MYCEL);
1365 static final Set<Integer> liquids = mkSet(WATER, STAT_WATER, LAVA,
1366 STAT_LAVA);
1367 static final Set<Integer> golden = mkSet(283, 284, 285, 286, 294, 314, 315,
1368 316, 317);
1369 static final Set<Integer> swords = mkSet(268, 272, 267, 283, 276);
1370 static final Set<Integer> picks = mkSet(270, 274, 257, 285, 278);
1371 static final Set<Integer> shovels = mkSet(269, 273, 256, 284, 277);
1372 static final Set<Integer> axes = mkSet(271, 275, 258, 286, 279);
1373 static final Set<Integer> hoes = mkSet(290, 291, 292, 294, 293);
1374 static final Set<Integer> bows = mkSet(BOW);
1375 static final Set<Integer> torches = mkSet(TORCH, RS_TORCH_OFF, RS_TORCH);
1376 static final Set<Integer> boxes = mkSet(CHEST, 23, 61, 62, 117, 154, 146);
1377 static final Set<Integer> tileentityblocks = mkSet(63, 68, 52, 25, 84, 144,
1378 137);
1379 static final Set<Integer> armor = mkSet(302, 303, 304, 305, 306, 307, 308,
1380 309, 310, 311, 312, 313, 314, 315, 316, 317);
1381 static final Set<Integer> curses = mkSet(MOUSETRAP, MOUSETRAP + 1,
1382 BUTTERCURSE, WHISPERCURSE, SMITETRAP, BABELCURSE);
1383 static final Set<Integer> latchblocks = mkSet(6, 12, 13, 27, 28, 31, 32,
1384 37, 38, 39, 40, 50, 55, 59, 65, 66, 68, 69, 70, 82, 75, 76, 77, 78,
1385 83, 96, 104, 105, 106, 115, 111, 93, 94, 64, 122, 131, 132, 141,
1386 142, 143, 145);
1387 static final Set<Integer> stairs = mkSet(53, 67, 108, 109, 114, 128, 134,
1388 135, 136, 156);
1389
1390 // Runes which an uninitiated player can still use
1391 static final Set<Integer> initiationExceptionRunes = mkSet(TELEPORTER,
1392 WALLTELEPORTER, WALLTELEPORTER + 1, INITIATOR);
1393
1394 // *** referenced classes ***
1395 static final Logger log = Logger.getLogger("Minecraft");
1396 static final Random rand = new Random();
1397 static final Timer tm = new Timer(true);
1398 static Runecraft_MAIN self;
1399 private final RuneWorld main_world;
1400
1401 // *** configuration ***
1402 private final Set<String> rl = createSet(); // (black/white)list for runes
1403 public boolean wl = false; // white list?
1404
1405 private final Set<String> opt = createSet();
1406
1407 // *** world identifiers ***
1408 private final Map<String, Integer> worldId = createMap(); // don't use this
1409 // directly
1410 protected final Map<Integer, RuneWorld> worlds = createMap();
1411
1412 // *** run-time a (magic.dat) ***
1413 static final int DRT_DATASAVINGTASK = 65000; // rct.task for data saving
1414 // task
1415
1416 private volatile boolean drt_magicDatNeedsUpdate = false; // dirty flag for
1417 // magic.dat
1418
1419 final Map<String, List<int[]>> sl = Collections
1420 .synchronizedMap(new HashMap<String, List<int[]>>());
1421 final Map<String, List<Integer>> rrReceived = new HashMap<String, List<Integer>>();
1422 final Map<String, Integer> rrTransmitColour = new HashMap<String, Integer>();
1423 final Map<String, Integer> rrTransmit = new HashMap<String, Integer>();
1424 final List<int[]> waypointRuneList = createLList(); // waypoint list
1425 final List<RunePoint> waypointList = createLList(); // new waypoint list,
1426 // will eventually
1427 // supercede old one.
1428 final List<int[]> teleportRuneList = createLList(); // teleporter list
1429 final List<int[]> faithRuneList = createLList(); // faith rune list
1430 final List<int[]> positionRuneList = createLList(); // position rune list
1431 final List<int[]> runePadList = createLList(); // rune pad list
1432 final List<int[]> logicDestinationRuneList = createLList(); // logic
1433 // destination
1434 // list
1435 final List<int[]> wardRuneList = createLList(); // ward list
1436 // [x,y,z,w,radius,state,type]
1437 final List<int[]> whisperSourceList = createLList(); // list of Whisper
1438 // curse runes, for
1439 // hex blocks to
1440 // link back to.
1441 final List<int[]> realityAnchorList = createLList(); // list of reality
1442 // anchors TODO:
1443 // SAVE/LOAD FOR
1444 // THIS LIST
1445
1446 final List<String[]> wpassgnl = createLList();
1447 final List<List<String>> strl = createLList();
1448 public Set<Integer> mfrl = new HashSet<Integer>(); // contains moving faith
1449 // islands' indexes. not
1450 // saved!
1451 static Set<String> dbgl = new HashSet<String>();
1452
1453 public List<rcm> mrml = new ArrayList<rcm>(); // contains list of working
1454 // reality masters
1455
1456 /** a list of a list of ints. the ints are grouped world IDs */
1457 public List<List<Integer>> wgl = createLList();
1458
1459 public Set<Integer> wgo = new HashSet<Integer>(); // inks that ignore world
1460 // grouping
1461 // final List<int[]> fwpl = createLList(); // faith WP rune list
1462
1463 final Map<String, Vector<Integer>> rplp = Collections
1464 .synchronizedMap(new HashMap<String, Vector<Integer>>());
1465 final Map<rcm, RunePlayer[]> rplm = Collections
1466 .synchronizedMap(new HashMap<rcm, RunePlayer[]>());
1467
1468 private final Set<String> ip = createSet(); // initiated players list (for
1469 // initiation mode)
1470
1471 private final List[] md = { waypointRuneList, teleportRuneList,
1472 faithRuneList, positionRuneList, runePadList,
1473 logicDestinationRuneList, wardRuneList, whisperSourceList,
1474 realityAnchorList }; // access only for loading/saving stuff
1475
1476 // positional runes indexed by x,y,z,world_id
1477 public final Map<rcm, rcm> positionRune = createMap();
1478 // hex runes, indexed by x,y,z,world_id
1479 public final Map<rcm, rcm> hexRune = createMap();
1480
1481 private long ctLastUse = 0; // last use of Chrono Trigger for cooldown
1482
1483 // *** constructor ***
1484 Runecraft_MAIN(final String version, final RuneWorld world) {
1485 this.main_world = world;
1486 this.version = version;
1487 initializeRuneUsesTable();
1488 intializeBMT();
1489 readWhiteList(); // read white/blacklist
1490 l_loadMagicDat(); // read magic.dat
1491 registerWorld(world);
1492
1493 // start player/mob proximity tasks
1494 // tm.schedule(t(main_world, 5, null), 4000, 4000);
1495 // tm.schedule(t(main_world, 6, null), 100, 100);
1496 t(main_world, 5, null).scheduleSyncRepeating(100, 80);
1497 t(main_world, 6, null).scheduleSyncRepeating(100, 5);
1498 t(main_world, COMMPEARL, null).scheduleSyncRepeating(100, 200);
1499 logInfo(getVersion() + " initialized.");
1500 dbgl.add("Ctri");
1501 // dbgl.add("Der_Niabs");
1502 // dbgl.add("forrrrr");
1503 // dbgl.add("Maynard680");
1504 // dbgl.add("ramo1997");
1505 // dbgl.add("You_Randomly");
1506 // dbgl.add("Admiral_Minell");
1507 }
1508
1509 void initializeRuneUsesTable() {
1510 runeUsesTable.put(null, Arrays.asList(0, 10, 10, 10, 10, 10, 10, 10));// default
1511 // value
1512
1513 // this code is autogenerated from the spreadsheet
1514 // https://docs.google.com/spreadsheet/ccc?key=0AtbF8yXVlRLndFUwWTBxbEg4UTVodURoTkVCZDRnQXc
1515 runeUsesTable.put("Compass", Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0));
1516 runeIdToRuneNameTable.put(COMPASS, "Compass");
1517 runeUsesTable.put("Oracle",
1518 Arrays.asList(0, 16, 16, 16, 16, 16, 16, 16));
1519 runeIdToRuneNameTable.put(ORACLE, "Oracle");
1520 runeUsesTable.put("Depth Note",
1521 Arrays.asList(0, 22, 24, 34, 214, 994, 2326, 23192));
1522 runeIdToRuneNameTable.put(DEPTHPAPER, "Depth Note");
1523 runeUsesTable.put("Waypoint", Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0));
1524 runeIdToRuneNameTable.put(WAYPOINT, "Waypoint");
1525 runeIdToRuneNameTable.put(WALLWPOINT, "Waypoint");
1526 runeIdToRuneNameTable.put(WALLWPOINT + 1, "Waypoint");
1527 runeUsesTable.put("Teleporter",
1528 Arrays.asList(0, 0, 3, 23, 372, 1885, 4468, 44936));
1529 runeIdToRuneNameTable.put(TELEPORTER, "Teleporter");
1530 runeIdToRuneNameTable.put(WALLTELEPORTER, "Teleporter");
1531 runeIdToRuneNameTable.put(WALLTELEPORTER + 1, "Teleporter");
1532
1533 runeUsesTable.put("Personal Teleport",
1534 Arrays.asList(0, 1, 1, 1, 1, 1, 1, 1));
1535 runeIdToRuneNameTable.put(QUICKTP, "Personal Teleport");
1536 runeUsesTable.put("Recall",
1537 Arrays.asList(0, 12, 12, 12, 12, 12, 12, 12));
1538 runeIdToRuneNameTable.put(RECALL, "Recall");
1539 runeUsesTable.put("Warp", Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0));
1540 runeIdToRuneNameTable.put(WARPZONE, "Warp");
1541 runeIdToRuneNameTable.put(WARPZONE + 1, "Warp");
1542 runeUsesTable.put("Faithpoint", Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0));
1543 runeIdToRuneNameTable.put(FAITHPOINT, "Faithpoint");
1544 runeIdToRuneNameTable.put(WALLFPOINT, "Faithpoint");
1545 runeIdToRuneNameTable.put(WALLFPOINT + 1, "Faithpoint");
1546
1547 runeUsesTable.put("Faith", Arrays.asList(0, 4, 6, 8, 11, 12, 13, 23));
1548 runeIdToRuneNameTable.put(FAITH, "Faith");
1549 runeUsesTable.put("Faith Transfer Portal",
1550 Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0));
1551 runeIdToRuneNameTable.put(FTP, "Faith Transfer Portal");
1552 runeIdToRuneNameTable.put(WALLFTP, "Faith Transfer Portal");
1553 runeIdToRuneNameTable.put(WALLFTP + 1, "Faith Transfer Portal");
1554 runeUsesTable.put("Mineshaft",
1555 Arrays.asList(0, 8, 16, 24, 32, 76, 160, 1464));
1556 runeIdToRuneNameTable.put(MINESHAFT, "Mineshaft");
1557 runeUsesTable.put("Ovicaptor", Arrays.asList(0, 1, 1, 1, 1, 1, 1, 1));
1558 runeIdToRuneNameTable.put(OVICAPTOR, "Ovicaptor");
1559 runeUsesTable.put("Solar Flare",
1560 Arrays.asList(0, 1228, 1228, 1228, 1228, 1228, 1228, 1228));
1561 runeIdToRuneNameTable.put(SCORCHER, "Solar Flare");
1562 runeUsesTable.put("Magic Beacon",
1563 Arrays.asList(0, 2, 3, 6, 66, 326, 770, 7726));
1564 runeIdToRuneNameTable.put(BEACON, "Magic Beacon");
1565 runeUsesTable.put("Surface Tension",
1566 Arrays.asList(0, 2, 3, 5, 50, 245, 578, 5795));
1567 runeIdToRuneNameTable.put(SURFACE_TENSION, "Surface Tension");
1568 runeUsesTable.put("Embedder",
1569 Arrays.asList(0, 10, 41, 46, 136, 526, 1192, 11625));
1570 runeIdToRuneNameTable.put(EMBEDDER, "Embedder");
1571 runeIdToRuneNameTable.put(EMBEDDER + 1, "Embedder");
1572 runeUsesTable.put("Wall Master",
1573 Arrays.asList(0, 64, 66, 76, 256, 1036, 2368, 23234));
1574 runeIdToRuneNameTable.put(WALLMASTER, "Wall Master");
1575 runeIdToRuneNameTable.put(WALLMASTER + 1, "Wall Master");
1576 runeUsesTable.put("Bridge Master",
1577 Arrays.asList(0, 64, 66, 76, 256, 1036, 2368, 23234));
1578 runeIdToRuneNameTable.put(BRIDGEMASTER, "Bridge Master");
1579 runeIdToRuneNameTable.put(BRIDGEMASTER + 1, "Bridge Master");
1580 runeUsesTable
1581 .put("Mound", Arrays.asList(0, 52, 52, 52, 52, 52, 52, 52));
1582 runeIdToRuneNameTable.put(MOUND, "Mound");
1583 runeUsesTable.put("Freezer",
1584 Arrays.asList(0, 2652, 2652, 2652, 2652, 2652, 2652, 2652));
1585 runeIdToRuneNameTable.put(FREEZER, "Freezer");
1586 runeUsesTable.put("Topsy Turvy",
1587 Arrays.asList(0, 4, 6, 7, 8, 10, 11, 23));
1588 runeIdToRuneNameTable.put(FLP, "Topsy Turvy");
1589 runeIdToRuneNameTable.put(FLP + 1, "Topsy Turvy");
1590 runeIdToRuneNameTable.put(VFLPNS, "Topsy Turvy");
1591 runeIdToRuneNameTable.put(VFLPEW, "Topsy Turvy");
1592 runeUsesTable.put("Zeerix Chest",
1593 Arrays.asList(0, 25, 26, 28, 64, 220, 486, 4659));
1594 runeIdToRuneNameTable.put(SECRETCHEST, "Zeerix Chest");
1595 runeIdToRuneNameTable.put(SECRETCHEST + 1, "Zeerix Chest");
1596 runeIdToRuneNameTable.put(SUPERSECRETCHEST, "Zeerix Ender Chest");
1597 runeIdToRuneNameTable.put(SUPERSECRETCHEST + 1, "Zeerix Ender Chest");
1598 runeUsesTable.put("Bottomless Cauldron",
1599 Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0));
1600 runeIdToRuneNameTable.put(CAULDRON, "Bottomless Cauldron");
1601 runeUsesTable.put("Spring",
1602 Arrays.asList(0, 446, 463, 554, 2190, 9281, 21390, 211086));
1603 runeIdToRuneNameTable.put(SPRINGSTRING, "Spring");
1604 runeIdToRuneNameTable.put(SPRINGSTRING + 1, "Spring");
1605 runeUsesTable.put("Flotilla",
1606 Arrays.asList(0, 10, 10, 10, 10, 10, 10, 10));
1607 runeIdToRuneNameTable.put(FLOTILLA, "Flotilla");
1608 runeIdToRuneNameTable.put(FLOTILLA + 1, "Flotilla");
1609 runeUsesTable.put("Phantom Torch",
1610 Arrays.asList(0, 16, 17, 22, 112, 502, 1168, 11601));
1611 runeIdToRuneNameTable.put(PHANTOMTORCH, "Phantom Torch");
1612 runeIdToRuneNameTable.put(PHANTOMTORCH + 1, "Phantom Torch");
1613 runeIdToRuneNameTable.put(REDTORCH, "Phantom Torch");
1614 runeIdToRuneNameTable.put(REDTORCH + 1, "Phantom Torch");
1615 runeUsesTable.put("Chrono Trigger",
1616 Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0));
1617 runeIdToRuneNameTable.put(TIMECONTROL, "Chrono Trigger");
1618 // runeUsesTable.put("Endurance", Arrays.asList(0, 30, 30, 30, 30, 30,
1619 // 30, 30)); runeIdToRuneNameTable.put((Integer)ENDURANCE, "Endurance");
1620 runeUsesTable.put("Endurance",
1621 Arrays.asList(0, 46, 48, 57, 217, 910, 2094, 20642));
1622 runeIdToRuneNameTable.put(ENDURANCE, "Endurance");
1623 runeIdToRuneNameTable.put(ENDURANCE + 1, "Endurance");
1624 runeUsesTable.put("Diver's Helmet",
1625 Arrays.asList(0, 36, 43, 78, 718, 3492, 8228, 82419));
1626 runeIdToRuneNameTable.put(DIVERHELM, "Diver's Helmet");
1627 runeUsesTable.put("Cold Feet",
1628 Arrays.asList(0, 198, 228, 388, 3268, 15748, 37060, 370923));
1629 runeIdToRuneNameTable.put(COLDFEET, "Cold Feet");
1630 runeIdToRuneNameTable.put(COLDFEET + 1, "Cold Feet");
1631 runeUsesTable.put("Fairy Boots",
1632 Arrays.asList(0, 64, 71, 106, 746, 3520, 8256, 82447));
1633 runeIdToRuneNameTable.put(FAIRYBOOTS, "Fairy Boots");
1634 runeIdToRuneNameTable.put(FAIRYBOOTS + 1, "Fairy Boots");
1635 runeUsesTable.put("Shield",
1636 Arrays.asList(0, 125, 125, 125, 125, 125, 125, 125));
1637 runeIdToRuneNameTable.put(SHIELD, "Shield");
1638 runeUsesTable.put("Force Field",
1639 Arrays.asList(0, 93, 101, 145, 945, 4412, 10332, 103072));
1640 runeIdToRuneNameTable.put(FORCEFIELD, "Force Field");
1641 runeUsesTable.put("Power Pick",
1642 Arrays.asList(0, 49, 53, 73, 433, 1993, 4657, 46389));
1643 runeIdToRuneNameTable.put(POWERPICK, "Power Pick");
1644 runeUsesTable.put("Power Hoe",
1645 Arrays.asList(0, 16, 20, 40, 400, 1960, 4624, 46356));
1646 runeIdToRuneNameTable.put(POWERHOE, "Power Hoe");
1647 runeUsesTable.put("Power Drill",
1648 Arrays.asList(0, 25, 27, 37, 217, 997, 2329, 23195));
1649 runeIdToRuneNameTable.put(POWERDRILL, "Power Drill");
1650 runeIdToRuneNameTable.put(POWERDRILL + 1, "Power Drill");
1651 runeUsesTable.put("Leaf Blower",
1652 Arrays.asList(0, 305, 305, 305, 305, 305, 305, 305));
1653 runeIdToRuneNameTable.put(LEAFBLOWER, "Leaf Blower");
1654 runeUsesTable.put("Ice Pick",
1655 Arrays.asList(0, 26, 26, 29, 74, 269, 602, 5818));
1656 runeIdToRuneNameTable.put(ICEPICK, "Ice Pick");
1657 runeUsesTable.put("Water Pick",
1658 Arrays.asList(0, 132, 140, 180, 900, 4020, 9348, 92813));
1659 runeIdToRuneNameTable.put(WATERPICK, "Water Pick");
1660 runeUsesTable.put("Underwater Pick",
1661 Arrays.asList(0, 62, 65, 84, 423, 1891, 4399, 43677));
1662 runeIdToRuneNameTable.put(UNDERWATERPICK, "Underwater Pick");
1663 runeUsesTable.put("Fire Pick",
1664 Arrays.asList(0, 68, 69, 74, 164, 554, 1220, 11653));
1665 runeIdToRuneNameTable.put(FIREPICK, "Fire Pick");
1666 runeUsesTable.put("Admin Pick",
1667 Arrays.asList(0, 12, 24, 36, 48, 60, 72, 84));
1668 runeIdToRuneNameTable.put(ADMINPICK, "Admin Pick");
1669 runeUsesTable.put("Uncrafter",
1670 Arrays.asList(0, 14, 17, 32, 302, 1472, 3470, 34769));
1671 runeIdToRuneNameTable.put(UNCRAFTER, "Uncrafter");
1672 runeIdToRuneNameTable.put(UNCRAFTER + 1, "Uncrafter");
1673 runeUsesTable.put("Doubt", Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0));
1674 runeIdToRuneNameTable.put(DOUBT, "Doubt");
1675 runeUsesTable.put("Green Thumb",
1676 Arrays.asList(0, 321, 336, 416, 1856, 8096, 18752, 185683));
1677 runeIdToRuneNameTable.put(GREENTHUMB, "Green Thumb");
1678 runeUsesTable.put("Farmer's Charm",
1679 Arrays.asList(0, 23, 23, 23, 23, 23, 23, 23));
1680 runeIdToRuneNameTable.put(FARMERCHARM, "Farmer's Charm");
1681 runeIdToRuneNameTable.put(FARMERCHARM + 1, "Farmer's Charm");
1682 runeUsesTable.put("Shrub Seed", Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0));
1683 runeIdToRuneNameTable.put(SHRUB, "Shrub Seed");
1684 runeUsesTable.put("Tunnel Shovel",
1685 Arrays.asList(0, 1045, 1105, 1425, 7185, 32145, 74769, 742496));
1686 runeIdToRuneNameTable.put(TUNNELSHOVEL, "Tunnel Shovel");
1687 runeIdToRuneNameTable.put(TUNNELSHOVEL + 1, "Tunnel Shovel");
1688 runeUsesTable.put("Bow of Light",
1689 Arrays.asList(0, 29, 36, 72, 712, 3485, 8221, 82413));
1690 runeIdToRuneNameTable.put(LIGHTBOW, "Bow of Light");
1691 runeUsesTable.put("Bow of Red Light",
1692 Arrays.asList(0, 29, 36, 72, 712, 3485, 8221, 82413));
1693 runeIdToRuneNameTable.put(REDLIGHTBOW, "Bow of Red Light");
1694 runeUsesTable.put("Siege bow",
1695 Arrays.asList(0, 29, 36, 72, 712, 3485, 8221, 82413));
1696 runeIdToRuneNameTable.put(GLOWARROWBOW, "Siege bow");
1697 runeUsesTable.put("Multishot",
1698 Arrays.asList(0, 36, 41, 64, 475, 2258, 5302, 52997));
1699 runeIdToRuneNameTable.put(MULTIBOW, "Multishot");
1700 runeUsesTable.put("Magic Lasso",
1701 Arrays.asList(0, 502, 509, 545, 1200, 4036, 8880, 84758));
1702 runeIdToRuneNameTable.put(LASSO, "Magic Lasso");
1703 runeUsesTable.put("Pyrokinesis",
1704 Arrays.asList(0, 35, 36, 39, 87, 295, 650, 6214));
1705 runeIdToRuneNameTable.put(FIREBLAST, "Pyrokinesis");
1706 runeUsesTable.put("Fire Sword",
1707 Arrays.asList(0, 26, 29, 42, 282, 1322, 3098, 30920));
1708 runeIdToRuneNameTable.put(FIRESWORD, "Fire Sword");
1709 runeUsesTable.put("Bow of Translocation",
1710 Arrays.asList(0, 39, 40, 46, 155, 628, 1435, 14082));
1711 runeIdToRuneNameTable.put(TRANSLOCATOR, "Bow of Translocation");
1712 runeIdToRuneNameTable.put(TRANSLOCATOR + 1, "Bow of Translocation");
1713 runeUsesTable.put("Dispel", Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0));
1714 runeIdToRuneNameTable.put(DISPEL, "Dispel");
1715 runeIdToRuneNameTable.put(DISPEL + 1, "Dispel");
1716 runeUsesTable.put("Engraver", Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0));
1717 runeIdToRuneNameTable.put(ENGRAVER, "Engraver");
1718 runeUsesTable.put("Identifier", Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0));
1719 runeIdToRuneNameTable.put(IDENTIFIER, "Identifier");
1720 runeUsesTable.put("Enchantment Swap",
1721 Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0));
1722 runeIdToRuneNameTable.put(ENCHANTMENTSWAP, "Enchantment Swap");
1723 runeIdToRuneNameTable.put(ENCHANTMENTSWAP + 1, "Enchantment Swap");
1724 runeUsesTable.put("Altar of Judgement",
1725 Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0));
1726 runeIdToRuneNameTable.put(JUDGEMENT, "Altar of Judgement");
1727 runeUsesTable.put("Initiation", Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0));
1728 runeIdToRuneNameTable.put(INITIATOR, "Initiation");
1729 runeUsesTable.put("Mouse Trap",
1730 Arrays.asList(0, 28, 29, 34, 130, 546, 1256, 12385));
1731 runeIdToRuneNameTable.put(MOUSETRAP, "Mouse Trap");
1732 runeIdToRuneNameTable.put(MOUSETRAP + 1, "Mouse Trap");
1733 runeUsesTable.put("Accelerator",
1734 Arrays.asList(0, 292, 295, 313, 640, 2059, 4480, 42419));
1735 runeIdToRuneNameTable.put(ACCELERATOR, "Accelerator");
1736 runeUsesTable.put("Phase Block",
1737 Arrays.asList(0, 32, 38, 71, 656, 3191, 7520, 75336));
1738 runeIdToRuneNameTable.put(PHASEBLOCKS, "Phase Block");
1739 runeUsesTable.put("Lock Block",
1740 Arrays.asList(0, 1, 1, 1, 3, 12, 28, 272));
1741 runeIdToRuneNameTable.put(LOCKBLOCKS, "Lock Block");
1742 runeUsesTable.put("Spleef Block",
1743 Arrays.asList(0, 0, 6, 39, 624, 3159, 7488, 75304));
1744 runeIdToRuneNameTable.put(SPLEEFBLOCKS, "Spleef Block");
1745 runeUsesTable.put("Secret Panel",
1746 Arrays.asList(0, 64, 68, 88, 448, 2008, 4672, 46404));
1747 runeIdToRuneNameTable.put(TOGGLER, "Secret Panel");
1748 runeIdToRuneNameTable.put(TOGGLER + 1, "Secret Panel");
1749 runeUsesTable.put("Automation Designator",
1750 Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0));
1751 runeIdToRuneNameTable.put(LOGDST, "Automation Designator");
1752 runeUsesTable.put("Redstone Sensor",
1753 Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0));
1754 runeIdToRuneNameTable.put(LOGRED, "Redstone Sensor");
1755 runeUsesTable.put("Sticky Redstone Sensor",
1756 Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0));
1757 runeIdToRuneNameTable.put(LOGSRED, "Sticky Redstone Sensor");
1758 runeUsesTable.put("Pressure Sensor",
1759 Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0));
1760 runeIdToRuneNameTable.put(LOGPAD, "Pressure Sensor");
1761 runeUsesTable.put("Damage Sensor",
1762 Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0));
1763 runeIdToRuneNameTable.put(LOGHIT, "Damage Sensor");
1764 runeIdToRuneNameTable.put(LOGHITE, "Damage Sensor");
1765 runeUsesTable
1766 .put("Block Sensor", Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0));
1767 runeIdToRuneNameTable.put(LOGBLOCK, "Block Sensor");
1768 runeUsesTable.put("Immersion", Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0));
1769 runeIdToRuneNameTable.put(CTRI, "Immersion");
1770 runeUsesTable.put("Light Pick",
1771 Arrays.asList(0, 87, 96, 140, 940, 4407, 10327, 103067));
1772 runeIdToRuneNameTable.put(LIGHTSWORD, "Light Pick");
1773 runeUsesTable.put("Spider Touch",
1774 Arrays.asList(0, 14, 15, 23, 167, 791, 1857, 18550));
1775 runeIdToRuneNameTable.put(SPIDERTOUCH, "Spider Touch");
1776 runeIdToRuneNameTable.put(SPIDERTOUCH + 1, "Spider Touch");
1777 runeUsesTable.put("Prometheus",
1778 Arrays.asList(0, 0, 0, 0, 1, 6, 14, 136));
1779 runeIdToRuneNameTable.put(PROMETHEUS, "Prometheus");
1780 runeIdToRuneNameTable.put(PROMETHEUS + 1, "Prometheus");
1781 runeUsesTable.put("Magma Gel",
1782 Arrays.asList(0, 9, 9, 10, 16, 50, 245, 1373));
1783 runeIdToRuneNameTable.put(LAVAGEL, "Magma Gel");
1784 runeUsesTable.put("Magic Cake", Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0));
1785 runeIdToRuneNameTable.put(MAGICCAKE, "Magic Cake");
1786 runeUsesTable.put("Pegasus", Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0));
1787 runeIdToRuneNameTable.put(PEGASUS, "Pegasus");
1788 runeUsesTable.put("Whisper Curse",
1789 Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0));
1790 runeIdToRuneNameTable.put(WHISPERCURSE, "Whisper Curse");
1791 runeUsesTable.put("Butterfingers Curse",
1792 Arrays.asList(0, 5, 25, 40, 300, 1600, 3800, 35000));
1793 runeIdToRuneNameTable.put(BUTTERCURSE, "Butterfingers Curse");
1794 runeUsesTable.put("Butterfingers Counter Curse",
1795 Arrays.asList(0, 5, 25, 40, 300, 1600, 3800, 35000));
1796 runeIdToRuneNameTable.put(BUTTERCURSE + 1,
1797 "Butterfingers Counter Curse");
1798 runeUsesTable.put("Touch Hex",
1799 Arrays.asList(0, 5, 15, 21, 50, 218, 1192, 6832));
1800 runeIdToRuneNameTable.put(TOUCHHEX, "Touch Hex");
1801 runeUsesTable.put("Damage Hex",
1802 Arrays.asList(0, 5, 15, 21, 50, 218, 1192, 6832));
1803 runeIdToRuneNameTable.put(DAMAGEHEX, "Damage Hex");
1804 runeUsesTable.put("Portal Hex",
1805 Arrays.asList(0, 5, 15, 21, 50, 218, 1192, 6832));
1806 runeIdToRuneNameTable.put(PORTALHEX, "Portal Hex");
1807 runeUsesTable.put("Permanence", Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0));
1808 runeIdToRuneNameTable.put(PERMANENCE, "Permanence");
1809 runeUsesTable.put("Salvation", Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0));
1810 runeIdToRuneNameTable.put(FAITHOUT, "Salvation");
1811 runeUsesTable.put("Redemption", Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0));
1812 runeIdToRuneNameTable.put(FAITHIN, "Redemption");
1813 runeUsesTable.put("Toggle Blocks",
1814 Arrays.asList(0, 21, 25, 41, 333, 1601, 3765, 37673));
1815 runeIdToRuneNameTable.put(TOGGLEBLOCKS, "Toggle Blocks");
1816 runeUsesTable.put("Danger Ward", Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0));
1817 runeIdToRuneNameTable.put(WARDNGR, "Danger Ward");
1818 runeUsesTable.put("TP ward", Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0));
1819 runeIdToRuneNameTable.put(WARDTP, "TP ward");
1820 runeUsesTable.put("Aether Ward", Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0));
1821 runeIdToRuneNameTable.put(WARDLIGHT, "Aether Ward");
1822 runeUsesTable.put("Void Ward", Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0));
1823 runeIdToRuneNameTable.put(WARDDARK, "Void Ward");
1824 runeUsesTable.put("Tool Ward", Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0));
1825 runeIdToRuneNameTable.put(WARDTOOL, "Tool Ward");
1826 runeUsesTable.put("Flight Ward", Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0));
1827 runeIdToRuneNameTable.put(WARDFLIGHT, "Flight Ward");
1828 runeUsesTable.put("Flight",
1829 Arrays.asList(0, 66, 134, 498, 7043, 35407, 83843, 842624));
1830 runeIdToRuneNameTable.put(LEVITATE, "Flight");
1831 runeUsesTable.put("True Name",
1832 Arrays.asList(0, 0, 0, 1, 6, 34, 80, 806));
1833 runeIdToRuneNameTable.put(TRUENAME, "True Name");
1834 runeIdToRuneNameTable.put(TRUENAME + 1, "True Name");
1835 runeIdToRuneNameTable.put(TRUENAME + 2, "True Name");
1836 runeIdToRuneNameTable.put(TRUENAME + 3, "True Name");
1837 runeUsesTable.put("Babel Curse",
1838 Arrays.asList(0, 5, 10, 20, 40, 80, 200, 750));
1839 runeIdToRuneNameTable.put(BABELCURSE, "Babel Curse");
1840 runeUsesTable.put("Babel Counter Curse",
1841 Arrays.asList(0, 5, 10, 20, 40, 80, 200, 750));
1842 runeIdToRuneNameTable.put(BABELCURSE + 1, "Babel Counter Curse");
1843 runeUsesTable.put("Lightning Trap",
1844 Arrays.asList(0, 1, 3, 5, 10, 20, 60, 180));
1845 runeIdToRuneNameTable.put(SMITETRAP, "Lightning Trap");
1846 runeUsesTable.put("True Name Ward",
1847 Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0));
1848 runeIdToRuneNameTable.put(WARDTRUNAME, "True Name Ward");
1849 runeUsesTable.put("Runic Radio", Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0));
1850 runeIdToRuneNameTable.put(COMMPEARL, "Runic Radio");
1851
1852 // TODO: fiddle with these tier values. Reality masters use table ==
1853 // area, reality anchor == distance from center
1854 runeUsesTable.put("Reality Master", Arrays.asList(0, 729, 2197, 12167,
1855 19683, 27000, 103823, 500000));
1856 runeIdToRuneNameTable.put(REALITYMASTER, "Reality Master");
1857 runeUsesTable.put("Reality Anchor",
1858 Arrays.asList(0, 15, 20, 25, 30, 35, 50, 100));
1859 runeIdToRuneNameTable.put(REALITYANCHOR, "Reality Anchor");
1860 runeUsesTable
1861 .put("Freightpoint", Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7));
1862 runeIdToRuneNameTable.put(FREIGHTPOINT, "Freightpoint");
1863 runeUsesTable.put("Freight Teleporter",
1864 Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7));
1865 runeIdToRuneNameTable.put(FREIGHTTP, "Freight Teleporter");
1866
1867 runeUsesTable.put("Memento",
1868 Arrays.asList(0, 6, 32, 200, 1100, 6500, 32000, 220000));
1869 runeIdToRuneNameTable.put(MEMENTO, "Memento");
1870
1871 // end autogenerated code
1872 // 4, 6, 8, 11, 12, 13, 23)
1873
1874 runeUsesTable.put("Secret Passage",
1875 Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0));
1876 for (int i = 0; i < 6; i++) {
1877 runeIdToRuneNameTable.put(PASSAGE + i, "Secret Passage");
1878 }
1879 runeUsesTable.put("Fire Turret", Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0));
1880 runeIdToRuneNameTable.put(FIRETURRET, "Fire Turret");
1881 runeUsesTable.put("Flare", Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0));
1882 runeIdToRuneNameTable.put(FLARE, "Flare");
1883 runeUsesTable.put("Stairmaster", Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0));
1884 runeIdToRuneNameTable.put(STAIRMASTER, "Stairmaster");
1885 runeUsesTable.put("Faith Wrencher",
1886 Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0));
1887 runeIdToRuneNameTable.put(CTRI2, "Faith Wrencher");
1888 runeUsesTable.put("Xyvaz Test", Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0));
1889 runeIdToRuneNameTable.put(XYVAZ, "Xyvaz Test");
1890 runeUsesTable.put("Communications Tower",
1891 Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0));
1892 runeIdToRuneNameTable.put(COMMTOWER, "Communications Tower");
1893 runeUsesTable.put("Temp Rune", Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0));
1894 runeIdToRuneNameTable.put(TEMPRUNE, "Temp Rune");
1895 runeUsesTable.put("Hell Maw", Arrays.asList(1, 5, 0, 0, 0, 0, 0, 0));
1896 runeIdToRuneNameTable.put(HELLMAW, "Hell Maw");
1897 runeIdToRuneNameTable.put(HELLMAW + 1, "Hell Maw");
1898
1899 runeUsesTable.put("Truename Altar", Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7));
1900 runeIdToRuneNameTable.put(TRUENAMEALTAR, "Truename Altar");
1901
1902 runeUsesTable.put("Genesis", Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7));
1903 runeIdToRuneNameTable.put(GENESIS, "Genesis");
1904 }
1905
1906 void intializeBMT() {
1907 // meta data tiers, make sure list is 16 items long
1908 List<Integer> StoneBlocks = Arrays.asList(2, 3, 3, 5, 0, 0, 0, 0, 0, 0,
1909 0, 0, 0, 0, 0, 0);
1910 bmt.put(98, StoneBlocks);
1911 }
1912
1913 void logInfo(String msg) {
1914 log.info("[Runecraft] " + msg);
1915 }
1916
1917 // **************************
1918 // *** external interface ***
1919
1920 public static void init(final String version, final RuneWorld world) {
1921 if (self == null)
1922 self = new Runecraft_MAIN(version, world);
1923 }
1924
1925 public String getVersion() {
1926 return version;
1927 }
1928
1929 public static void save_data() {
1930 if (self != null) {
1931 self.s_saveToMagicDat(); // force data save; called in onDisable
1932 self.do_s_doSaveToMagicDat();
1933 }
1934 }
1935
1936 // set options from config file or similar; TODO: config file for vanilla
1937 public void set_opt(Set<String> opts) {
1938 opt.clear();
1939 opt.addAll(opts);
1940
1941 }
1942
1943 public boolean readWhiteList() {
1944 wl = false;
1945 rl.clear(); // reset whitelist, so you can reload the file
1946 try {
1947 File f = new File("disabled-runes.txt");
1948 if (!f.exists()) {
1949 BufferedWriter bw = new BufferedWriter(new FileWriter(
1950 "disabled-runes.txt"));
1951 bw.write("#If you wish to disable a rune, list its proper name in this file.\r\n"
1952 + "#This is the name printed when the rune is activated.\r\n"
1953 + "#If you wish to use a whitelist instead, uncomment this line:\r\n"
1954 + "#whitelist\r\n"
1955 + "#list the name of a player to ban them from using magic (except existing teleporters).\r\n"
1956 + "#here are some extra options you can add to the list:\r\n"
1957 + "# enable travel ink - force teleporters and waypoints to be made of a specific material\r\n"
1958 + "# ink X - dermine the block type (X) to use for travel ink-- you must add this if you add the above\r\n"
1959 + "# enable teleport toll - force users of teleporters to sacrifice a specific block in the center\r\n"
1960 + "# toll X - determine the block type (X) to use for travel toll-- you must add this if you add the above\r\n"
1961 + "# enable multiworld travel - allows teleportation between worlds in bukkit.\r\n"
1962 + "# initiation - players cannot use runes until they activate a special rune containing bedrock\r\n"
1963 + "# judgement - allows the creation of the altar of judgement, allowing players to modify disabled-runes ingame.\r\n"
1964 + "# salvation - Saves a faith island to a file in the main world folder.\r\n"
1965 + "# redemption - loads a faith island from a file in the main world folder.\r\n"
1966 + "# signature assignments - Enables TP/Automation signature restrictions.\r\n"
1967 + "# Define them like this: (3 spaces)\r\n"
1968 + "# name,north,east,south,west \r\n"
1969 + "# SuperLlama,35,37,*,* \r\n"
1970 + "# Zeerix,35,38,4,* \r\n"
1971 + "# Ctri,*,122,4,* \r\n"
1972 + "# *,*,*,* (for the default assignment group)\r\n"
1973 + "# These all stack, allowing multiple sig groups per person.\r\n\r\n"
1974 +
1975
1976 "# World Groups - Enables the restriction of TPs/FTPs/Zeerix Chest to a collection of worlds.\r\n"
1977 + "# Define the group like this, based on world folder name.\r\n"
1978 + "# WorldGroup world, world_nether, world_the_end\r\n"
1979 + "# WorldGroup creative, creative_2 \r\n"
1980 + "# With this enabled, worlds ungrouped will be freely accessible by other ungrouped worlds. \r\n\r\n"
1981 +
1982
1983 "# use MultiGroupInk to define teleport/FTP/etc inks that can escape world groups \r\n"
1984 + "# MultiGroupInk 57 (would allow diamond runes to travel freely) \r\n"
1985 + "# MultiGroupInk 7 (would allow bedrock runes to travel freely) \r\n"
1986 + "# use MultiGroupRune to define teleport/FTP/etc runes can escape world groups \r\n"
1987 + "# MultiGroupRune recall (would allow recall rune to travel freely) \r\n"
1988 + "# \r\n"
1989 + "# --Below comes an auto generated list of rune names. Simply remove the # to disable that rune --\r\n"
1990 + "# --(or if you have 'whitelist' enabled, to enable them)-- \r\n"
1991 + "\r\n");
1992 for (String str : runeIdToRuneNameTable.values()) {
1993 bw.write("#" + str + "\r\n");
1994 }
1995
1996 bw.close();
1997 }
1998 BufferedReader br = new BufferedReader(new FileReader(f));
1999 int indentmode = 0;
2000 boolean wgs = false; // world groups
2001 for (String ln = br.readLine(); ln != null; ln = br.readLine()) {
2002 ln = ln.replaceAll("[^A-Za-z0-9 #:,*]+", "").toLowerCase();
2003 if (ln.equals("whitelist"))
2004 wl = true;
2005 else if (ln.startsWith("tier ")) {
2006 // block composite
2007 String bc = ln.split(" ")[1];
2008 int bo;
2009 // new tier
2010 int nt = Integer.parseInt(ln.split(" ")[2]);
2011
2012 if (bc.split(":").length > 1) {
2013 bo = Integer.parseInt(bc.split(":")[0]);
2014 // old tier
2015 int ot = bt_blockTier[bo];
2016 int bm = Integer.parseInt(bc.split(":")[1]);
2017 List<Integer> ml = Arrays.asList(ot, ot, ot, ot, ot,
2018 ot, ot, ot, ot, ot, ot, ot, ot, ot, ot, ot);
2019
2020 if (bmt.containsKey(bo)) {
2021 ml = bmt.get(bo);
2022
2023 }
2024 // logInfo("ot="+ot+" bo="+bo+" bm="+bm +" nt="+nt);
2025 if (bm >= 0 && bm < 16)
2026 ml.set(bm, nt);
2027 if (bo > 0 && bo < 255 && nt >= 0 && nt <= MAX_TIER)
2028 bmt.put(bo, ml);
2029 logInfo("Tier of block #" + bo + " with metadata " + bm
2030 + " set to " + nt + ".");
2031 } else {
2032 bo = Integer.parseInt(ln.split(" ")[1]);
2033 if (bo > 0 && bo < 255 && nt >= 0 && nt <= MAX_TIER)
2034 bt_blockTier[bo] = nt;
2035 logInfo("Tier of block #" + bo + " set to " + nt + ".");
2036 }
2037
2038 } else if (ln.toLowerCase().startsWith("enable world groups")) {
2039 logInfo("Enabling world groups");
2040 wgs = true;
2041 } else if (ln.toLowerCase().startsWith("worldgroup ") && wgs) {
2042 String dbgoutput = "Grouping worlds ";
2043 String[] worlds = ln.substring(11).split(", ");
2044 List<Integer> worldIDs = createLList();
2045 for (String worldname : worlds) {
2046 worldIDs.add(Integer.parseInt(worldname));
2047 dbgoutput += "[" + Integer.parseInt(worldname) + "]";
2048 }
2049 logInfo(dbgoutput);
2050 wgl.add(worldIDs);
2051
2052 } else if (ln.toLowerCase().startsWith("multigroupink") && wgs) {
2053 try {
2054 final int ink = Integer.parseInt(ln.split(" ")[1]);
2055 logInfo("Multigroup ink: " + ink);
2056 wgo.add(ink);
2057 } catch (NumberFormatException e) {
2058 logInfo("Unable to parse Multigroup ink line: " + ln);
2059 }
2060 // logInfo("adding block ID "+Integer.parseInt(ln.split(" ")[1])+"to multi-group inks");
2061 } else if (ln.toLowerCase().startsWith("signature assignment")) {
2062 indentmode = 1;
2063 } else if (ln.startsWith(" ")) {
2064
2065 if (indentmode == 1) {
2066 ln = ln.substring(3);
2067 String[] str = ln.split(",");
2068 if (str.length == 5)
2069 logInfo(str[0] + "," + str[1] + "," + str[2] + ","
2070 + str[3] + "," + str[4]);
2071 if (str.length == 4)
2072 logInfo(str[0] + "," + str[1] + "," + str[2] + ","
2073 + str[3]);
2074 wpassgnl.add(str);
2075
2076 }
2077
2078 } else if (ln.startsWith("april fools"))
2079 APRIL_FOOLS = true;
2080 else if (!ln.startsWith("#"))
2081
2082 rl.add(ln);
2083 }
2084 br.close();
2085 // logInfo("World grouping status = "+wgs);
2086 } catch (Exception e) {
2087 e.printStackTrace();
2088 return false;
2089 }
2090
2091 logInfo("Rune " + (wl ? "white" : "black") + "list with " + rl.size()
2092 + " runes loaded.");
2093 return true;
2094 }
2095
2096 public void reassignTierValue(int blockID, int newTier) {
2097 // specifically for finding a "tier"
2098 boolean add = true;
2099 String line = "";
2100 List<String> trl = createLList();
2101 try {
2102 File f = new File("disabled-runes.txt");
2103
2104 BufferedReader br = new BufferedReader(new FileReader(f));
2105
2106 for (String ln = br.readLine(); ln != null; ln = br.readLine()) {
2107 if (!ln.toLowerCase().startsWith("tier " + newTier))
2108 trl.add(ln);
2109 else
2110 // we have found an instance of a tier change!
2111 if (newTier == 0) {
2112 add = false; /* erase the line */
2113 } else {
2114 add = true;
2115 trl.add("tier " + blockID + " " + newTier);
2116 }
2117 }
2118 br.close();
2119 } catch (Exception e) {
2120 e.printStackTrace();
2121 }
2122 toggleDisabledRunesTxt(trl, line, add);
2123 }
2124
2125 public void toggleDisabledRunesTxt(String line) {
2126 boolean add = true;
2127 List<String> trl = createLList();
2128 try {
2129 File f = new File("disabled-runes.txt");
2130
2131 BufferedReader br = new BufferedReader(new FileReader(f));
2132
2133 for (String ln = br.readLine(); ln != null; ln = br.readLine()) {
2134 if (!ln.toLowerCase().equals(line.toLowerCase()))
2135 trl.add(ln);
2136 else
2137 add = false;
2138 }
2139 br.close();
2140 } catch (Exception e) {
2141 e.printStackTrace();
2142 }
2143 toggleDisabledRunesTxt(trl, line, add);
2144
2145 }
2146
2147 public void toggleDisabledRunesTxt(List<String> trl, String line,
2148 boolean add)
2149 // this method is basically just for outputting input from toggle_t_rl, or
2150 // toggle_rl
2151 {
2152 try {
2153 File f = new File("disabled-runes.txt");
2154 BufferedWriter bw = new BufferedWriter(new FileWriter(f));
2155 for (String ln : trl) {
2156 bw.write(ln);
2157 bw.newLine();
2158 }
2159 if (add) {
2160 bw.write(line);
2161 bw.newLine();
2162 logInfo("The line \"" + line
2163 + "\" was added to disabled-runes.txt.");
2164 } else
2165 logInfo("The line \"" + line
2166 + "\" was removed from disabled-runes.txt.");
2167 bw.close();
2168 } catch (Exception e) {
2169 e.printStackTrace();
2170 }
2171
2172 }
2173
2174 // *** end external interface ***
2175 // ********************************
2176 // *** event dispatch functions ***
2177
2178 /**
2179 * Called when a block was right-clicked (tp=0)
2180 *
2181 * @param pl
2182 * Player
2183 * @param i
2184 * The item in the player's hand
2185 * @param x
2186 * ,y,z Location of the clicked block
2187 * @param f
2188 * the face it was clicked on
2189 */
2190 boolean on_rightClick(RunePlayer pl, int i, int x, int y, int z, int f) {
2191 RunePlayer originalPlayer = pl;
2192
2193 // DBG("activating item: "+i);
2194 boolean truenameused = false;
2195 boolean b1, b2, b3, b4 = b3 = b2 = b1 = false;
2196
2197 if (i > 0)
2198 b2 = d_doMasterToolEnchantment(TP_RIGHTCLICK, i, pl, x, y, z, f); // TOOL
2199
2200 if (!b2 && (i > 255 || i == 0)) {
2201 b1 = d_handlePRdigging(TP_RIGHTCLICK, originalPlayer, x, y, z, 0, f);
2202 } // RCM
2203
2204 rcm rune = a(originalPlayer, x, y, z, i, f);
2205 rcm curse = getcr(x, y, z, originalPlayer.getWorld().getWorldId());
2206 if (rune.runePattern != 0 || curse != null) {
2207
2208 pl = pl.getTargetPlayerViaTrueName();
2209 if (pl != originalPlayer) {
2210 truenameused = true;
2211 }
2212 }
2213 // int tp, RunePlayer pl, int x, int y, int z, int r
2214 // rv = pr_doPositionRune(pl, tp, r, e, null, 0);
2215
2216 if (!b2 && (i > 255 || i == 0)) {
2217 b4 = d_handleCRdigging(TP_RIGHTCLICK, pl, x, y, z, 0);
2218 } // RCM
2219
2220 if (!b2)
2221 b3 = d_masterRuneFunctionExecute(rune, pl, pl.getWorld(), f); // RUNE
2222
2223 if (truenameused)// rune or hexblock activated successfully
2224 {
2225 originalPlayer.destroyHelmet();
2226 DBG(EnChat.PURPLE + originalPlayer.aw_getName()
2227 + " Performed Black Magic upon " + pl.aw_getName());
2228 originalPlayer.ab(EnChat.PURPLE + "You have used " + pl.aw_getName()
2229 + "'s True Name. It crumbles to dust around you.");
2230 pl.ab(EnChat.PURPLE
2231 + "Someone has just used your True Name to cast magic upon you. ");
2232 }
2233
2234 if (b2 || b3 || b1) {
2235 if (RunecraftParser.b_blockOrBlockTool(i)) // is it a block?
2236 r(x, y, z, f); // go back a face?
2237 // DBG("Returning true from a right click event ["+b2+"]["+b3+"]["+b1+"]");
2238 return true;
2239 }
2240 return false;
2241 }
2242
2243 void on_invSelectChange(RunePlayer pl, int iNew, int[] iaNew, int iOld,
2244 int[] iaOld) {
2245 // DBG(Chat.RED+"old (held) "+ iOld +"= new (not yet selected) "+ iNew);
2246
2247 // note
2248 boolean b1, b2 = b1 = false;
2249
2250 if (iaOld != null) {
2251 b2 = d_doToolEngravedEnchantment(TP_INV_HOLDING, iOld, pl, 0, 0, 0,
2252 -1, iaOld);
2253 } else {
2254 b2 = d_doToolTypeEnchantment(TP_INV_HOLDING, iOld, pl, 0, 0, 0, -1);
2255 }// old item
2256 // needs to know if it's being changed INTO, or ONTO. maybe using
2257 // facing!
2258
2259 // in the event of changing AWAY, this isn't called, but when changing
2260 // TOO, this is.
2261 if (iaNew != null) {
2262 b1 = d_doToolEngravedEnchantment(TP_INV_HOLDING, iNew, pl, 0, 0, 0,
2263 1, iaNew);
2264 } else {
2265 b1 = d_doToolTypeEnchantment(TP_INV_HOLDING, iNew, pl, 0, 0, 0, 1);
2266 }// new item
2267
2268 // DBG(Chat.RED+"End of invSelectchange "+b1+":"+b2);
2269 }
2270
2271 void updateRRreceive(RunePlayer pl) {
2272 /*
2273 * if (pl != null) DBG("ring ring" + pl.aw_getName());
2274 */
2275 List<Integer> oldFrequencies = rrReceived.get(pl.aw_getName());
2276
2277 if (oldFrequencies == null)
2278 oldFrequencies = new ArrayList<Integer>();
2279 rrReceived.put(pl.aw_getName(), new ArrayList<Integer>());
2280 rrReceived.get(pl.aw_getName()).clear();
2281
2282 if (pl.inventoryContains(368)) {
2283 d_doMasterToolEnchantment(TP_PASSIVE, 368, pl, 0, 0, 0, -1);
2284 for (int[] ia : pl.gAllEnch(TP_CATCHALL, 368)) {
2285 d_doToolEngravedEnchantment(TP_PASSIVE, 368, pl, 0, 0, 0, -1,
2286 ia);
2287 }
2288 }
2289 // go through the player's inventory
2290 // gench for each of these
2291
2292 }
2293
2294 void updateRRtransmit(RunePlayer pl) {
2295 // DBG("updating transmit for ",pl);
2296 if (pl.Pc() != 368)
2297 rrTransmit.remove(pl.aw_getName());
2298 if (pl.Pc() == 368) {
2299 d_doMasterToolEnchantment(TP_CATCHALL, 368, pl, 0, 0, 0, 1);
2300 } else {
2301 d_doToolTypeEnchantment(TP_CATCHALL, 368, pl, 0, 0, 0, -1);
2302 }
2303
2304 }
2305
2306 void transmitRR(int frequency, String message, String playerName) {
2307
2308 String output = /* "\u00A7"+(frequency % 16)+"@+"+frequency+ Chat.WHITE+ */"#"
2309 + playerName + "# ";
2310 Integer colourcode = rrTransmitColour.get(playerName);
2311 if (colourcode != null)
2312 output += "\u00A7" + wooltohex(colourcode);
2313 output += message;
2314 logInfo(frequency + ": " + output);
2315 for (String rcvPlayerName : rrReceived.keySet()) {
2316 List<Integer> frequencies = rrReceived.get(rcvPlayerName);
2317 if (frequencies != null)
2318 if (frequencies.contains(frequency)) {
2319 RunePlayer pl = getPlayerByName(rcvPlayerName);
2320
2321 if (pl != null)
2322 pl.ab(output);
2323 }
2324
2325 }
2326 }
2327
2328 /*
2329 * RuneWorld w = pl.getWorld();
2330 *
2331 * b1 = (i > 0 && d(0, i, pl, x, y, z, f)); if (!b1 )b2 = d( a(pl, x, y, z,
2332 * i, f), pl, w,f); if (!b1 && !b2)b3 = d(0,pl,x,y,z,0);
2333 *
2334 * //DBG("activating item: "+i + "b123 = "+b1+":"+b2+":"+b3); if (b1 || b2
2335 * ){ if (rcn.b(i)) r(x, y, z, f); return true; } return false;}
2336 */
2337 boolean on_projectileLaunch(RunePlayer pl) {
2338
2339 int ta[] = pl.gench(TP_ALL);
2340 if (ta != null) {
2341 DBG("Engraved enchant found, preventing throw");
2342 return true; // prevent the throwing/ launching of right-click
2343 // enchanted objects
2344 }
2345 if (r_searchForToolTypeEnchants(pl, TP_ALL, pl.Pc(), 0)) {
2346 DBG("unengraved enchant found, preventing throw");
2347 return true;
2348 }
2349 DBG("no enchant for held item, throwing! = " + pl.Pc(), pl);
2350 return false;
2351 }
2352
2353 /**
2354 * Called when a block was placed (tp=4)
2355 *
2356 * @param pl
2357 * Player
2358 * @param i
2359 * The item in the player's hand
2360 * @param x
2361 * ,y,z Location of the placed block
2362 * @param f
2363 * Face; the direction the placed block is relative to the
2364 * clicked block
2365 */
2366 boolean on_blockPlacement(RunePlayer pl, int i, int x, int y, int z, int f) {
2367 if (RunecraftParser.b_blockOrBlockTool(i)
2368 && pl.getWorld().a(x, y, z) != 0) {
2369 if (!d_doMasterToolEnchantment(TP_PLACED, i, pl, x, y, z, f))
2370 return d_handleDigging(TP_PLACED, pl, x, y, z, 0);
2371 }
2372 return false;
2373 }
2374
2375 /**
2376 * Called for some digging actions
2377 *
2378 * @param tp
2379 * Type of action: 1:ArmSwing, 2:Digging, 3:BlockBreak
2380 * @param pl
2381 * Player
2382 * @param x
2383 * , y, z Block or location
2384 * @param f
2385 * Face; might be -1: unknown
2386 * @return true: Cancel action
2387 */
2388 boolean on_digging(EnAction tp, RunePlayer pl, int x, int y, int z, int f) {// TODO
2389 // add
2390 // TrueName
2391 // swap
2392 // for
2393 // Damage
2394 // Sensor.
2395 // Don't
2396 // let
2397 // players
2398 // steal
2399 // tool
2400 // swings,
2401 // though.
2402 int i = pl.Pc();
2403
2404 // If we are trying to break the block, AND we are trying to move this
2405 // block with faith / pegasus
2406 if (tp == TP_BROKEN && isBlockMoving(pl.getWorld(), x, y, z)) {
2407 pl.ab(EnChat.RED + "This block is being held by the aether!");
2408 return true;
2409 }
2410
2411 if (i >= 0 && d_doMasterToolEnchantment(tp, i, pl, x, y, z, f))
2412 return true;
2413 d_doMasterToolEnchantment(tp, 0, pl, x, y, z, f); // curse checker?
2414 if (tp != TP_SWING) {
2415 boolean res = d_handleDigging(tp, pl, x, y, z, f);
2416 return tp == TP_BROKEN && res;
2417 }
2418 return false;
2419 }
2420
2421 /**
2422 * Checks if this block is being moved by a faith island
2423 *
2424 * @param w
2425 * RuneWorld
2426 * @param x
2427 * , y, z block or location
2428 *
2429 */
2430 boolean isBlockMoving(RuneWorld w, int x, int y, int z) {
2431
2432 for (final int j : mfrl) {
2433
2434 final int[] fa = faithRuneList.get(j);
2435
2436 // Blocking check, planning to improve to a non-blocking method
2437 // non-blocking check: find potentially blocking islands. Instead of
2438 // saving data from these blocks, replace with air in saved data.
2439 // try to use this to
2440 if (fa[4] == -1 || fa[4] == w.getWorldId())
2441 if (radiuscheck(x, y, z, fa[0], fa[1], fa[2], fa[3] + 0.5)) {
2442 // DBG("fa[3] ia "+fa[3] +" and FI[3] is " + fi[3],pl);
2443 return true;
2444 }
2445 }
2446 return false;
2447 }
2448
2449 /**
2450 * Called when the text on a sign changes
2451 *
2452 * @param x
2453 * ,y,z: Coordinates of sign
2454 * @param txt
2455 * : Text lines
2456 */
2457 void on_ls_signTextChange(RuneWorld w, int x, int y, int z, String txt[]) {
2458 rcm e;
2459 synchronized (positionRune) {
2460 e = getpr(x, y, z, getWorldId(w));
2461 }
2462 if (e != null && e.runePattern == 3)
2463 t(w, e.toolArmorType, (int[]) null, null).runSign(txt, e.x, e.y,
2464 e.z);
2465 }
2466
2467 /**
2468 * Called when redstone current changes
2469 *
2470 * @param x
2471 * ,y,z: Block that changes current
2472 * @param ol
2473 * : old current level
2474 * @param nl
2475 * : new current level
2476 * @return new level
2477 */
2478 int on_rs_redstoneCurrentChange(RuneWorld w, int x, int y, int z, int ol,
2479 int nl) {
2480
2481 if ((ol != 0 && nl != 0) || ol == nl)
2482 return -1; // trigger on edges only
2483
2484 final int edge = nl != 0 ? 1 : -1; // 0->1 or 1->0
2485
2486 // find a connected Lock Block
2487 final int wid = getWorldId(w);
2488 final int b = w.a(x, y, z); // get trigger block type
2489
2490 synchronized (positionRune) {
2491 switch (b) {
2492 case RS_TORCH:
2493 case RS_TORCH_OFF: {
2494 final rcm e = getpr(x, y + 1, z, wid); // the block above the
2495 // torch
2496 rs_t(w, e, b, edge);
2497 break;
2498 }
2499 case RS_WIRE: {
2500 rcm e = getpr(x, y - 1, z, wid); // the block below the wire
2501 rs_t(w, e, b, edge);
2502
2503 for (int[] dir : RCT_main.around2d) {
2504 if (w.a(x + dir[1], y, z + dir[0]) == RS_WIRE
2505 || w.a(x - dir[1], y, z - dir[0]) == RS_WIRE)
2506 continue; // the wire must end in the block
2507 e = getpr(x + dir[0], y, z + dir[1], wid);
2508 rs_t(w, e, b, edge);
2509 }
2510 break;
2511 }
2512 case LEVER:
2513 case BUTTON:
2514 case WOOD_BUTTON: {
2515 final rcm e;
2516
2517 switch (w.b(x, y, z) % 8) {
2518 case 0:
2519 case 7:
2520 e = getpr(x, y + 1, z, wid);
2521 break; // UP
2522 case 5:
2523 case 6:
2524 e = getpr(x, y - 1, z, wid);
2525 break; // DOWN
2526 case 1:
2527 e = getpr(x - 1, y, z, wid);
2528 break; // WEST
2529 case 2:
2530 e = getpr(x + 1, y, z, wid);
2531 break; // EAST
2532 case 3:
2533 e = getpr(x, y, z - 1, wid);
2534 break; // NORTH
2535 case 4:
2536 e = getpr(x, y, z + 1, wid);
2537 break; // SOUTH
2538 default:
2539 throw new RuntimeException("Math is broken?");
2540 }
2541
2542 rs_t(w, e, b, edge);
2543 break;
2544 }
2545 case RS_REPEATER:
2546 case RS_REPEATER_OFF:
2547 case RS_COMPARATOR:
2548 case RS_COMPARATOR_OFF:
2549 case TRIPWIRE_HOOK: {
2550 final rcm e;
2551 switch (w.b(x, y, z) % 4) {
2552 case 0:
2553 e = getpr(x, y, z - 1, wid);
2554 break; // NORTH
2555 case 1:
2556 e = getpr(x + 1, y, z, wid);
2557 break; // EAST
2558 case 2:
2559 e = getpr(x, y, z + 1, wid);
2560 break; // SOUTH
2561 case 3:
2562 e = getpr(x - 1, y, z, wid);
2563 break; // WEST
2564 default:
2565 throw new RuntimeException("Math is broken?");
2566 }
2567 rs_t(w, e, b, edge);
2568 break;
2569 }
2570 }
2571 }
2572 return -1;
2573 }
2574
2575 // called when a pr is triggered by redstone
2576 void rs_t(RuneWorld w, rcm e, int b, int edge) {
2577
2578 if (e != null)
2579 switch (e.runePattern) {
2580 case LOCKBLOCKS:
2581 // wDBG("Redstone schedule of PBLB");
2582 t(w, 7, null, e.x, e.y, e.z, b, edge).scheduleSync(0);
2583 break;
2584 case LOGRED:
2585 /*
2586 * if (w.a(e.x,e.y-1,e.z) != IRON_BLOCK) pr.remove(e); else
2587 */
2588 if (edge > 0) {
2589 RuneDummy dummy = new RuneDummy(w, "Redstone");
2590 dummy.setPos(e.x, e.y, e.z);
2591 ls_r(w, dummy, 0, -1, e.length, e.metaData,
2592 e.toolArmorType, 0, 0, 0, 0);
2593 }
2594
2595 break;
2596 case LOGSRED:
2597 /*
2598 * if (w.a(e.x,e.y-1,e.z) != IRON_BLOCK) pr.remove(e); else
2599 */
2600
2601 if (edge > 0) {
2602 // DBG("Activation of a redstone sticky sensor ["+e.x+","+e.y+","+e.z+"]");
2603
2604 synchronized (worlds) {
2605 for (RuneWorld wor : worlds.values()) {
2606 if (wgc(e.w, wor.getWorldId(), 0,
2607 runeIdToRuneNameTable.get(LOGSRED))) {
2608 RuneDummy dummy = new RuneDummy(wor, "Redstone");
2609 dummy.setPos(e.x, e.y, e.z);
2610
2611 ls_r(wor, dummy, 0, -1, e.length, e.metaData,
2612 e.toolArmorType, 0, 0, 0, 0);
2613 }
2614 }
2615 }
2616
2617 }
2618 break;
2619 case MEMENTO:
2620 DBG("state [" + e.metaData + "] edge [" + edge + "]");
2621 if (e.metaData == 1 && edge > 0) {
2622 } else if (e.metaData == 0 && edge < 0) {
2623 } else {
2624 d_handlePRdigging(TP_RIGHTCLICK, new RuneDummy(w,
2625 "Redstone"), e.x, e.y, e.z, 0, -1);
2626 }
2627
2628 }
2629 }
2630
2631 // trigger all right-click functions with a certain logic signature.
2632 void ls_r(RuneWorld w, RunePlayer pl, int tl, int dir, int s, int s2,
2633 int k, int x, int y, int z, int dst) {
2634 // DBG("ls_r entry",pl);
2635 synchronized (logicDestinationRuneList) {
2636 int counter = 0;
2637 for (int[] ta : logicDestinationRuneList) {
2638 RuneDummy autoDummy = new RuneDummy(getWorldById(ta[3]),
2639 "Automation");
2640 autoDummy.setPos(ta[0], ta[1], ta[2]);
2641 // does signature and key match?
2642 if (ta[4] != s || ta[5] != s2 || (ta[6] != k && ta[6] != 0))
2643 continue;
2644
2645 // range check
2646
2647 // Do worlds match or is trigger multi-world sensor?
2648 // Using -1 to trigger multiworld, as this will also trigger
2649 // infinite distance.
2650 // Only makes sense. If a rune can trigger automation across
2651 // worlds, reaching anywhere in it's world only makes sense
2652
2653 if (ta[3] != w.getWorldId() && dst >= 0) {
2654 continue;
2655 }
2656
2657 RunePlayer usePl;
2658 if (dst < 0) {
2659 usePl = autoDummy;
2660 } else {
2661 usePl = pl;
2662 }
2663
2664 // System.out.println("ta[0] = " + ta[0] + ", s = " + s +
2665 // ", dst*dst = " + dst*dst + ", rdst = " + rdst);
2666 if (radiuscheck(x - ta[0], y - ta[1], z - ta[2], dst)
2667 || dst <= 0) {
2668
2669 // TOOL -> RCM -> RUNE
2670 counter++;
2671 String dbg = EnChat.BLUE.toString() + counter + EnChat.GREEN
2672 + "[" + EnChat.YELLOW + ta[0] + "," + ta[1] + ","
2673 + ta[2] + EnChat.GREEN + "] ";
2674 int ea = 0;
2675 int ra = 0;
2676 rcm e = getpr(ta[0], ta[1], ta[2], ta[3]);
2677 if (e != null) {
2678 pr_doPositionRune(usePl, TP_RIGHTCLICK, -1, e, null, 0);
2679 dbg += EnChat.PURPLE + "Block " + EnChat.GREEN + ": "
2680 + EnChat.YELLOW
2681 + runeIdToRuneNameTable.get(e.runePattern)
2682 + EnChat.GREEN;
2683 ea = e.runePattern;
2684 }
2685
2686 rcm cr = getcr(ta[0], ta[1], ta[2], ta[3]);
2687 if (cr != null) {
2688 if (cr.metaData == TP_RIGHTCLICK.getCode()) {
2689 pr_doPositionRune(usePl, TP_RIGHTCLICK, -1, cr,
2690 null, 0);
2691 DBG("Found an automated CR!");
2692 }
2693 }
2694
2695 e = a(usePl, ta[0], ta[1], ta[2], tl, -1);
2696 if (e.runePattern == 0) {
2697 e = a(usePl, ta[0], ta[1], ta[2], 0, -1);
2698 }
2699 if (e.runePattern != 0) {
2700 dbg += EnChat.PURPLE + " Rune" + EnChat.GREEN + ": "
2701 + EnChat.YELLOW
2702 + runeIdToRuneNameTable.get(e.runePattern)
2703 + EnChat.GREEN;
2704 ra = e.runePattern;
2705 }
2706
2707 if (ra != 0 || ea != 0) {
2708 DBG(dbg, usePl);
2709 }
2710 d_masterRuneFunctionExecute(e, usePl, usePl.getWorld(), dir);
2711
2712 // check this is taking tool data
2713
2714 // DBG("rn = ["+rn +","+e.a+
2715 // "] rv = ["+rv+"] @ "+ta[0]+","+ta[1]+","+ta[2]);
2716
2717 }
2718
2719 }
2720 }
2721 }
2722
2723 /**
2724 * Called when shooting a bow (tp=7)
2725 *
2726 * @param pl
2727 * Player
2728 * @param tl
2729 * tool (bow!)
2730 * @param fo
2731 * force/span; 0.1 - 1.0
2732 * @return true: Cancel action
2733 */
2734 boolean on_bow(RunePlayer pl, int tl, float fo) {
2735 if (tl > 0
2736 && d_doMasterToolEnchantment(TP_ARROWLAUNCH, tl, pl, 0, 0, 0,
2737 (int) (fo * 100))) {
2738 return true;
2739 }
2740 return false;
2741 }
2742
2743 /**
2744 * Called when an enchanted arrow hits a block
2745 *
2746 * @param w
2747 * The world the arrow is in
2748 * @param pl
2749 * Shooter
2750 * @param x
2751 * ,y,z Block hit location
2752 * @param eff
2753 * The arrow effect & extra data
2754 * @return true: Remove effect from arrow
2755 */
2756 boolean on_ahit(RuneWorld w, RunePlayer pl, int x, int y, int z, int[] eff) {
2757 // DBG("Arrow has hit, repeat, the arrow has hit.");
2758 switch (eff[0]) {
2759
2760 case LIGHTBOW:
2761 if (eff[1] == AIR)
2762 break;
2763 while (y <= w.getMaxY() && w.a(x, y, z) != AIR
2764 && w.a(x, y, z) != SNOW)
2765 ++y;
2766 if (y <= w.getMaxY())
2767 if (w.try_bp(pl, x, y, z, eff[1], 0)) {
2768 w.e(x, y, z, eff[1]);
2769 }
2770 break;
2771 case GLOWARROWBOW: {
2772 w.Explode(x, y, z, eff[1], true);
2773 break;
2774 }
2775 default:
2776 t(w, eff[0], eff, pl).runAt(x, y, z, 0, 0, TP_ARROWLAUNCH);
2777 }
2778
2779 return true;
2780 }
2781
2782 // **********************************
2783 // *** digging handler and others ***
2784
2785 boolean d_handleDigging(EnAction tp, RunePlayer pl, int x, int y, int z, int r) // first
2786 // D
2787 {
2788 boolean crproc = d_handleCRdigging(tp, pl, x, y, z, r);
2789 boolean prproc = d_handlePRdigging(tp, pl, x, y, z, r);
2790 return crproc || prproc;
2791 }
2792
2793 boolean d_handlePRdigging(EnAction tp, RunePlayer pl, int x, int y, int z,
2794 int r) {
2795 return d_handlePRdigging(tp, pl, x, y, z, r, 0);
2796 }
2797
2798 boolean d_handlePRdigging(EnAction tp, RunePlayer pl, int x, int y, int z,
2799 int r, int f) {
2800
2801 RuneWorld w = pl.getWorld();
2802 int wid = getWorldId(w);
2803 int rv = 0;
2804 synchronized (positionRune) {
2805 rcm e = getpr(x, y, z, wid);
2806 if (e != null)
2807 // hit an enchanted block directly
2808 rv = pr_doPositionRune(pl, tp, r, e, null, 0, f);
2809 // DBG("rv = " + rv);
2810 if (rv == 0) {
2811 // hit neighbors of enchanted blocks
2812 for (int[] dir : RCT_main.around) {
2813 e = getpr(x + dir[0], y + dir[1], z + dir[2], wid);
2814 if (e != null)
2815 rv = pr_doPositionRune(pl, tp, r, e, dir, rv);
2816 }
2817 }
2818 }
2819 // DBG("Returning "+(rv != 0),pl);
2820 return rv != 0;
2821 }
2822
2823 boolean d_handleCRdigging(EnAction tp, RunePlayer pl, int x, int y, int z,
2824 int r) {
2825 RuneWorld w = pl.getWorld();
2826 int wid = getWorldId(w);
2827
2828 // get positional enchantments
2829 int rv = 0;
2830 synchronized (hexRune) {
2831 rcm e = getcr(x, y, z, wid);
2832 if (e != null)
2833 // hit a hexed block directly
2834
2835 rv = pr_doPositionRune(pl, tp, r, e, null, 0);
2836 }
2837 return rv != 0;
2838 }
2839
2840 // helper routine for getting tier of a block
2841
2842 static int gt_getTier(int x, int y, int z, RuneWorld w) {
2843 int b = w.a(x, y, z);
2844 int bm = w.b(x, y, z);
2845 return (gt_getTierByMetaValue(b, bm));
2846 }
2847
2848 static int gt_getTierByMetaValue(int b, int bm) {
2849 if (bm < 0 || bm > 15)
2850 return bt_blockTier[b];
2851 return (bmt.containsKey(b) ? bmt.get(b).get(bm) : bt_blockTier[b]);
2852 }
2853
2854 static int gt_getTier(int b) {
2855 return bt_blockTier[b];
2856 }
2857
2858 // / helper routine for positional rune enchantments; call it synchronized
2859 // on pr
2860
2861 protected rcm getpr(int x, int y, int z, int wid) {
2862 final rcm getpr_ = new rcm(x, y, z, wid);
2863 return positionRune.get(getpr_);
2864 }
2865
2866 // positional rune enchantment
2867 //
2868 int pr_doPositionRune(RunePlayer pl, EnAction tp, int r, rcm e, int[] dir,
2869 int rv) {
2870 return pr_doPositionRune(pl, tp, r, e, dir, rv, -1);
2871 }
2872
2873 int pr_doPositionRune(RunePlayer pl, EnAction tp, int r, rcm e, int[] dir,
2874 int rv, int face) {
2875 // if (e.a != 2)
2876 // DBG("PR "+e.a+" activated TP:["+tp+"] r:["+r+"] "+Chat.YELLOW+"["+e.x+","+e.y+","+e.z+"]",pl);
2877 RuneWorld w = pl.getWorld();
2878 switch (e.runePattern) {
2879 // legacy position runes (Hidden Passage, ...)
2880 case 0:
2881 // legacy position runes only on direct hit (dir == null)
2882 // check if any position rune applies
2883 if (dir == null) {
2884 DBG("legacy PR Entry");
2885 for (int i = 0; i < positionRuneList.size(); i++) {
2886 int[] ta = positionRuneList.get(i);
2887
2888 int f = tf[ta[0] - 1];
2889 if (f == 2 && tp != TP_DIGGING)
2890 continue;
2891 if (f == 4 && tp != TP_PLACED)
2892 continue;
2893 if (tp == TP_BROKEN && f != 3)
2894 continue;
2895 int sz = 2;
2896 if (ta[0] == 1)
2897 sz = ta[9]; // hidden passage
2898 if (ta[0] == 1 && tp == TP_DIGGING && ta[8] == 1)
2899 continue;
2900 // int[] ta = positionRuneList.get(i);
2901 if ((r == 0 || r == ta[0])
2902 && ta[1] == e.x
2903 && (ta[2] == e.y || (f == 1 && e.y < ta[2] && ta[2]
2904 - e.y <= sz)) && ta[3] == e.z
2905 && ta[4] == e.w) {
2906 t(w, -ta[0], ta, pl).run();
2907 rv = 1;
2908 }
2909
2910 }
2911 return rv;
2912 }
2913 break;
2914
2915 // shallow block (e.a==1)
2916 // e.t < 0: block indestructible
2917 // e.t >= 0: drops e.c*item(e.a) on destruction
2918 case WAYPOINT:
2919 case FAITHPOINT:
2920 if (tp == TP_BROKEN && dir == null) {
2921 synchronized (positionRune) {
2922 if (e.inkBlock != w.a(e.x, e.y, e.z)) { // looks like,
2923 // enchant.block
2924 // isn't
2925 // world.access XYZ
2926 rempr_removePositionRune(e); // enchant was removed
2927 } else {
2928 if (e.toolArmorType >= 0 || swords.contains(pl.Pc())) { // if
2929 // player
2930 // tool
2931 // isn't
2932 // 0,
2933 // or
2934 // player's
2935 // PC
2936 // is
2937 // a
2938 // sword
2939 rempr_removePositionRune(e); // remove enchant
2940 w.e(e.x, e.y, e.z, 0);
2941 // if (e.t >= 0) s(w, e.x,e.y,e.z, e.t, e.c); //
2942 // dunno what this does.
2943 }
2944 return 0;
2945 }
2946 }
2947 }
2948 break;
2949
2950 // destroyable rune (e.a==2)
2951 // e.t: rct to run (variables are set up like tool runes)
2952 // e.c == 1: this block is the center
2953 // e.b: sent in the task array
2954 case 2:
2955 if (tp == TP_BROKEN && dir == null) {
2956 synchronized (positionRune) {
2957 Iterable<rcm> stack = cnb_collectBlockNeighbors(e, false);
2958 for (rcm bl : stack) {
2959 int[] ta = { e.inkBlock };
2960 if (bl.length == 1)
2961 t(w, bl.toolArmorType, ta, pl).runAt(bl.x, bl.y,
2962 bl.z, 0, pl.Pc(), TP_BROKEN);
2963 positionRune.remove(bl);
2964 }
2965 }
2966 s_saveToMagicDat();
2967 }
2968 break;
2969
2970 // note: e.a == 3 means a sign rune, so it's in the function above
2971 case 3:
2972 break;
2973
2974 case BEACON:
2975 if (tp == TP_BROKEN && dir == null) {
2976 synchronized (positionRune) {
2977 Iterable<rcm> stack = cnb_collectBlockNeighbors(e, false);
2978 for (rcm bl : stack) {
2979 if (w.a(bl.x, bl.y, bl.z) == GLOWSTONE)
2980 w.e(bl.x, bl.y, bl.z, AIR);
2981 positionRune.remove(bl);
2982 }
2983 }
2984 s_saveToMagicDat(); // save
2985 }
2986 break;
2987 case BRIDGEMASTER: {
2988 // strip out non right click/ placements
2989
2990 // move the block placed.
2991 for (int i = 0; i < positionRuneList.size(); i++) {
2992 int[] ta = positionRuneList.get(i);
2993 if ((ta[1] == e.x && ta[2] == e.y && ta[3] == e.z && ta[4] == e.w)) {
2994 if (w.a(e.x, e.y, e.z) != 0) {
2995 // DBG("Triggering bridge master");
2996 t(w, -5, ta, pl).run();
2997 rv = 1;
2998 }
2999 }
3000 }
3001
3002 }
3003 case TOGGLEBLOCKS:
3004 if (tp == TP_BROKEN && e.runePattern == TOGGLEBLOCKS && dir == null
3005 && swords.contains(pl.Pc())) {
3006 // w.e(e.x, e.y, e.z, e.b & 0xFF, (e.b >> 8) & 0xF); // flip
3007 // toggleblock
3008 s(getWorldById(e.w), e.x, e.y, e.z, e.inkBlock & 0xFF, 1,
3009 (short) ((e.inkBlock >> 8) & 0xF));
3010 rempr_removePositionRune(e);
3011 break;
3012 }
3013 case PHASEBLOCKS:
3014 case LOCKBLOCKS:
3015 case SPLEEFBLOCKS:
3016
3017 int returnvalue = pblb(w, pl.Pc(), tp, e, dir, rv);
3018 // DBG("PBLB return = "+returnvalue);
3019 if (returnvalue == -2) {
3020 pl.ab(EnChat.RED
3021 + "Your sword has destroyed the phase magic that was once here");
3022 returnvalue = 0;
3023 }
3024 return (0);
3025
3026 // DAMAGE SENSOR
3027 // e.b -> tier
3028 // e.c -> signature
3029 // e.d -> signature meta
3030 // e.t -> key
3031 // e.l -> last hit
3032 case LOGHIT:
3033 if (tp == TP_BROKEN && dir == null && swords.contains(pl.Pc())) {
3034 pl.ab(EnChat.RED + "Damage sensor destroyed.");
3035 logInfo(pl.aw_getName() + " destroyed a damage sensor.");
3036 rempr_removePositionRune(e);
3037 RuneBlock dest = w.getBlock(e.x, e.y, e.z);
3038 Collection<RuneItem> drops = dest
3039 .getDrops(w.getItem(278, 1, 1));
3040 for (RuneItem dr : drops) {
3041 w.s(e.x + 0.5D, e.y + 0.5D, e.z + 0.5D, dr.getType(),
3042 dr.getAmount(), (short) dr.getData());
3043 }
3044 w.e(e.x, e.y, e.z, 0);
3045
3046 break;
3047 } else if ((tp == TP_DIGGING || tp == TP_BROKEN) && dir == null) {
3048 int time = ((int) (System.currentTimeMillis() % 10000));
3049 if (time - e.l > 500
3050 || (time < e.l && (time + 10000) - e.l > 500)) {
3051
3052 int[] logpad_tiers = { 0, 4, 12, 36, 108, 324, 972, 2916 };
3053 // DBG("Damage sensor triggered, ["+e.length+","+e.metaData+"]");
3054
3055 ls_r(w, pl, /* pl.Pc() */pl.Pc(), r, e.length, e.metaData,
3056 e.toolArmorType, e.x, e.y, e.z,
3057 (logpad_tiers[bt_blockTier[e.inkBlock]]));
3058
3059 }
3060 e.l = time; // last time triggered
3061 }
3062 if (tp == TP_BROKEN && dir == null) {
3063 return 1; // cancel breaking
3064 }
3065 break;
3066
3067 // BLOCK SENSOR
3068 case LOGBLOCK:
3069 if (tp == TP_PLACED && dir == null) {
3070 int[] logpad_tiers = { 0, 4, 12, 36, 108, 324, 972, 2916 };
3071 logInfo(pl.aw_getName() + " triggered a block sensor.");
3072 ls_r(w, pl, pl.Pc(), -1, e.length, e.metaData, e.toolArmorType,
3073 e.x, e.y, e.z, (e.inkBlock == BEDROCK ? 0
3074 : logpad_tiers[bt_blockTier[e.inkBlock]]));
3075 }
3076 break;
3077
3078 // REDSTONE SENSOR; destroyed if the iron block below is destroyed
3079 case LOGRED:
3080 if (tp == TP_BROKEN && dir != null && dir[0] == 0 && dir[1] == 1
3081 && dir[2] == 0) {
3082 pl.ab(EnChat.RED + "Redstone sensor destroyed.");
3083 logInfo(pl.aw_getName() + " destroyed a redstone sensor.");
3084 rempr_removePositionRune(e);
3085 }
3086 break;
3087
3088 case LOGSRED:
3089 if (tp == TP_BROKEN && dir != null && dir[0] == 0 && dir[1] == 1
3090 && dir[2] == 0) {
3091 pl.ab(EnChat.RED + "Sticky redstone sensor destroyed.");
3092 logInfo(pl.aw_getName()
3093 + " destroyed a sticky redstone sensor.");
3094 rempr_removePositionRune(e);
3095 }
3096 break;
3097
3098 case IDENTIFIER:
3099 if (tp == TP_BROKEN && dir == null && pl.Pc() != AIR
3100 && !swords.contains(pl.Pc())) {
3101 return 1; // glass indestructible unless you use hand or sword
3102 } else if ((tp == TP_BROKEN && dir == null)
3103 || w.a(e.x, e.y, e.z) != GLASS) {
3104
3105 pl.ab(EnChat.RED + "Identifier destroyed.");
3106 logInfo(pl.aw_getName() + " destroyed an identifier.");
3107 rempr_removePositionRune(e);
3108 } else if ((tp == TP_DIGGING || tp == TP_RIGHTCLICK) && dir == null) {
3109 boolean found = false;
3110
3111 // check tool engraved enchantments
3112 for (final EnAction i : EnAction.primaryActions) {
3113 final int[] ta = pl.gench(i);
3114 if (ta != null) {
3115 String nm = runeIdToRuneNameTable.get(ta[0]);// rct.gtrn(ta[0]);
3116 final String us = ta[0] == POWERPICK || ta[0] == POWERDRILL
3117 ? " energy" : " uses";
3118
3119 if (nm == null) {
3120 nm = "unknown";
3121 DBG("Missing runeIDtoname for identifer: " + ta[0]);
3122 }
3123
3124 if (ta[3] == RCT_main.PERMANENT_USES) {
3125 pl.ab("This tool is enchanted with " + EnChat.AQUA + nm
3126 + EnChat.WHITE + " (permanent).");
3127 } else {
3128 pl.ab("This tool is enchanted with " + EnChat.AQUA + nm
3129 + EnChat.WHITE + " (" + ta[3] + us + ").");
3130 }
3131 found = true;
3132 }
3133 }
3134
3135 // check player enchantments on tool
3136 final List<int[]> en = sl.get(pl.aw_getName());
3137 final int itm = pl.Pc();
3138 if (en != null) {
3139 for (final int[] ta : en) {
3140 // DBG("task = "+ta[0] + " tool = "+ta[2],pl);
3141 if (ta != null && ta[2] == itm && itm == 0) // hand
3142 // enchants
3143 // only
3144 {
3145 String nm = runeIdToRuneNameTable.get(ta[0]);// rct.gtrn(ta[0]);
3146 if (nm == null) {
3147 nm = "unknown";
3148 DBG("Missing runeIDtoname for identifer: "
3149 + ta[0]);
3150 }
3151 switch (ta[0]) {
3152 case BUTTERCURSE:
3153 case BABELCURSE:
3154 pl.ab("You are afflicted with " + ta[4]
3155 + " charges of " + EnChat.RED + nm
3156 + EnChat.WHITE + " (" + ta[3]
3157 + " strength)");
3158 break;
3159 case LEVITATE:
3160 pl.ab("Your skin has the " + EnChat.AQUA + nm
3161 + EnChat.WHITE + " rune on it ("
3162 + (ta[3] / 10) + " seconds)");
3163 break;
3164 case ENDURANCE:
3165 pl.ab("Your skin has the " + EnChat.AQUA + nm
3166 + EnChat.WHITE + " rune on it (" + ta[3]
3167 + " seconds)");
3168 break;
3169 default:
3170 pl.ab("Your skin has the " + EnChat.AQUA + nm
3171 + EnChat.WHITE + " rune on it (" + ta[3]
3172 + " power)");
3173 break;
3174 }
3175 found = true;
3176 } else if (ta != null && ta[2] == itm) {
3177 String nm = runeIdToRuneNameTable.get(ta[0]);// rct.gtrn(ta[0]);
3178 if (nm == null) {
3179 nm = "unknown";
3180 DBG("Missing runeIDtoname for identifer: "
3181 + ta[0]);
3182 }
3183 final String us = ta[0] == POWERPICK || ta[0] == POWERDRILL
3184 ? " energy" : " uses";
3185
3186 pl.ab("This type of tool is enchanted with "
3187 + EnChat.PURPLE + nm + EnChat.WHITE + " ("
3188 + ta[3] + us + ").");
3189 found = true;
3190 }
3191 }
3192 }
3193 if (!found) {
3194 final String what = itm == 0 ? "Your hand" : "This tool";
3195 pl.ab(EnChat.YELLOW + what + " is not enchanted.");
3196 }
3197 }
3198 break;
3199
3200 case ENGRAVER:
3201
3202 if ((tp == TP_BROKEN && dir == null)
3203 || w.a(e.x, e.y, e.z) != LAPIS_BLOCK) {
3204 pl.ab(EnChat.RED + "Engraver destroyed.");
3205 logInfo(pl.aw_getName() + " destroyed an engraver.");
3206 rempr_removePositionRune(e);
3207
3208 } else if (tp == TP_RIGHTCLICK && dir == null) {
3209 String name = pl.getHeldItemName();
3210
3211 DBG("named item used for engraver: " + name);
3212 int itm = pl.Pc();
3213 if (!swords.contains(itm) && !picks.contains(itm)
3214 && !shovels.contains(itm) && !axes.contains(itm)
3215 && !hoes.contains(itm) && !bows.contains(itm)
3216 && itm != 387 && !armor.contains(itm) && name == "") {
3217 break;
3218 }
3219 if (pl.Pcc() > 1) {
3220 pl.ab(EnChat.YELLOW
3221 + "You can only engrave an enchant onto one item!");
3222 break;
3223 }
3224 // transfer a tool enchantment on the player to the tool
3225 List<int[]> en = sl.get(pl.aw_getName());
3226 if (en == null)
3227 en = createAList();
3228
3229 boolean found = false;
3230 final Iterator<int[]> iter = en.iterator();
3231 final EnAction[] interesting = { TP_RIGHTCLICK, TP_SWING,
3232 TP_DIGGING, TP_BROKEN, TP_PLACED, TP_INV_HOLDING,
3233 TP_CATCHALL, TP_ARROWLAUNCH };
3234 while (iter.hasNext()) {
3235 int[] ta = iter.next();
3236 if (ta != null
3237 && ta[2] == itm
3238 && ta.length >= 4
3239 && ArrayUtils.contains(interesting,
3240 EnAction.fromCode(ta[1]))) {
3241 String DBG = ("Found ench " + ta[0] + "," + ta[1] + ","
3242 + ta[2] + "," + ta[3] + "] ");
3243 for (int j = 4; j < ta.length; j++) {
3244 DBG += " ta" + j + "[" + ta[j] + "]";
3245 }
3246 DBG(DBG);
3247
3248 pl.sench(ta[0], EnAction.fromCode(ta[1]), ta[2], ta[3],
3249 Arrays.copyOfRange(ta, 4, ta.length));
3250 iter.remove();
3251 s_saveToMagicDat();
3252
3253 String nm = runeIdToRuneNameTable.get(ta[0]);
3254 if (nm == null)
3255 nm = "unknown";
3256 pl.ab("You engraved " + EnChat.AQUA + nm + EnChat.WHITE
3257 + " on this tool.");
3258 found = true;
3259 return 1;
3260 }
3261 }
3262 if (!found) {
3263 pl.ab(EnChat.YELLOW + "There is no spell to engrave.");
3264 DBG("Engraver failed. used item = " + itm);
3265 }
3266
3267 }
3268 break;
3269
3270 case CAULDRON:
3271 if ((tp == TP_BROKEN && dir == null)
3272 || w.a(e.x, e.y, e.z) != CAULDRON_BLOCK) {
3273 pl.ab(EnChat.RED + "Bottomless Cauldron destroyed.");
3274 logInfo(pl.aw_getName() + " destroyed a bottomless cauldron.");
3275 rempr_removePositionRune(e);
3276 } else if (tp == TP_RIGHTCLICK && dir == null) {
3277 int itm = pl.Pc();
3278 if (itm == BOTTLE) {
3279 w.c(e.x, e.y, e.z, 3 /* cauldron filled */);
3280 // server fills bottle
3281 } else if (itm == BUCKET) {
3282 w.c(e.x, e.y, e.z, 3 /* cauldron filled */);
3283 int itmQ = pl.Pcc();
3284 if (itmQ > 1) {
3285 pl.rfhs(BUCKET, 1);
3286 pl.Pa(BUCKET, 0, 1);
3287 }
3288 // check for multiple buckets
3289 // if more than one bucket, attempt to add a filled bucket
3290 // to inventory, or drop
3291 // else:
3292 pl.Pe(WATER_BUCKET, 1, (short) 0);
3293 } else if (itm == WATER_BUCKET) {
3294 w.c(e.x, e.y, e.z, 3 /* cauldron filled */);
3295 pl.Pe(BUCKET, 1, (short) 0);
3296 } else if (itm == LAVA_BUCKET) {
3297 w.c(e.x, e.y, e.z, 0 /* cauldron empty */);
3298 pl.Pe(BUCKET, 1, (short) 0);
3299 pl.ab(EnChat.RED + "Bottomless Cauldron destroyed.");
3300 logInfo(pl.aw_getName()
3301 + " destroyed a bottomless cauldron.");
3302 rempr_removePositionRune(e);
3303 }
3304 }
3305 break;
3306
3307 /*
3308 * case CTRI: if ((tp == TP_BROKEN && dir == null) || w.a(e.x, e.y, e.z)
3309 * != 41 ) { pl.ab(Chat.RED +
3310 * "\u00A7KC'tri's rune\u00A7R"+Chat.RED+" destroyed."); logInfo(pl.aw()
3311 * + " destroyed a Ctri Rune."); rempr(e); } else if (tp ==
3312 * TP_RIGHTCLICK && dir == null) { pl.ab("I like trains.");
3313 *
3314 * }
3315 *
3316 * break; /*
3317 */
3318
3319 case BUTTERCURSE: {
3320 if (wdc(pl, WardType.Void))
3321 break;
3322 if (tp.getCode() == e.metaData) {
3323 DBG("Cursed with Buttercurse " + e.runePattern + "|"
3324 + e.inkBlock + "|" + e.length + "|" + e.metaData, pl);
3325 int ch = 0;
3326 switch (e.inkBlock) { // percentage chances of occurring
3327 case 1:
3328 ch = 5;
3329 break;
3330 case 2:
3331 ch = 10;
3332 break;
3333 case 3:
3334 ch = 15;
3335 break;
3336 case 4:
3337 ch = 25;
3338 break;
3339 case 5:
3340 ch = 40;
3341 break;
3342 case 6:
3343 ch = 65;
3344 break;
3345 case 7:
3346 ch = 90;
3347 break;
3348 default:
3349 ch = 5;
3350 }
3351
3352 if (!r_searchForToolTypeEnchants(pl, TP_SWING, 0, e.runePattern)) {
3353 r_removeEnchantmentFromToolType(TP_SWING, 0, pl,
3354 e.runePattern);
3355 int uses = runeUsesTable.get(
3356 runeIdToRuneNameTable.get(e.runePattern)).get(
3357 e.inkBlock);
3358 f_addMagicToPlayer(pl, EnChat.YELLOW
3359 + "Your hands no longer grip your items securely",
3360 e.runePattern, 1, 0, ch, uses); // install new
3361 // buttercurse
3362 e.length--; // remove a use
3363 rv = 1;
3364 } else {
3365
3366 pl.ab(EnChat.YELLOW
3367 + "You have triggered a butterfingers curse, but you are already cursed with it.");
3368
3369 }
3370 if (e.length <= 0) {
3371 remcr(e);
3372 }
3373 }
3374 break;
3375 }
3376 case BABELCURSE: {
3377 if (tp.getCode() == e.metaData) {
3378 if (wdc(pl, WardType.Void))
3379 break;
3380
3381 int ch = 0;
3382 switch (e.inkBlock) // this is the pre-calculated tier, at time
3383 // of binding it to the hex
3384 { // percentage chances of occurring
3385 default:
3386 ch = 5;
3387 break;
3388 case 1:
3389 ch = 5;
3390 break;
3391 case 2:
3392 ch = 10;
3393 break;
3394 case 3:
3395 ch = 15;
3396 break;
3397 case 4:
3398 ch = 25;
3399 break;
3400 case 5:
3401 ch = 40;
3402 break;
3403 case 6:
3404 ch = 65;
3405 break;
3406 case 7:
3407 ch = 90;
3408 break;
3409
3410 }
3411 if (r_searchForToolTypeEnchants(pl, TP_SPEAK, 0, e.runePattern)) {
3412 pl.ab(EnChat.YELLOW
3413 + "You have triggered a babel curse, but you are already cursed with it.");
3414 rv = 0;
3415 break;
3416 }
3417
3418 r_removeEnchantmentFromToolType(TP_SPEAK, 0, pl, e.runePattern);
3419 int uses = 0;
3420 uses = runeUsesTable.get(
3421 runeIdToRuneNameTable.get(e.runePattern)).get(
3422 e.inkBlock);
3423
3424 f_addMagicToPlayer(pl, EnChat.YELLOW
3425 + "You feel your grip on the language lessen.",
3426 e.runePattern, -3, 0, ch, uses);
3427 rv = 1;
3428 e.length--; // remove a use
3429 if (e.length <= 0) {
3430 remcr(e);
3431 }
3432 }
3433 break;
3434 }
3435 case MOUSETRAP:
3436 case MOUSETRAP + 1: {
3437 if (tp.getCode() == e.metaData) {
3438
3439 if (wdc(pl, WardType.Void))
3440 break;
3441
3442 DBG("Burn. " + e.runePattern + "|" + e.inkBlock + "|"
3443 + e.length + "|" + e.metaData, pl);
3444
3445 if (!r_searchForToolTypeEnchants(pl, TP_SWING, 0, e.runePattern)) {
3446 pl.Z(e.inkBlock * 8 * 10);
3447 e.length--; // remove a use
3448 pl.ab(EnChat.RED + "You have activated a Mouse Trap curse!");
3449 rv = 1;
3450 }
3451 if (e.length <= 0) {
3452 remcr(e);
3453 }
3454 }
3455 break;
3456 }
3457 case SMITETRAP:
3458
3459 {
3460 if (wdc(pl, WardType.Void))
3461 break;
3462
3463 // DBG("Smitetrap"+tp+"|"+e.metaData);
3464 if (tp.getCode() == e.metaData) {
3465 // DBG("Burn. "+ e.runePattern+ "|"+e.inkBlock +
3466 // "|"+e.length+"|"+e.metaData,pl);
3467
3468 if (!r_searchForToolTypeEnchants(pl, TP_SWING, 0, e.runePattern)) {
3469
3470 int uses = runeUsesTable.get(
3471 runeIdToRuneNameTable.get(e.runePattern)).get(
3472 e.inkBlock);
3473 RCT_main t = t(w, SMITETRAP, pl, (int) pl.x(), (int) pl.y(),
3474 (int) pl.z(), uses,// *10 for regular seconds
3475 0); // no idea what this last one does
3476 t.setXyz((int) pl.x(), (int) pl.y(), (int) pl.z());
3477 if (uses > 40)
3478 w.setWeather(2);
3479
3480 t.scheduleSyncRepeating(10, 20);
3481 e.length--; // remove a use
3482 pl.ab(EnChat.RED
3483 + "You have activated a Lightning Trap curse!");
3484 rv = 1;
3485 }
3486 if (e.length <= 0) {
3487 remcr(e);
3488 }
3489 }
3490 break;
3491 }
3492 case WHISPERCURSE: {
3493 if (wdc(pl, WardType.Void))
3494 break;
3495 if (e.toolArmorType == -1) {
3496 remcr(e);
3497 DBG("whisper curse dehexed");
3498 }// possessed! (save failed)
3499 DBG("Whisper " + tp + "|" + e.metaData + "|" + e.toolArmorType
3500 + "|" + e.length);
3501 if (tp.getCode() == e.metaData) {
3502 logInfo(pl.aw_getName() + " triggered an alarm at " + e.x + ","
3503 + e.y + "," + e.z + " in world "
3504 + getWorldById(e.w).getName());
3505
3506 // textID, iterator,tidyup(0/1)
3507 int ta[] = whisperSourceList.get(e.toolArmorType);
3508 RCT_main t = t(w, WHISPERCURSE, ta, pl);
3509 t.scheduleSyncRepeating(10, 20);
3510 e.length--;
3511 if (e.length <= 0) {
3512
3513 DBG("Removing ");
3514 remcr(e);
3515
3516 }
3517 }
3518 break;
3519 }
3520 case WARDLIGHT:
3521 case WARDDARK: // note, at time of coding (2.13.1 a) WARDLIGHT is used
3522 // for both.
3523 {
3524 if (dir == null)
3525 if (tp == TP_RIGHTCLICK) {
3526 DBG(EnChat.YELLOW + "Ward toggle");
3527 synchronized (positionRune) {
3528 Iterable<rcm> stack = cnb_collectBlockNeighbors(e,
3529 false);
3530 for (rcm we : stack) {
3531 /*
3532 * int[] ta = {e.b}; if (we.c == 1)
3533 * t(w,we.t,ta,pl).runAt(we.x, we.y, we.z, 0,
3534 * pl.Pc(), 3);
3535 */
3536
3537 if (we.length == 1) // ward is active
3538 {
3539 we.length = 0;
3540 if (w.a(we.x, we.y, we.z) == 102)
3541 w.e(we.x, we.y, we.z, 0);
3542 synchronized (wardRuneList) {
3543 for (int[] ia : wardRuneList) {
3544 if (ia[0] == we.x && ia[1] == we.y
3545 && ia[2] == we.z
3546 && ia[3] == we.w) {
3547 ia[5] = 0;
3548
3549 if (ia[6] == 1) {
3550 pl.ab(EnChat.GREEN
3551 + "The ward rests, and the aether can now hear those who are nearby.");
3552 } else if (ia[6] == 2) {
3553 pl.ab(EnChat.PURPLE
3554 + "The ward rests, and the void can now hear those who are nearby.");
3555 } else if (ia[6] == 3) {
3556 pl.ab(EnChat.YELLOW
3557 + "The ward rests, and enchanted tools nearby will work once more.");
3558 } else if (ia[6] == 4) {
3559 pl.ab(EnChat.GREEN
3560 + "The ward rests, and teleporting to and from nearby is possible again.");
3561 } else if (ia[6] == 5) {
3562 pl.ab(EnChat.GREEN
3563 + "The ward rests, dangerous runes will work again.");
3564 } else if (ia[6] == 6) {
3565 pl.ab(EnChat.GREEN
3566 + "The ward rests, and your True Name is visible through the aether once more.");
3567 } else if (ia[6] == 7) {
3568 pl.ab(EnChat.GREEN
3569 + "The ward rests, those who would escape gravity are free to do so.");
3570 } else {
3571 pl.ab(EnChat.GREEN
3572 + "The ward rests");
3573 DBG("Missing ward rest text for ward type "
3574 + ia[6]);
3575 }
3576 }
3577 }
3578 }
3579
3580 } else if (we.length == 0) {
3581 we.length = 1;
3582 if (w.a(we.x, we.y, we.z) == 0)
3583 w.e(we.x, we.y, we.z, 102);
3584 synchronized (wardRuneList) {
3585 for (int[] ia : wardRuneList) {
3586 if (ia[0] == we.x && ia[1] == we.y
3587 && ia[2] == we.z
3588 && ia[3] == we.w) {
3589 ia[5] = 1;
3590
3591 if (ia[6] == 1) {
3592 pl.ab(EnChat.GREEN
3593 + "The ward awakens, and the aether can no longer hear those who are nearby.");
3594 } else if (ia[6] == 2) {
3595 pl.ab(EnChat.PURPLE
3596 + "The ward awakens, and the void can no longer hear those who are nearby.");
3597 } else if (ia[6] == 3) {
3598 pl.ab(EnChat.YELLOW
3599 + "The ward awakens, and enchanted tools nearby become dormant.");
3600 } else if (ia[6] == 4) {
3601 pl.ab(EnChat.GREEN
3602 + "The ward awakens, and closes the aether to teleporting to and from nearby.");
3603 } else if (ia[6] == 5) {
3604 pl.ab(EnChat.GREEN
3605 + "The ward awakens, and dangerous runes nearby are now suppressed.");
3606 } else if (ia[6] == 6) {
3607 pl.ab(EnChat.GREEN
3608 + "The ward awakens, and your True Name is shielded from view whilst your are nearby.");
3609 } else if (ia[6] == 7) {
3610 pl.ab(EnChat.GREEN
3611 + "The ward awakens, grounding those who would escape gravity.");
3612 } else {
3613 pl.ab(EnChat.GREEN
3614 + "The ward awakens");
3615 DBG("Missing ward awaken text for ward type "
3616 + ia[6]);
3617 }
3618 }
3619 }
3620 }
3621 }
3622
3623 }
3624 }
3625 } else if (tp == TP_BROKEN) {
3626
3627 DBG(EnChat.RED + "Ward broken");
3628 synchronized (positionRune) {
3629 Iterable<rcm> stack = cnb_collectBlockNeighbors(e,
3630 false);
3631 for (rcm we : stack) {
3632 if (w.a(we.x, we.y, we.z) == 102)
3633 w.e(we.x, we.y, we.z, 0);
3634
3635 synchronized (wardRuneList) {
3636
3637 for (int i = 0; i < wardRuneList.size(); i++) {
3638 int[] ia = wardRuneList.get(i);
3639 if (ia[0] == we.x && ia[1] == we.y
3640 && ia[2] == we.z && ia[3] == we.w) {
3641
3642 wardRuneList.remove(ia);
3643 if (ia[6] == 1) {
3644 pl.ab(EnChat.RED
3645 + "Aether ward destroyed.");
3646 } else if (ia[6] == 2) {
3647 pl.ab(EnChat.PINK
3648 + "Void ward destroyed.");
3649 } else if (ia[6] == 3) {
3650 pl.ab(EnChat.RED
3651 + "Tool ward destroyed.");
3652 } else if (ia[6] == 4) {
3653 pl.ab(EnChat.RED
3654 + "Teleport ward destroyed.");
3655 } else if (ia[6] == 5) {
3656 pl.ab(EnChat.RED
3657 + "Protection ward destroyed");
3658 } else if (ia[6] == 6) {
3659 pl.ab(EnChat.RED
3660 + "True Name ward destroyed");
3661 }
3662 logInfo(pl.aw_getName()
3663 + " destroyed a ward.");
3664 }
3665 }
3666
3667 positionRune.remove(we);
3668 }
3669 }
3670 }
3671 }
3672 break;
3673 }
3674 case TRUENAME: {
3675 if (tp == TP_BROKEN && dir == null && swords.contains(pl.Pc())) {
3676 rempr_removePositionRune(e);
3677 pl.ab(EnChat.RED + "True Namer destroyed");
3678 }
3679 // if the player breaks a block here with a sword, self destruct
3680 if (tp == TP_RIGHTCLICK && dir == null) {
3681 if (gt_getTierByMetaValue(w.a(e.x, e.y, e.z),
3682 w.b(e.x, e.y, e.z)) > 0) // if there IS a tierblock
3683 // existing in this spot.
3684 {
3685 if (getUses(TRUENAME, w.a(e.x, e.y, e.z),
3686 w.b(e.x, e.y, e.z)) == 0)
3687 pl.ab(EnChat.RED
3688 + "Your offering is insignificant next to the power of a True Name.");
3689 else {
3690 e.length += getUses(TRUENAME, w.a(e.x, e.y, e.z),
3691 w.b(e.x, e.y, e.z)); // add uses to the skull
3692 c(w, e.x, e.y, e.z, 1); // remove the tier block
3693 pl.ab(EnChat.YELLOW
3694 + "You have fed more uses to the True Namer. It now has "
3695 + e.length + " uses.");
3696 }
3697 } else {
3698 if (e.length > 0) {
3699 pl.dropSkull(e.x, e.y, e.z);
3700 e.length--;
3701 }
3702 }
3703
3704 }
3705 break;
3706 }
3707 case -REALITYANCHOR: {
3708 if (tp == TP_BROKEN && dir == null
3709 && (picks.contains(pl.Pc()) || swords.contains(pl.Pc()))) {
3710 // remove all anchors associated with this one.
3711 rempr_removePositionRune(e);
3712 pl.ab(EnChat.RED + "Reality Anchor destroyed");
3713
3714 // int cB = w.a(e.x, e.y, e.z);
3715 // w.s((double)e.x, (double)e.y, (double)e.z, cB, 1, (short)0);
3716 } else if (tp == TP_BROKEN && dir == null) {
3717 return 1; // cancel breaking
3718 } else if (w.a(e.x, e.y, e.z) != 133) {
3719 rempr_removePositionRune(e);
3720 pl.ab(EnChat.RED + "The Aether has detected your deception.");
3721 } else if (tp == TP_RIGHTCLICK) {// || tp == TP_DIGGING){
3722 // DBG(Chat.RED+"Oh look, an anchor");
3723
3724 /*
3725 * Stores x,y,z,w normally Tier value stored in inkBlock
3726 * Distance from center stored in length Direction stored in
3727 * tool type
3728 */
3729
3730 int[] offset = RCT_main.dir(face);
3731 if (dir != null) {
3732 offset = dir;
3733 }
3734 int[] comp = RCT_main.dir(e.toolArmorType);
3735
3736 if (Math.abs(offset[0]) == Math.abs(comp[0])
3737 && Math.abs(offset[1]) == Math.abs(comp[1])
3738 && Math.abs(offset[2]) == Math.abs(comp[2])) { // if
3739 // clicked
3740 // on
3741 // same
3742 // axis
3743 // as
3744 // anchor
3745 // check bounds
3746
3747 int delta = offset[0] * comp[0] + offset[1] * comp[1]
3748 + offset[2] * comp[2];
3749 // has a value of 1 or -1.
3750
3751 int rd = getUses(REALITYANCHOR, e.inkBlock, e.metaData);
3752 if (e.toolArmorType == 0) {
3753 rd *= 2;
3754 rd -= 1;
3755 }
3756
3757 if (getpr(e.x + offset[0], e.y + offset[1],
3758 e.z + offset[2], e.w) != null) {
3759 pl.ab(EnChat.YELLOW
3760 + "Some form of magic block is preventing the anchor from advancing!");
3761 }
3762 if (e.length + delta > rd) {
3763 pl.ab(EnChat.YELLOW
3764 + "At the limit of this anchor's reach!");
3765 return 0;
3766 }
3767 if (e.length + delta <= 0) {
3768 pl.ab(EnChat.YELLOW
3769 + "This anchor cannot move further inward!");
3770 return 0;
3771 }
3772 if (e.y + offset[1] > w.getMaxY()) {
3773 pl.ab(EnChat.YELLOW
3774 + "This anchor cannot be removed from the mortal plane!");
3775 return 0;
3776 }
3777
3778 // Check block
3779 int b = w.a(e.x + offset[0], e.y + offset[1], e.z
3780 + offset[2]);
3781 int cB = w.a(e.x, e.y, e.z);
3782
3783 if (b == AIR || liquids.contains(b)) {
3784 // set old block to air. set new block to emerald. move
3785 // magic
3786 w.e(e.x + offset[0], e.y + offset[1], e.z + offset[2],
3787 cB);
3788 w.e(e.x, e.y, e.z, 0);
3789
3790 rempr_removePositionRune(e);
3791
3792 e.setXyz(e.x + offset[0], e.y + offset[1], e.z
3793 + offset[2]);
3794 e.length += delta;
3795
3796 if (!addpr_addPositionRune(e)) {
3797 // UNREACHABLE COE
3798 // RCM in the way of this rcm. force place, cancel,
3799 // or try again?
3800 // I'm going to go with 'force' for now.
3801 rcm destr = getpr(e.x, e.y, e.z, e.w);
3802 DBG(EnChat.RED
3803 + "blocking RCM : "
3804 + runeIdToRuneNameTable
3805 .get(destr.runePattern)
3806 + " : destroying");
3807 // need to add something to properly destroy stuff
3808 // later
3809 rempr_removePositionRune(e);
3810 addpr_addPositionRune(e);
3811 }
3812 return 1;
3813 } else {
3814 pl.ab("This anchor cannot move through materials!");
3815 }
3816
3817 }
3818 }
3819
3820 // Um... not sure this should be handled here. XD
3821 // Should probably be handled in the PR_handler.
3822 // Handler for the emerald bounding units used by the reality anchor
3823
3824 // Check direction of click, check that it is the correct direction
3825 // to move them.
3826
3827 // Check if blocked :: (if there is a block where this is trying to
3828 // go, do not relocate)
3829
3830 // Move, update location int.
3831
3832 break;
3833 }
3834 case REALITYANCHOR: {
3835 if (tp == TP_BROKEN && dir == null && swords.contains(pl.Pc())) {
3836 // Remove all anchors associated with this rune
3837 rempr_removePositionRune(e);
3838 pl.ab(EnChat.RED + "Reality Anchor destroyed");
3839 for (int i = 0; i < realityAnchorList.size(); i++) {
3840 int[] ta = realityAnchorList.get(i);
3841 if (ta[2] == e.x && ta[3] == e.y && ta[4] == e.z
3842 && ta[5] == e.w) {
3843 realityAnchorList.remove(i);
3844 i--;
3845 }
3846 }
3847 return 0;
3848 } else if (tp == TP_RIGHTCLICK && dir == null) { // right click and
3849 // direct hit
3850 DBG(EnChat.RED + "anchor center");
3851
3852 // So, two steps. Check the sig (nothing to do here right now,
3853 // I'm not storing the sig in the anchor yet
3854
3855 boolean found = false;
3856
3857 for (int i = 0; i < realityAnchorList.size(); i++) {
3858 int[] ta = realityAnchorList.get(i);
3859 if (ta[2] == e.x && ta[3] == e.y && ta[4] == e.z
3860 && ta[5] == e.w) {
3861 found = true;
3862
3863 int g = gg(getWorldById(e.w), e.x, e.y, e.z,
3864 e.runePattern, false);
3865 int gd = gg(getWorldById(e.w), e.x, e.y, e.z,
3866 e.runePattern, true);
3867
3868 ta[6] = e.inkBlock;
3869 if (g == ta[0] && gd == ta[1]) {
3870 // pl.ab(Chat.RED +
3871 // "This anchor is already established.");
3872 // //redundant message unless changing the signature
3873 } else {
3874 // DBG("Faithpoint altered at ["+r.x+","+r.y+","+r.z+","+r.w+"]",pl);
3875 // get the FWPL with the established signature
3876
3877 ta[0] = g;
3878 ta[1] = gd;
3879 s_saveToMagicDat();
3880
3881 pl.ab(EnChat.GREEN
3882 + "You have changed the signature of this anchor");
3883 }
3884 }
3885 }
3886
3887 if (!found) {
3888 DBG(EnChat.RED + "Desync: no anchor found for RCM. Deleting");
3889 rempr_removePositionRune(e);
3890 return 0;
3891 }
3892
3893 // And then check the area. Done by searching up to max distance
3894 // (determined by tier) for -REALITYANCHORS
3895
3896 int y = e.y + 2; // center of pattern area
3897
3898 // List<rcm> bounds = createLList();
3899
3900 rcm lowerBound = new rcm(e.x, y, e.z, e.w);
3901 rcm upperBound = new rcm(e.x, y, e.z, e.w);
3902
3903 for (int d = 0; d < 6; d++) {
3904
3905 int rd = getUses(REALITYANCHOR, e.inkBlock, e.metaData);
3906
3907 if (d == 0) {
3908 rd *= 2;
3909 rd -= 1;
3910 }
3911
3912 if (d == 1) {
3913 continue;
3914 // ignore downward
3915 }
3916 int[] pdir = RCT_main.dir(d);
3917 found = false;
3918 for (int i = 1; i <= rd; i++) {
3919 rcm bound = getpr(e.x + i * pdir[0], y + i * pdir[1],
3920 e.z + i * pdir[2], e.w);
3921 if (bound != null
3922 && bound.runePattern == -REALITYANCHOR) {
3923 // bounds.add(bound);
3924 if (w.a(e.x + i * pdir[0], y + i * pdir[1], e.z + i
3925 * pdir[2]) != 133) {
3926 rempr_removePositionRune(bound);
3927 pl.ab(EnChat.RED
3928 + "The Aether has detected your deception.");
3929 break;
3930 }
3931
3932 if (pdir[0] + pdir[1] + pdir[2] < 0) {
3933 lowerBound.setXyz(lowerBound.x + i * pdir[0],
3934 lowerBound.y + i * pdir[1],
3935 lowerBound.z + i * pdir[2]);
3936 } else {
3937 upperBound.setXyz(upperBound.x + i * pdir[0],
3938 upperBound.y + i * pdir[1],
3939 upperBound.z + i * pdir[2]);
3940 }
3941 found = true;
3942 break;
3943 }
3944 }
3945 if (!found) {
3946 // attempt to recreate the anchor
3947 for (int i = 1; i <= rd; i++) {
3948 int b = getWorldById(e.w).a(e.x + i * pdir[0],
3949 y + i * pdir[1], e.z + i * pdir[2]);
3950 if (b == 133) {
3951 // Found emerald
3952
3953 rcm nAnch = new rcm(-REALITYANCHOR, e.inkBlock,
3954 e.x + i * pdir[0], y + i * pdir[1], e.z
3955 + i * pdir[2], e.w, i, d);
3956 if (!addpr_addPositionRune(nAnch)) {
3957 continue;
3958 }
3959 pl.ab(EnChat.GREEN + "A new " + dirs(d, true)
3960 + " anchor has been created.");
3961 // bounds.add(bound);
3962 if (pdir[0] + pdir[1] + pdir[2] < 0) {
3963 lowerBound.setXyz(lowerBound.x + i
3964 * pdir[0], lowerBound.y + i
3965 * pdir[1], lowerBound.z + i
3966 * pdir[2]);
3967 } else {
3968 upperBound.setXyz(upperBound.x + i
3969 * pdir[0], upperBound.y + i
3970 * pdir[1], upperBound.z + i
3971 * pdir[2]);
3972 }
3973 found = true;
3974 break;
3975 }
3976 }
3977
3978 if (!found) {
3979 pl.ab(EnChat.YELLOW + "The aether cannot find the "
3980 + dirs(d, true) + " anchor!");
3981 return 0;
3982 }
3983 // Destroy anchor and all attached bounds? Or wait to
3984 // see if an anchor will be moved back?
3985 // possibly add another rune to create new anchors?
3986
3987 }
3988 }
3989
3990 // Adjust bounds off of the emerald blocks
3991 lowerBound.setXyz(lowerBound.x + 1, lowerBound.y,
3992 lowerBound.z + 1);
3993 upperBound.setXyz(upperBound.x - 1, upperBound.y - 1,
3994 upperBound.z - 1);
3995
3996 int volume = (upperBound.x - lowerBound.x + 1)
3997 * (upperBound.y - lowerBound.y + 1)
3998 * (upperBound.z - lowerBound.z + 1);
3999
4000 DBG(EnChat.RED + "volume = " + volume);
4001 DBG(EnChat.GREEN + "upperBound = :x:" + EnChat.RED + upperBound.x
4002 + EnChat.GREEN + " :y:" + EnChat.RED + upperBound.y
4003 + EnChat.GREEN + " :z:" + EnChat.RED + upperBound.z);
4004
4005 DBG(EnChat.GREEN + "lowerBound = :x:" + EnChat.RED + lowerBound.x
4006 + EnChat.GREEN + " :y:" + EnChat.RED + lowerBound.y
4007 + EnChat.GREEN + " :z:" + EnChat.RED + lowerBound.z);
4008
4009 if (volume > getUses(REALITYMASTER, e.inkBlock, e.metaData)) {
4010 pl.ab(EnChat.YELLOW
4011 + "This anchor is not powerful enough to hold this much space!");
4012 return 0;
4013 } else {
4014 pl.ab(EnChat.GREEN + "The aether tenses, anchoring the area.");
4015 // Need to think of another message for these...
4016 }
4017
4018 return 0; // by removing the interrupt, we can overlap Anchors
4019 // and Masters.
4020 // the anchor will try and change sig, but provided
4021 // the target anchor is already established, wont be
4022 // able to.
4023
4024 }
4025
4026 // Check for changed sig, check area via anchors
4027 break;
4028 }
4029 case MEMENTO: {
4030 if (tp == TP_RIGHTCLICK && pl.Pc() != 331) {
4031 int fb = w.a(e.x, e.y, e.z);
4032 int fd = w.b(e.x, e.y, e.z);
4033 if (gt_getTierByMetaValue(fb, fd) != 0) {
4034 int newtier = gt_getTierByMetaValue(fb, fd);
4035 w.e(e.x, e.y, e.z, 0);
4036 e.length += runeUsesTable.get(
4037 runeIdToRuneNameTable.get(e.runePattern)).get(
4038 newtier);
4039 pl.ab(EnChat.YELLOW + "You have fed a block to the memento.");
4040 } else {
4041 if (e.metaData == 1) {
4042 e.metaData = 0;
4043 pl.ab(EnChat.YELLOW
4044 + "The aether forgets about this memento");
4045 } else {
4046 if (w.a(e.x, e.y - 1, e.z) != 57) {
4047 pl.ab(EnChat.RED
4048 + "The memento's diamond anchor is missing!");
4049 return 0;
4050 }
4051
4052 int rd = gt_getTier(e.inkBlock);
4053 if (e.length < rd * rd) {
4054 pl.ab(EnChat.RED
4055 + "This memento doesn't have enough power! Feed it blocks.");
4056 return 0;
4057 }
4058 e.metaData = 1;
4059 int ia[] = { e.x, e.y, e.z, 6, e.inkBlock };
4060 RCT_main t = t(w, MEMENTO, ia, pl);
4061 t.scheduleSyncRepeating(10, 20);
4062 pl.ab(EnChat.YELLOW
4063 + "The memento concentrates the aether's memory on this location");
4064 }
4065 }
4066
4067 return 1;
4068
4069 }
4070
4071 }
4072
4073 }
4074
4075 return rv; // default: return unchanged rv
4076 }
4077
4078 /**
4079 * collect neighbors attached to the block
4080 *
4081 * @param e
4082 * - initial rune
4083 * @param cmatch
4084 * - true if the signature has to be identical
4085 * @return All connected runes (with same signature) special: if <e> is a
4086 * phase/lock/toggle block, all connected phase/lock/spleef blocks
4087 * are found special: if <e> is a spleef block, no connected blocks
4088 * will be found
4089 */
4090 Iterable<rcm> cnb_collectBlockNeighbors(rcm e, boolean cmatch) {
4091 boolean phaseBlocks = (e.runePattern == PHASEBLOCKS
4092 || e.runePattern == LOCKBLOCKS || e.runePattern == TOGGLEBLOCKS);
4093
4094 List<rcm> list = createAList();
4095 list.add(e);
4096
4097 if (e.runePattern == SPLEEFBLOCKS) {
4098 return list; // toggle single spleef block only
4099 }
4100
4101 Set<rcm> all = new HashSet<rcm>(list);
4102
4103 synchronized (positionRune) {
4104
4105 int i = 0;
4106 while (i < list.size() && i < 1024 * 4) { // too big toggle areas
4107 // could be a problem
4108 e = list.get(i++);
4109
4110 for (int[] dir : RCT_main.around) {
4111 rcm n = getpr(e.x + dir[0], e.y + dir[1], e.z + dir[2], e.w);
4112 if (n != null
4113 && !all.contains(n)
4114 && (phaseBlocks ? (n.runePattern == PHASEBLOCKS
4115 || n.runePattern == LOCKBLOCKS
4116 || n.runePattern == SPLEEFBLOCKS || n.runePattern == TOGGLEBLOCKS)
4117 : n.runePattern == e.runePattern))
4118 if (!cmatch || e.length == n.length) {
4119 list.add(n);
4120 all.add(n);
4121 }
4122
4123 }
4124 }
4125 }
4126 return list;
4127 }
4128
4129 // lock blocks redstone event
4130 Map<rcm, long[]> lbGuard = createMap();
4131
4132 void lbrs(RuneWorld w, int[] ia) {
4133 synchronized (positionRune) {
4134 rcm e = getpr(ia[0], ia[1], ia[2], getWorldId(w));
4135 if (e != null && e.runePattern == Runecraft_MAIN.LOCKBLOCKS) {
4136 int oldt = e.toolArmorType;
4137 pblb(w, -1, TP_RIGHTCLICK, e, null, ia[4]);
4138 if (oldt == e.toolArmorType)
4139 return; // no burnout if nothing changes
4140 if (e.toolArmorType != 0)
4141 return; // no burnout on falling edges
4142 } else
4143 return;
4144
4145 // burn out? - "leaky bucket" pattern
4146 long[] leaky = lbGuard.get(e);
4147 if (leaky == null) {
4148 leaky = new long[2]; // [0] filling, [1] time of last change
4149 lbGuard.put(e, leaky);
4150 }
4151
4152 leaky[0] += 18;
4153 if (leaky[1] - w.e() < 0)
4154 leaky[0] += leaky[1] - w.e();
4155 leaky[1] = w.e();
4156 if (leaky[0] < 0)
4157 leaky[0] = 0;
4158 if (leaky[0] >= 50) { // burnout!
4159 leaky[0] = 50;
4160 for (int[] dir : RCT_main.around) {
4161 int b = w.a(e.x + dir[0], e.y + dir[1], e.z + dir[2]);
4162 if (b == RS_TORCH || b == RS_TORCH_OFF || b == RS_WIRE) {
4163 w.e(e.x + dir[0], e.y + dir[1], e.z + dir[2], FIRE, 0);
4164 t(w, 4 /* replace block */, null, e.x + dir[0],
4165 e.y + dir[1], e.z + dir[2], FIRE, AIR)
4166 .scheduleSync(10 + rand.nextInt(10));
4167 }
4168 }
4169 }
4170 }
4171 }
4172
4173 // phase blocks and lock blocks
4174 int pblb(RuneWorld w, int hand, EnAction tp, rcm e, int[] dir, int rv) {
4175
4176 // Phase Blocks (e.a==PHASEBLOCKS) and
4177 // Lock Blocks (e.a==LOCKBLOCKS)
4178 // Spleef Blocks (e.a==SPLEEFBLOCKS)
4179 // e.b: (block | meta << 8 | lockkey << 16 || keymeta << 24)
4180 // e.c: signature
4181 // e.t: 0 = shown, 1 = hidden
4182 if (tp == TP_BROKEN && swords.contains(hand) && dir == null) {
4183 rempr_removePositionRune(e);
4184 rv = -2;
4185 return rv;
4186 }
4187
4188 if (e.runePattern == PHASEBLOCKS || e.runePattern == SPLEEFBLOCKS
4189 || e.runePattern == TOGGLEBLOCKS) {
4190 if (dir != null && e.runePattern == SPLEEFBLOCKS)
4191 return rv; // direct hit on spleef blocks only
4192
4193 if (tp != TP_RIGHTCLICK && tp != TP_DIGGING)
4194 return rv; // only left/right click
4195 if (rv == 0) {
4196 if (e.toolArmorType == 0)
4197 rv = -1; // hide blocks; e.t => 1
4198 else
4199 rv = 1; // show blocks; e.t => 0
4200 }
4201
4202 // if (tp == 0 /* right click */)
4203 if (tp == TP_DIGGING /* left click */) {
4204 if (rv == 1)
4205 return rv; // show only on right-click
4206 if (swords.contains(hand))
4207 return rv; // destroyable by sword
4208 }
4209 }
4210
4211 if (e.runePattern == LOCKBLOCKS) {
4212 if (dir != null || (tp != TP_RIGHTCLICK && tp != TP_DIGGING))
4213 return rv;
4214 if (rv == 0) {
4215 if (e.toolArmorType == 0)
4216 rv = -1; // hide blocks; e.t => 1
4217 else
4218 rv = 1; // show blocks; e.t => 0
4219 } else {
4220 // switch only into the non-active state to avoid additional
4221 // work
4222 if ((e.toolArmorType == 0 && rv != -1)
4223 || (e.toolArmorType == 1 && rv != 1))
4224 return rv;
4225 }
4226 }
4227
4228 Iterable<rcm> pile = cnb_collectBlockNeighbors(e, true);
4229
4230 // 'pile' contains all connected blocks; check the lock blocks first
4231 for (rcm bl : pile) {
4232 if (bl.runePattern != LOCKBLOCKS)
4233 continue;
4234 // DBG("Lock block in circuit detected."+Chat.YELLOW+bl.x+","+bl.y+","+bl.z);
4235 int b = w.a(bl.x, bl.y, bl.z);
4236 if (RCT_main.norm_bl(b) != RCT_main.norm_bl(bl.inkBlock & 0xFF)) {
4237 if (w.eAa(bl.x, bl.z)) // if chunk is loaded
4238 positionRune.remove(bl); // destroyed
4239 continue;
4240 }
4241
4242 int vb0 = (bl.inkBlock >> 16) & 0xFF;
4243 int vb1 = (bl.inkBlock >> 24) & 0xF;
4244
4245 boolean ulock = vb0 == 0;
4246 if (!ulock)
4247 for (int[] dr : RCT_main.around) {
4248 int k0 = c_aliasTierZeroToAir(w, bl.x + dr[0],
4249 bl.y + dr[1], bl.z + dr[2]);
4250 short k1 = w.matb_returnOnlyValuableMetaData(
4251 k0,
4252 (short) w.b(bl.x + dr[0], bl.y + dr[1], bl.z
4253 + dr[2]));
4254 if (vb0 == k0 && vb1 == k1) {
4255 ulock = true;
4256 break;
4257 }
4258 }
4259 if (e.runePattern == PHASEBLOCKS || e.runePattern == TOGGLEBLOCKS
4260 || !ulock) // Phase Blocks & toggle blocks aren't clickable
4261 // if you have a Lock Block
4262 return rv;
4263 }
4264
4265 // set the state of the lock block first to avoid recursive calls
4266 if (e.runePattern == LOCKBLOCKS)
4267 e.toolArmorType = (rv == 1) ? 0 : 1;
4268
4269 // toggle the blocks in 'pile'.
4270 if (rv == 1) {
4271 for (rcm bl : pile)
4272 // place the blocks; cut through liquids/snow
4273 if (bl.toolArmorType != 0
4274 && (bl.runePattern == PHASEBLOCKS || bl.runePattern == SPLEEFBLOCKS)) {
4275 if (!w.eAa(bl.x, bl.z))
4276 continue;
4277 int b = w.a(bl.x, bl.y, bl.z);
4278 if (liquids.contains(b) && w.b(bl.x, bl.y, bl.z) != 0)
4279 b = 0;
4280 if (b == SNOW)
4281 b = 0;
4282 if (b == 0) {
4283 bl.toolArmorType = 0;
4284 w.e(bl.x, bl.y, bl.z, bl.inkBlock & 0xFF,
4285 (bl.inkBlock >> 8) & 0xF);
4286 }
4287 } else if (bl.toolArmorType != 0
4288 && (bl.runePattern == TOGGLEBLOCKS)) {
4289 if (!w.eAa(bl.x, bl.z))
4290 continue;
4291 int ob = w.a(bl.x, bl.y, bl.z);
4292 ob |= (w.b(bl.x, bl.y, bl.z) << 8); // new block information
4293 w.e(bl.x, bl.y, bl.z, bl.inkBlock & 0xFF,
4294 (bl.inkBlock >> 8) & 0xF); // flip toggleblock
4295 bl.inkBlock = ob; // store old toggleblock
4296 bl.toolArmorType = 0;
4297 } else if (bl.toolArmorType != 0)
4298 bl.toolArmorType = 0;
4299 } else {
4300 for (rcm bl : pile)
4301 // remove the blocks
4302 if (bl.toolArmorType == 0
4303 && (bl.runePattern == PHASEBLOCKS || bl.runePattern == SPLEEFBLOCKS)) {
4304 if (!w.eAa(bl.x, bl.z))
4305 continue;
4306 int b = w.a(bl.x, bl.y, bl.z);
4307 if (RCT_main.norm_bl(b) == RCT_main.norm_bl(bl.inkBlock & 0xFF)) {
4308 bl.inkBlock = b | (w.b(bl.x, bl.y, bl.z) << 8);
4309 bl.toolArmorType = 1;
4310 w.e(bl.x, bl.y, bl.z, 0);
4311 } else
4312 positionRune.remove(bl); // destroyed
4313 }// for toggle blocks only
4314 else if (bl.toolArmorType == 0
4315 && (bl.runePattern == TOGGLEBLOCKS)) {
4316 if (!w.eAa(bl.x, bl.z))
4317 continue;
4318 int ob = w.a(bl.x, bl.y, bl.z);
4319
4320 ob |= (w.b(bl.x, bl.y, bl.z) << 8); // new block information
4321 w.e(bl.x, bl.y, bl.z, bl.inkBlock & 0xFF,
4322 (bl.inkBlock >> 8) & 0xF); // flip toggleblock
4323 bl.inkBlock = ob; // store old toggleblock
4324 bl.toolArmorType = 1;
4325 } else if (bl.toolArmorType == 0)
4326 bl.toolArmorType = 1;
4327 }
4328
4329 s_saveToMagicDat(); // save
4330 return rv;
4331 }
4332
4333 //
4334 // TODO change this to allow multiple enchantments on one tool
4335 /**
4336 * tool enchantment handler
4337 *
4338 * @param triggerType
4339 * - trigger type
4340 * @param toolType
4341 * - tool tpye
4342 * @param pl
4343 * - player
4344 * @param x
4345 * - block's X
4346 * @param y
4347 * - block's Y
4348 * @param z
4349 * - block's Z
4350 * @param d
4351 * - block's d
4352 * @return
4353 */
4354
4355 boolean d_doToolEngravedEnchantment(EnAction triggerType, int toolType,
4356 RunePlayer pl, int x, int y, int z, int d, int[] ia) {
4357 if (ia != null) {
4358 final RuneWorld w = pl.getWorld();
4359 return t(w, -ia[0], ia, pl).en().runAt(x, y, z, d, toolType,
4360 triggerType);
4361 }
4362 return false;
4363 }
4364
4365 /** only handle tool-type enchants, not engravements */
4366 boolean d_doToolTypeEnchantment(EnAction triggerType, int toolType,
4367 RunePlayer pl, int x, int y, int z, int d) {
4368 final RuneWorld w = pl.getWorld();
4369 boolean rv = false;
4370
4371 final List<int[]> l = sl.get(pl.aw_getName());
4372 if (l != null) {
4373 // Some of these runes will attempt to modify the list of effects
4374 // on this player. We make the assumption that none of these modifications
4375 // were going to remove the remainder of the effects to be checked and
4376 // iterate over a copy of the list using toArray.
4377 for (final int[] ta : l.toArray(new int[l.size()][])) {
4378 final EnAction a = EnAction.fromCode(ta[1]);
4379 if ((a == triggerType || a == TP_CATCHALL) && ta[2] == toolType) {
4380 rv |= t(w, -ta[0], ta, pl)
4381 .runAt(x, y, z, d, toolType,triggerType);
4382 }
4383 }
4384 }
4385
4386 return rv;
4387 }
4388
4389 boolean d_doMasterToolEnchantment(EnAction triggerType, int toolType,
4390 RunePlayer pl, int x, int y, int z, int d) {
4391 boolean rv = false;
4392
4393 // check engraved tool enchantment for <tp>
4394 final int[] ia = pl.gench(triggerType);
4395 rv |= d_doToolEngravedEnchantment(triggerType, toolType, pl, x, y, z,
4396 d, ia);
4397
4398 // check player enchantments
4399 rv |= d_doToolTypeEnchantment(triggerType, toolType, pl, x, y, z, d);
4400
4401 return rv;
4402 }
4403
4404 void r_removeEnchantmentFromToolType(EnAction tp, int tl, RunePlayer pl) {
4405 r_removeEnchantmentFromToolType(tp, tl, pl, 0);
4406 }
4407
4408 void r_removeEnchantmentFromToolType(EnAction tp, int tl, RunePlayer pl,
4409 int rn) {
4410 DBG("Entry " + tp);
4411 final List<int[]> l = sl.get(pl.aw_getName());
4412 if (l == null)
4413 return;
4414
4415 final Iterator<int[]> iter = l.iterator();
4416 while (iter.hasNext()) {
4417 final int[] ta = iter.next();
4418 DBG("Searched enchant = ["+ta[0]+" "+runeIdToRuneNameTable+ta[0]+"] TP = ["+ta[1]+"] tool = "+ta[2]
4419 );
4420 // prevent stacking //tool matching //override command
4421 if ((ta[1] == tp.getCode() || tp == TP_ALL || ta[1] == TP_CATCHALL.getCode()) && ta[2] == tl
4422 && (rn == 0 || ta[0] == rn)) {
4423 if (tl != 0) {
4424 if (tp == TP_RIGHTCLICK || tp == TP_SWING
4425 || tp == TP_CATCHALL)
4426 pl.ab(EnChat.YELLOW
4427 + "You can no longer channel through this tool.");
4428 else if (ArrayUtils.contains(EnAction.primaryActions, tp))
4429 pl.ab(EnChat.YELLOW
4430 + "You sense a passive effect escaping through this tool.");
4431 }
4432 // DBG("removed an enchantment");
4433 iter.remove();
4434 }
4435 }
4436 s_saveToMagicDat();
4437 }
4438
4439 /**
4440 * Helper method: Check if a tool is enchanted, without erasing the contents
4441 *
4442 * @param pl
4443 * - the player to be searched
4444 * @param tp
4445 * - the trigger to be searched for (-1 for any)
4446 * @param tl
4447 * - the tool to be searched for
4448 * @param rn
4449 * - rune pattern being searched for (0 for any)
4450 * @return - whether or not an ench was found (true found, false notfound)
4451 */
4452 boolean r_searchForToolTypeEnchants(RunePlayer pl, EnAction tp, int tl, int rn) // find
4453 // enchants
4454 // for
4455 // a
4456 // specific
4457 // tool
4458 {
4459 final List<int[]> l = sl.get(pl.aw_getName());
4460 if (l == null)
4461 return false;
4462 for (final int[] ta : l) {
4463 if ((ta[1] == tp.getCode() || tp == TP_ALL) && ta[2] == tl
4464 && (rn == 0 || ta[0] == rn)) {
4465 return true;
4466 }
4467 }
4468
4469 return false;
4470 }
4471
4472 void r(int x, int y, int z, int d) {
4473 switch (d) {
4474 case 0:
4475 --y;
4476 break;
4477 case 1:
4478 ++y;
4479 break;
4480 case 2:
4481 --z;
4482 break;
4483 case 3:
4484 ++z;
4485 break;
4486 case 4:
4487 --x;
4488 break;
4489 case 5:
4490 ++x;
4491 break;
4492 }
4493 }
4494
4495 public rcm a(RunePlayer pl, int x, int y, int z, int tl, int f) {
4496 // DBG("entered a() with tool of "+tl);
4497 RuneWorld w = pl.getWorld();
4498 int wid = getWorldId(w);
4499
4500 int clk = w.a(x, y, z);
4501 if (clk == SNOW || clk == RS_WIRE) {
4502 --y;
4503 f = 1;
4504 } // flat blocks are effectively transparent
4505
4506 // if (tl > 255 || tl == 0) d(0,pl,x,y,z,0);
4507
4508 for (int i = 0; i < wr_runeTemplateArray.length; i++) {
4509 int cx = x, cy = y, cz = z;
4510 int r = RunecraftParser.a_runeDetection(wr_runeTemplateArray[i], w,
4511 cx, cy, cz, tl, pl);
4512 if (r == 0 && (tl > 255 || tl == 0)) {
4513 switch (f) { // try again in clicked-face direction
4514
4515 // 0(down) 1(up) 2(east) 3(west) 4(north) 5(south)
4516 // y-1 y+1 x+1 x-1 z-1 z+1
4517 case -1:
4518 break; // Automation / other 'no direction' signals
4519 case 0:
4520 --cy;
4521 break;
4522 case 1:
4523 ++cy;
4524 break;
4525 case 2:
4526 ++cx;
4527 break;
4528 case 3:
4529 --cx;
4530 break;
4531 case 4:
4532 --cz;
4533 break;
4534 case 5:
4535 ++cz;
4536 break;
4537 }
4538 r = RunecraftParser.a_runeDetection(wr_runeTemplateArray[i], w,
4539 cx, cy, cz, tl, pl);
4540 }
4541 if (r > 0) { // removed code (rcn.aa==0?tl:rcn.aa)
4542 // DBG("Tool used is "+ tl);
4543 return new rcm(i + 1, r, cx, cy, cz, wid,
4544 RunecraftParser.repetitionCount, RunecraftParser.inkMd,
4545 tl);
4546 }
4547 }
4548 return new rcm(0, 0, x, y, z, wid, 0, tl);
4549 }
4550
4551 private boolean c(String paramString, RunePlayer pl, int rb, WardType cu) {
4552 //
4553 return c(
4554 paramString,
4555 pl,
4556 "used "
4557 + ("aeiou".contains(paramString.substring(0, 1)
4558 .toLowerCase()) ? "an " : "a ") + paramString
4559 + ".", rb, cu);
4560 }
4561
4562 boolean c(String paramString, RunePlayer pl, WardType cu) {
4563 // for curses
4564 return c(
4565 paramString,
4566 pl,
4567 "used "
4568 + ("aeiou".contains(paramString.substring(0, 1)
4569 .toLowerCase()) ? "an " : "a ") + paramString
4570 + ".", 0, cu);
4571 }
4572
4573 boolean c(String paramString, RunePlayer pl) {
4574 return c(
4575 paramString,
4576 pl,
4577 "used "
4578 + ("aeiou".contains(paramString.substring(0, 1)
4579 .toLowerCase()) ? "an " : "a ") + paramString
4580 + ".");
4581 }
4582
4583 boolean c(String paramString, RunePlayer pl, int rb) {
4584 return c(
4585 paramString,
4586 pl,
4587 "used "
4588 + ("aeiou".contains(paramString.substring(0, 1)
4589 .toLowerCase()) ? "an " : "a ") + paramString
4590 + ".", rb);
4591 }
4592
4593 /**
4594 * Check if disabled-runes.txt contains the given line
4595 *
4596 * @param nm
4597 * line to check for
4598 * @return true when the file contains the line
4599 */
4600 boolean rlc(String nm) {
4601 nm = nm.replaceAll("[^A-Za-z0-9 ]+", "").toLowerCase();
4602 // DBG("Checking for: ["+Chat.YELLOW+nm+Chat.GREEN+"], "+Chat.RED+rl.contains(nm));
4603 return rl.contains(nm);
4604 }
4605
4606 boolean c(String nm, RunePlayer pl, String use) {
4607 return c(nm, pl, use, 0, WardType.Aether);
4608 }
4609
4610 boolean c(String nm, RunePlayer pl, String use, int rb) {
4611 return c(nm, pl, use, rb, WardType.Aether);
4612 }
4613
4614 /**
4615 * Check if a player is blocked from using a rune.
4616 *
4617 * @param runeName
4618 * name of rune
4619 * @param pl
4620 * player using rune
4621 * @param use
4622 * string describing action
4623 * @param rb
4624 * ink block id
4625 * @param cu
4626 * Type of ward relevant to this action
4627 * @return true if rune is disabled
4628 */
4629 boolean c(String runeName, RunePlayer pl, String use, int rb, WardType cu) {
4630 final String playerName = pl.aw_getName();
4631
4632 if (rlc(playerName)) {
4633 pl.ab(EnChat.RED + "The aether refuses to listen to you!");
4634 return true;
4635 }
4636
4637 // check wards - includes error messages
4638 if (wdc(pl, cu)) {
4639 return true;
4640 }
4641
4642 // Check bukkit permissions
4643 final boolean perm = pl.c(
4644 "runes."
4645 + runeName.replaceAll("[^A-Za-z0-9]+", "")
4646 .toLowerCase(), "activate");
4647 if (!perm) {
4648 pl.ab(EnChat.RED + "The aether would not accept your " + runeName
4649 + ".");
4650 return true;
4651 }
4652
4653 // Check disabled-runes.txt
4654 final boolean r = rlc(runeName);
4655 final boolean pr = rlc(playerName + " " + runeName);
4656 final boolean rt = rlc(runeName + " " + rb);
4657 final boolean prt = rlc(playerName + " " + runeName + " " + rb);
4658
4659 // Players need an even number of matches to proceed. Each match toggles
4660 // permission.
4661 if (wl ^ r ^ pr ^ rt ^ prt) {
4662 if (rt ^ prt) {
4663 pl.ab(EnChat.RED
4664 + "The aether demands a different material from you.");
4665 } else if (prt ^ pr) {
4666 pl.ab(EnChat.RED + "The aether will not grant this power to you.");
4667 } else {
4668 pl.ab(EnChat.RED + "The aether would not accept your " + runeName
4669 + ".");
4670 }
4671
4672 return true;
4673 }
4674
4675 final EnChat msgColor = cu == WardType.Void ? EnChat.PURPLE : EnChat.GREEN;
4676 pl.ab(msgColor + runeName.substring(0, 1).toUpperCase()
4677 + runeName.substring(1) + " accepted.");
4678 logInfo(playerName + " " + use);
4679 return false;
4680 }
4681
4682 rcm b_NextEmptySpace(RuneWorld w, int x, int y, int z) {
4683 return b(w, x, y, z, 1);
4684 }
4685
4686 rcm b(RuneWorld w, int x, int y, int z, int dir) {
4687 // DBG("Entering b with direction " + dir);
4688 rcm r = new rcm(x, y, z, w.getWorldId());
4689 r.inkBlock = w.a(x, y, z);
4690 switch (dir) {
4691 // 0(down) 1(up) 2(east) 3(west) 4(north) 5(south)
4692 // y-1 y+1 x+1 x-1 z-1 z+1
4693 case 0: {
4694 r.y = 0;
4695 for (int i = y; i >= 0; i--) {
4696 int b = (w.a(x, i, z));
4697 if (b == 0 || b == OBSIDIAN || b == BEDROCK) {
4698 r.inkBlock = b;
4699 r.y = i; /* DBG("Ping case 0");/* */
4700 break;
4701 }
4702 }
4703 }
4704 break;
4705 case 1: // 024 = -ve values
4706 {
4707 r.y = w.getMaxY() + 1;
4708 for (int i = y; i <= w.getMaxY(); i++) {
4709 int b = (w.a(x, i, z));
4710 if (b == 0 || b == OBSIDIAN || b == BEDROCK) {
4711 r.inkBlock = b;
4712 r.y = i; /* DBG("Ping case 1");/* */
4713 break;
4714 }
4715 }
4716 }
4717 break;
4718 case 4:
4719 // north is -z
4720 r.z = z - 64;
4721 for (int i = z; i > z - 64; i--) {
4722 if (!w.eAa(x, i))
4723 w.eAd(x, i);
4724 int b = (w.a(x, y, i));
4725 if (b == 0 || b == OBSIDIAN || b == BEDROCK) {
4726 r.inkBlock = b;
4727 r.z = i; /* DBG("Ping case 2 "+i+"|"+b);/* */
4728 break;
4729 }
4730 }
4731 break;
4732 case 5:
4733 r.z = z + 64;
4734 for (int i = z; i < z + 64; i++) {
4735 if (!w.eAa(x, i))
4736 w.eAd(x, i);
4737 int b = (w.a(x, y, i));
4738 if (b == 0 || b == OBSIDIAN || b == BEDROCK) {
4739 r.inkBlock = b;
4740 r.z = i; /* DBG("Ping case 3 "+i+"|"+b);/* */
4741 break;
4742 }
4743 }
4744 break;
4745 case 3:
4746 r.x = x - 64;
4747 for (int i = x; i > x - 64; i--) {
4748 if (!w.eAa(i, z))
4749 w.eAd(i, z);
4750 int b = (w.a(i, y, z));
4751 if (b == 0 || b == OBSIDIAN || b == BEDROCK) {
4752 r.inkBlock = b;
4753 r.x = i; /* DBG("Ping case 4 "+i+"|"+b);/* */
4754 break;
4755 }
4756 }
4757 break;
4758
4759 case 2:
4760 r.x = x + 64;
4761 for (int i = x; i < x + 64; i++) {
4762 if (!w.eAa(i, z))
4763 w.eAd(i, z);
4764 int b = (w.a(i, y, z));
4765 if (b == 0 || b == OBSIDIAN || b == BEDROCK) {
4766 r.inkBlock = b;
4767 r.x = i; /* DBG("Ping case 5 "+i+"|"+b);/* */
4768 break;
4769 }
4770 }
4771 break;
4772 }
4773 // DBG("b complete, dir["+dir+dirs(dir)+"]! ["+r.x+","+r.y+","+r.z+"]");
4774 return r;
4775
4776 }
4777
4778 boolean c(RuneWorld w, int f, int t, int x, int y, int z) {
4779 for (int i = y; i > 0; i--) {
4780 int k = w.a(x, i, z);
4781 if (k == 9)
4782 k = 8;
4783 if (k == f) {
4784 if (k != 8 || w.b(x, i, z) == 0) // must be source water
4785 w.e(x, i, z, t);
4786 return true;
4787 } else if (k > 0) {
4788 return false;
4789 }
4790 }
4791 return false;
4792 }
4793
4794 /**
4795 * Retrieves a unique id the world is associated with This is used as 4th
4796 * coordinate dimension
4797 */
4798 int getWorldId(RuneWorld w) {
4799 int id = w.getWorldId();
4800 if (id != -1)
4801 return id;
4802
4803 synchronized (worlds) {
4804 // find an unused number
4805 for (int i = 0;; ++i)
4806 if (!worldId.containsValue(i)) {
4807 worldId.put(w.getName(), i);
4808 worlds.put(i, w);
4809 w.setWorldId(i);
4810 logInfo("World '" + w.getName() + "': new id " + i);
4811 return i;
4812 }
4813 }
4814 }
4815
4816 public RuneWorld getWorldById(int id) {
4817 synchronized (worlds) {
4818 return worlds.get(id);
4819 }
4820 }
4821
4822 // the Bukkit plugin must register loaded worlds here
4823 public void registerWorld(RuneWorld w) {
4824 synchronized (worlds) {
4825 RuneWorld old = null;
4826
4827 int id = w.getWorldId();
4828 if (id != -1) {
4829 if (worlds.get(id) == null)
4830 logInfo("World '" + w.getName() + "': id " + id);
4831 if (worlds.get(id) != null
4832 && !w.getName().equals(worlds.get(id).getName())) {
4833 logInfo("Conflict: World '" + w.getName() + "': id " + id
4834 + " is used by '" + worlds.get(id).getName() + "'");
4835 old = worlds.get(id);
4836 worldId.remove(old.getName());
4837 worlds.remove(id);
4838 }
4839
4840 worldId.put(w.getName(), id);
4841 worlds.put(id, w);
4842 }
4843 if (id == -1) {
4844 w.setWorldId(-1); // let getWorldId fetch a new one
4845 id = getWorldId(w);
4846 }
4847
4848 if (old != null) {
4849 // get a new id for the other world
4850 old.setWorldId(-1);
4851 getWorldId(old);
4852 }
4853
4854 // remove duplicates with same id
4855 Iterator<Entry<String, Integer>> iter = worldId.entrySet()
4856 .iterator();
4857 while (iter.hasNext()) {
4858 Entry<String, Integer> other = iter.next();
4859 if (other.getValue().equals(id)
4860 && !other.getKey().equals(w.getName()))
4861 iter.remove();
4862 }
4863
4864 }
4865 }
4866
4867 /**
4868 * Load integer array Loads integer array, prefixed with array size, and
4869 * returns it
4870 */
4871 private int[] lia(DataInputStream dis) throws IOException {
4872 int[] arr = new int[dis.readInt()];
4873 for (int i = 0; i < arr.length; ++i)
4874 arr[i] = dis.readInt();
4875 return arr;
4876 }
4877
4878 /**
4879 * Save integer array Stores size of array and integer values
4880 */
4881 private void sia(DataOutputStream dos, int[] arr) throws IOException {
4882 dos.writeInt(arr.length);
4883 for (int i = 0; i < arr.length; ++i)
4884 dos.writeInt(arr[i]);
4885 }
4886
4887 // saving is an expensive operation, so we shouldn't do it often
4888 // and we shouldn't block the main thread;
4889 // a task is scheduled in method l()
4890 void s_saveToMagicDat() {
4891 drt_magicDatNeedsUpdate = true;
4892 }
4893
4894 void do_s_doSaveToMagicDat() {
4895 synchronized (this) {
4896 if (drt_magicDatNeedsUpdate == false)
4897 return;
4898 FileOutputStream fos = null;
4899 DataOutputStream dos = null;
4900 try {
4901 File magic_new = new File(main_world.getWorldFolder(),
4902 "magic.dat_new");
4903 File magic_real = new File(main_world.getWorldFolder(),
4904 "magic.dat");
4905
4906 fos = new FileOutputStream(magic_new);
4907 dos = new DataOutputStream(fos);
4908
4909 // current version number (negated)
4910 dos.writeInt(-11);
4911
4912 // data blocks
4913 dos.writeInt(md.length);
4914 for (int q = 0; q < md.length; q++) {
4915 List<int[]> mdq = md[q];
4916 dos.writeInt(mdq.size());
4917 for (int i = 0; i < mdq.size(); i++) {
4918 sia(dos, mdq.get(i));
4919 }
4920 }
4921 // DBG("--"+strl.size() + " total messages");
4922 dos.writeInt(strl.size()); // number of entries
4923 for (int i = 0; i < strl.size(); i++) {
4924 dos.writeInt(strl.get(i).size()); // lines in an entry
4925 // DBG("-"+strl.get(i).size() + " Lines in this message");
4926 for (int j = 0; j < strl.get(i).size(); j++) {
4927 // DBG(strl.get(i).get(j).length() +
4928 // ": "+strl.get(i).get(j));
4929 String str = strl.get(i).get(j);
4930 byte[] data = str.getBytes("UTF-8");
4931 dos.writeInt(data.length);
4932 dos.write(data);
4933
4934 /*
4935 * for (int k = 0; k < strl.get(i).get(j).length(); k++)
4936 * {
4937 *
4938 * } dos.writeChars(strl.get(i).get(j));
4939 */
4940 }
4941 }
4942 // player slots/functions
4943 synchronized (sl) {
4944 dos.writeInt(sl.size());
4945 for (Map.Entry<String, List<int[]>> e : sl.entrySet()) {
4946 dos.writeUTF(e.getKey());
4947 dos.writeInt(e.getValue().size());
4948 for (int i = 0; i < e.getValue().size(); i++) {
4949 sia(dos, e.getValue().get(i));
4950 }
4951 }
4952 }
4953
4954 // 'pr' HashMap data (positional runes)
4955 synchronized (positionRune) {
4956 int c = 0;
4957 for (rcm e : positionRune.values())
4958 if (e.runePattern != 0)
4959 ++c; // count 'real' pr runes
4960 dos.writeInt(c);
4961 for (rcm e : positionRune.values()) {
4962 if (e.runePattern == 0)
4963 continue; // no need to save those
4964 sia(dos, e.toArray());
4965 }
4966 }
4967
4968 // names of initiated players
4969 synchronized (ip) {
4970 dos.writeInt(ip.size());
4971 for (String s : ip)
4972 dos.writeUTF(s);
4973 }
4974
4975 // save (world => id) mapping
4976 synchronized (worlds) {
4977 dos.writeInt(worldId.size());
4978 for (Map.Entry<String, Integer> e : worldId.entrySet()) {
4979 dos.writeUTF(e.getKey());
4980 dos.writeInt(e.getValue());
4981 }
4982 }
4983
4984 synchronized (hexRune) {
4985 int c = 0;
4986
4987 for (rcm e : hexRune.values())
4988 if (e.runePattern != 0)
4989 ++c; // count 'real' pr runes
4990 // logInfo("Saved "+c+" hexed runes ");
4991 dos.writeInt(c);
4992 for (rcm e : hexRune.values()) {
4993 if (e.runePattern == 0)
4994 continue; // no need to save those
4995 sia(dos, e.toArray());
4996 }
4997 }
4998
4999 // close file
5000 dos.close();
5001
5002 // replace actual file
5003 if (magic_real.exists())
5004 magic_real.delete();
5005 magic_new.renameTo(magic_real);
5006
5007 } catch (Exception e) {
5008 e.printStackTrace();
5009 } finally {
5010 try {
5011 if (dos != null)
5012 dos.close();
5013 if (fos != null)
5014 fos.close();
5015 } catch (Exception e) {
5016 }
5017 drt_magicDatNeedsUpdate = false; // mark magic.dat as saved
5018 }
5019 // save waypoints
5020
5021 try {
5022 File WayPointNew = new File(main_world.getWorldFolder(),
5023 "magic_waypoints.dat_new");
5024 File WayPointOld = new File(main_world.getWorldFolder(),
5025 "magic_waypoints.dat");
5026
5027 fos = new FileOutputStream(WayPointNew);
5028 PrintWriter pos = new PrintWriter(fos);
5029
5030 for (RunePoint wp : waypointList) {
5031 //DBG("Saving waypoint[" + wp.getSaveString() + "]");
5032 pos.write(wp.getSaveString()+"\n");
5033 }
5034
5035 pos.close();
5036 if (WayPointOld.exists())
5037 WayPointOld.delete();
5038 WayPointNew.renameTo(WayPointOld);
5039 } catch (Exception e) {
5040 e.printStackTrace();
5041 }
5042
5043 }
5044 }
5045
5046 private void l_loadMagicDat() {
5047 try {
5048 FileInputStream fis = new FileInputStream(new File(
5049 main_world.getWorldFolder(), "magic.dat"));
5050 DataInputStream dis = null;
5051 try {
5052 dis = new DataInputStream(fis);
5053 // negated version number
5054 int vr = -dis.readInt();
5055 if (vr < 2)
5056 throw new UnsupportedOperationException(
5057 "Runecraft's magic.dat is in a very old and unsupported data format.");
5058 logInfo("Loading magic.dat file, version [" + vr + "]");
5059
5060 // load data points
5061 // they are stored as 5 (or more) LinkedLists of int[]
5062 // List[] md = { wpl, tpl, frl, prl, rpl };
5063 int md_s = dis.readInt(); // this is the number of linked lists
5064 for (int q = 0; q < md_s; q++) {
5065 int list_s = dis.readInt(); // length of the linked list
5066 // being read
5067 for (int i = 0; i < list_s; i++) {
5068 int[] ta = lia(dis); // load integer array (must be
5069 // prefixed with size)
5070
5071 if (q >= md.length)
5072 continue; // ignore broken data
5073 if (q == 3 && ta[0] - 1 >= tf.length)
5074 continue; // ditto
5075 md[q].add(ta);
5076 }
5077 }
5078 if (vr >= 10) {
5079
5080 int lmt1 = dis.readInt();
5081 // DBG("Loading!! "+lmt1+" entries");
5082 for (int i = 0; i < lmt1; i++) // number of entries
5083 {
5084 int lmt2 = dis.readInt();
5085 DBG("Loaded " + lmt2 + " lines");
5086 List<String> strs = new ArrayList<String>();
5087
5088 for (int j = 0; j < lmt2; j++)// number of lines
5089 {
5090 String str = "";
5091 int length = dis.readInt();
5092 byte[] data = new byte[length];
5093 dis.readFully(data);
5094 str = new String(data, "UTF-8");
5095
5096 if (str.length() > 0) {
5097 strs.add(str);
5098 DBG(str.length() + " " + str);
5099 }
5100
5101 }
5102 strl.add(strs);
5103
5104 }
5105
5106 } else
5107 System.out.println("Version is actually " + vr);
5108
5109 logInfo("Loaded:");
5110 logInfo(" - " + waypointRuneList.size() + " waypoints, "
5111 + teleportRuneList.size() + " teleporters");
5112 logInfo(" - " + positionRuneList.size() + " position runes");
5113 logInfo(" - " + runePadList.size() + " rune pads");
5114 logInfo(" - " + logicDestinationRuneList.size() + " logic pads");
5115
5116 // converting old data (waypoints, teleporters)
5117 if (vr < 4) {
5118 // {sig,sig2, r.x,r.y,r.z,new:{worldId}, ink}
5119 for (int i = 0; i < waypointRuneList.size(); i++) {
5120 int[] wp = waypointRuneList.get(i);
5121 int[] nwp = new int[] { wp[0], 0, wp[2], wp[3], wp[4],
5122 0, wp[1], 1 };
5123 waypointRuneList.set(i, nwp);
5124 }
5125
5126 // {r.x, r.y, r.z, new:{worldId}, sig,sig2}
5127 for (int i = 0; i < teleportRuneList.size(); i++) {
5128 int[] tp = teleportRuneList.get(i);
5129 int[] ntp = new int[] { tp[0], tp[1], tp[2], 0, tp[3],
5130 0 };
5131 teleportRuneList.set(i, ntp);
5132 }
5133 }
5134
5135 // converting old data (rune pads)
5136 if (vr < 4) {
5137 for (int i = 0; i < runePadList.size(); i++) {
5138 int[] rp = runePadList.get(i);
5139 if (rp.length != 9 && rp.length != 11)
5140 continue;
5141 int[] nrp = new int[rp.length + 1];
5142 for (int k = 0; k < 4; ++k)
5143 nrp[k] = rp[k];
5144 for (int k = 4; k < rp.length; ++k)
5145 nrp[k + 1] = rp[k];
5146 nrp[4] = 0;
5147 runePadList.set(i, nrp);
5148 }
5149 }
5150
5151 // converting old data (logic dest, LOGPAD rune pads)
5152 if (vr < 6) {
5153 for (int i = 0; i < logicDestinationRuneList.size(); i++) {
5154 int[] ld = logicDestinationRuneList.get(i);
5155 int[] nld = new int[] { ld[2], ld[3], ld[4], ld[5],
5156 ld[0], 0, ld[1] }; // x,y,z,w, sig,meta,key
5157 logicDestinationRuneList.set(i, nld);
5158 }
5159
5160 for (int i = 0; i < runePadList.size(); i++) {
5161 int[] rp = runePadList.get(i);
5162 if (rp[0] != LOGPAD)
5163 continue;
5164 int[] nrp = new int[rp.length + 1];
5165 for (int k = 0; k < rp.length; ++k)
5166 nrp[k] = rp[k];
5167 nrp[12] = nrp[11];
5168 nrp[11] = 0;
5169 runePadList.set(i, nrp);
5170 }
5171 }
5172
5173 // converting old data (hidden passage)
5174 if (vr < 5) {
5175 for (int i = 0; i < positionRuneList.size(); i++) {
5176 int[] ia = positionRuneList.get(i);
5177 int[] nia = new int[11];
5178 for (int k = 0; k < 4; k++)
5179 nia[k] = ia[k];
5180 for (int k = 4; k < ia.length; k++)
5181 nia[k + 1] = ia[k];
5182 positionRuneList.set(i, nia);
5183 }
5184 }
5185
5186 // populate position runes set
5187 for (int[] ta : positionRuneList)
5188 addpr_addPositionRune(ta);
5189
5190 // player slots/functions
5191 // each player has a separate LinkedList of int[]
5192 int sl_s = dis.readInt();
5193 final Map<String, List<int[]>> tempSL = Collections
5194 .synchronizedMap(new HashMap<String, List<int[]>>());
5195 synchronized (sl) {
5196 for (int i = 0; i < sl_s; i++) {
5197 String pl = dis.readUTF();
5198 List<int[]> ll = createLList();
5199 int ll_s = dis.readInt();
5200 for (int j = 0; j < ll_s; j++) {
5201 int[] ta = lia(dis);
5202 ll.add(ta);
5203 }
5204 tempSL.put(pl, ll);
5205 }
5206 }
5207 sl.clear();
5208 sl.putAll(tempSL);
5209 if (sl.size() != 0)
5210 logInfo(" - " + sl.size() + " player data sets");
5211
5212 // 'pr' HashMap data
5213 // each 'e' is a block with unique coordinates and additional
5214 // info
5215 int pr_s = dis.readInt();
5216 synchronized (positionRune) {
5217 for (int i = 0; i < pr_s; i++) {
5218 int[] ta = lia(dis);
5219 if (ta.length < 8) // convert old data (add world id)
5220 ta = new int[] { ta[0], ta[1], ta[2], 0, ta[3],
5221 ta[4], ta[5], ta[6] };
5222 if (ta.length < 9) // convert old data (add 'd' field)
5223 ta = new int[] { ta[0], ta[1], ta[2], ta[3], ta[4],
5224 ta[5], ta[6], 0, ta[7] };
5225 rcm e = new rcm(ta);
5226 positionRune.put(e, e);
5227 }
5228 }
5229 if (pr_s != 0)
5230 logInfo(" - " + pr_s + " block runes");
5231
5232 // update waypoints with direction.
5233 int WPupdateCtr = 0;
5234 for (int i = 0; i < waypointRuneList.size(); i++) {
5235 final int[] wp = waypointRuneList.get(i);
5236 if (wp == null)
5237 continue;
5238 if (wp.length >= 8)
5239 continue; // safety check
5240 DBG("Updating a waypoint");
5241 WPupdateCtr++;
5242 // {g, gd, r.x, r.y, r.z, r.w, r.b, dir}
5243 int[] wp2 = { wp[0], wp[1], wp[2], wp[3], wp[4], wp[5],
5244 wp[6], 1 };
5245 waypointRuneList.set(i, wp2);
5246 }
5247 if (WPupdateCtr > 0)
5248 System.out.println("Runecraft updated " + WPupdateCtr
5249 + " waypoints with directions");
5250
5251 // */
5252
5253 // load list of initiated players
5254 int ip_s = 0;
5255 if (vr >= 3) {
5256 ip_s = dis.readInt();
5257 synchronized (ip) {
5258 for (int i = 0; i < ip_s; i++)
5259 try {
5260 ip.add(dis.readUTF());
5261 } catch (Exception ee) {
5262
5263 }
5264 }
5265 }
5266
5267 if (ip_s != 0)
5268 logInfo(" - " + ip_s + " initiated players");
5269
5270 // load (world => id) mapping
5271 if (vr >= 4) {
5272 int wid_s = dis.readInt();
5273 synchronized (worlds) {
5274 for (int i = 0; i < wid_s; i++) {
5275 String w = dis.readUTF();
5276 int id = dis.readInt();
5277 worldId.put(w, id);
5278 }
5279
5280 worldId.clear(); // NEW: ignore mapping; use world.id
5281 // file instead.
5282 }
5283 if (vr < 7) { // update faith islands to appropriate Y
5284 // height (will be 120 - radius)
5285 // logInfo("--Faith Conversion: "+frl.size()+" --");
5286 for (int i = 0; i < faithRuneList.size(); i++) {
5287
5288 int[] fr = faithRuneList.get(i);
5289
5290 int[] nfr = { fr[0], 120 - fr[3], fr[2], fr[3], -1 };
5291 faithRuneList.set(i, nfr);
5292 }
5293
5294 }
5295 if (vr < 12) // before 2.15
5296 {
5297
5298 }
5299 }
5300 if (vr >= 9) {
5301 synchronized (hexRune) {
5302 int cr_s = dis.readInt();
5303 // logInfo("Attempting to read "+cr_s+" runes");
5304 for (int i = 0; i < cr_s; i++) {
5305 int[] ta = lia(dis);
5306 if (ta.length < 8) // convert old data (add world
5307 // id)
5308 ta = new int[] { ta[0], ta[1], ta[2], 0, ta[3],
5309 ta[4], ta[5], ta[6] };
5310 if (ta.length < 9) // convert old data (add 'd'
5311 // field)
5312 ta = new int[] { ta[0], ta[1], ta[2], ta[3],
5313 ta[4], ta[5], ta[6], 0, ta[7] };
5314 rcm e = new rcm(ta);
5315 hexRune.put(e, e);
5316 }
5317
5318 if (cr_s != 0)
5319 logInfo(" - " + cr_s + " hexed block runes");
5320 }
5321 }
5322 for (int i = 0; i < faithRuneList.size(); i++) {
5323 int fi[] = faithRuneList.get(i);
5324 if (fi.length < 5) {
5325 int[] fii = new int[5];
5326 fii[0] = fi[0];
5327 fii[1] = fi[1];
5328 fii[2] = fi[2];
5329 fii[3] = fi[3];
5330 fii[4] = -1;
5331 faithRuneList.set(i, fii);
5332 // add a world coordinate
5333 }
5334 }
5335
5336 } catch (Exception e) {
5337 e.printStackTrace();
5338 } finally {
5339 if (dis != null)
5340 dis.close();
5341 fis.close();
5342 }
5343 } catch (Exception e) {
5344 // ignore
5345 } finally {
5346 drt_magicDatNeedsUpdate = false; // magic.dat up-to-date
5347 tm.schedule(t(main_world, DRT_DATASAVINGTASK, null), 1000 * 60,
5348 1000 * 60);
5349 }
5350
5351 // load waypoint data
5352 File waypointDataFile = new File(main_world.getWorldFolder(),
5353 "magic_waypoints.dat");
5354 if (waypointDataFile.exists()) {
5355 try {
5356
5357 FileInputStream fis = new FileInputStream(new File(
5358 main_world.getWorldFolder(), "magic_waypoints.dat"));
5359 BufferedReader br = new BufferedReader(new InputStreamReader(
5360 fis));
5361 String line;
5362 while ((line = br.readLine()) != null) {
5363 RunePoint newRP;
5364
5365 if (line.startsWith("TrueNamePoint")) newRP = new WP_TrueName(line, this);
5366 else if (line.startsWith("anchorpoint")) newRP = new WP_AnchorPoint(line,this);
5367 else// if (line.startsWith("Waypoint"))
5368 {newRP = new WP_WayPoint(line,this);}
5369 if (newRP != null) // if null, invalid loadstring
5370 waypointList.add(newRP);
5371 }
5372
5373 } catch (Exception e) {
5374 e.printStackTrace();
5375 }
5376 logInfo("Loaded "+waypointList.size()+" runepoints from auxillary data file");
5377 } else // if the waypoints data file does not exist, convert from
5378 // magic.dat file.
5379 {
5380 for (int[] oldwp : waypointRuneList) {
5381 RunePoint newwp = new WP_WayPoint(new rcm(oldwp[2], oldwp[3],
5382 oldwp[4], oldwp[5]), oldwp[0], oldwp[1], oldwp[7], this);
5383 waypointList.add(newwp);
5384 // DBG("-- Converted waypoint --");
5385 // DBG("["+oldwp[0]+","+oldwp[1]+","+oldwp[2]+","+oldwp[3]+","+oldwp[4]+","+oldwp[5]+"]");
5386 // DBG(newwp.getSaveString());
5387
5388 }
5389
5390 }
5391 }
5392
5393 // add position rune to HashSet
5394 boolean addcr(rcm e) {
5395 synchronized (hexRune) {
5396 if (hexRune.containsKey(e))
5397 return false;
5398 hexRune.put(e, e);
5399 s_saveToMagicDat();
5400 }
5401 return true;
5402 }
5403
5404 // call synched on cr
5405 protected rcm getcr(int x, int y, int z, int wid) {
5406 final rcm getpr_ = new rcm(x, y, z, wid);
5407 return hexRune.get(getpr_);
5408 }
5409
5410 boolean remcr(rcm e) {
5411 synchronized (hexRune) {
5412 if (!hexRune.containsKey(e))
5413 return false;
5414 hexRune.remove(e);
5415 s_saveToMagicDat();
5416 }
5417 return true;
5418 }
5419
5420 void addpr_addPositionRune(int[] ta) {
5421
5422 addpr_addPositionRune(ta, 0);
5423 }
5424
5425 void addpr_addPositionRune(int[] ta, int tp) {
5426 int x = ta[1], z = ta[3];
5427 int y = ta[2]; // you can click on [y-sz ... y]
5428 int wid = ta[4]; // world id
5429 int sz = 0;
5430
5431 if (ta[0] == 1) // hidden passages
5432 sz = ta[9];
5433
5434 synchronized (positionRune) {
5435 for (int dy = 0; dy <= sz; ++dy) {
5436 rcm e = new rcm(x, y - dy, z, wid);
5437 e.runePattern = tp; // rcm.a used as type/action; 0 means
5438 // "look into prl"
5439 positionRune.put(e, e);
5440 }
5441 }
5442 }
5443
5444 boolean addpr_addPositionRune(rcm e) {
5445 synchronized (positionRune) {
5446 if (positionRune.containsKey(e)) {
5447 positionRune.get(e);
5448 DBG("Interfering rcm [" + e.runePattern + " "
5449 + runeIdToRuneNameTable.get(e.runePattern) + "]");
5450 return false;
5451 }
5452
5453 positionRune.put(e, e);
5454 s_saveToMagicDat();
5455 }
5456 return true;
5457 }
5458
5459 boolean rempr_removePositionRune(rcm e) {
5460 synchronized (positionRune) {
5461 if (!positionRune.containsKey(e))
5462 return false;
5463 positionRune.remove(e);
5464 s_saveToMagicDat();
5465 }
5466 return true;
5467 }
5468
5469 void c(RuneWorld w, rcm r, int u, int v) {
5470 c(w, r, u, v, 0);
5471 }
5472
5473 void c(RuneWorld w, rcm r, int u, int v, int yo) { // delete non-blanks
5474 for (int x = r.x - (u / 2); x <= r.x + (u / 2); x++)
5475 for (int z = r.z - (v / 2); z <= r.z + (v / 2); z++) {
5476 // delete torches attached to this block prior to this block
5477 if (x < r.x + (u / 2)
5478 && torches.contains(w.a(x + 1, r.y + yo, z)))
5479 w.e(x + 1, r.y + yo, z, AIR);
5480 if (z < r.z + (v / 2)
5481 && torches.contains(w.a(x, r.y + yo, z + 1)))
5482 w.e(x, r.y + yo, z + 1, AIR);
5483
5484 int a = w.a(x, r.y + yo, z);
5485 if (a == ENDER_EGG && !rlc("consume ender dragon eggs")) {
5486 DBG("a = [" + a + "] compared to " + ENDER_EGG);
5487 // relocate ender egg
5488 int rndx = 0;
5489 int rndz = 0;
5490 int rndy = 0;
5491 do {
5492 rndx = (int) (Math.random() * (15 * 2) - 15);
5493 rndz = (int) (Math.random() * (15 * 2) - 15);
5494 rndy = (int) (Math.random() * 7);
5495 } while (w.a(r.x + rndx, r.y + rndy, r.z + rndz) != AIR);
5496 w.e(r.x + rndx, r.y + rndy, r.z + rndz, ENDER_EGG);
5497 }// */
5498 if (bt_blockTier[a] != 0 && a != BEDROCK)
5499 w.e(x, r.y + yo, z, AIR);
5500 }
5501 }
5502
5503 void c(RuneWorld w, rcm r, int u, int v, int yo, int ovr) { // delete 'ovr'
5504 for (int x = r.x - (u / 2); x <= r.x + (u / 2); x++)
5505 for (int z = r.z - (v / 2); z <= r.z + (v / 2); z++) {
5506 int a = w.a(x, r.y + yo, z);
5507 if (ovr == 0 ? bt_blockTier[a] != 0 : a == ovr)
5508 w.e(x, r.y + yo, z, AIR);
5509 }
5510 }
5511
5512 void cStone(RuneWorld w, rcm r, int u, int v) {
5513 cStone(w, r, u, v, 0);
5514 }
5515
5516 void cStone(RuneWorld w, rcm r, int u, int v, int yo) { // delete non-blanks
5517 for (int x = r.x - (u / 2); x <= r.x + (u / 2); x++)
5518 for (int z = r.z - (v / 2); z <= r.z + (v / 2); z++) {
5519 // delete torches attached to this block prior to this block
5520 if (x < r.x + (u / 2)
5521 && torches.contains(w.a(x + 1, r.y + yo, z)))
5522 w.e(x + 1, r.y + yo, z, STONE);
5523 if (z < r.z + (v / 2)
5524 && torches.contains(w.a(x, r.y + yo, z + 1)))
5525 w.e(x, r.y + yo, z + 1, STONE);
5526
5527 int a = w.a(x, r.y + yo, z);
5528 /*
5529 * if (a == ENDER_EGG) { //relocate ender egg int rndx = 0; int
5530 * rndz = 0; int rndy = 0; do { rndx = (int)
5531 * (Math.random()*(15*2)-15); rndz = (int)
5532 * (Math.random()*(15*2)-15); rndy = (int) (Math.random()*7); }
5533 * while (w.a(r.x+rndx, r.y+rndy, r.z+rndz) != AIR);
5534 * w.e(r.x+rndx, r.y+rndy, r.z+rndz,ENDER_EGG); }
5535 */
5536 if (bt_blockTier[a] != 0 && a != BEDROCK)
5537 w.e(x, r.y + yo, z, STONE);
5538 }
5539 }
5540
5541 void e(RuneWorld w, rcm r, int u, int v) {
5542 for (int x = r.x - (u / 2); x <= r.x + (u / 2); x++)
5543 for (int z = r.z - (v / 2); z <= r.z + (v / 2); z++) {
5544 int a = w.a(x, r.y, z);
5545 if (bt_blockTier[a] != 0
5546 && (Math.abs(r.x - x) == Math.floor(u / 2) || Math
5547 .abs(r.z - z) == Math.floor(v / 2)))
5548 w.e(x, r.y, z, AIR);
5549 }
5550 }
5551
5552 int b(int v) {
5553 switch (v) {
5554 case AIR:
5555 case GRASS:
5556 case BEDROCK:
5557 case WATER:
5558 case STAT_WATER:
5559 case LAVA:
5560 case STAT_LAVA:
5561 case FIRE:
5562 case MOB_SPAWNER:
5563 return AIR;
5564 case RS_WIRE:
5565 return 331;
5566 }
5567 return v;
5568 }
5569
5570 /**
5571 * Get signature from rune
5572 *
5573 * @param world
5574 * World
5575 * @param x
5576 * ,y,z Center of rune
5577 * @param runeType
5578 * Modus - type of rune
5579 * @param usingMetaData
5580 * True if metadata signature, false if normal block signature
5581 */
5582 int gg(RuneWorld world, int x, int y, int z, int runeType,
5583 boolean usingMetaData) // SIGNATURE FINDING THING
5584 {
5585 int[][][] coord = new int[][][] {
5586 { { x, y, z - 1 }, { x + 1, y, z }, { x, y, z + 1 },
5587 { x - 1, y, z } }, // 0: Waypoint, QuickTP
5588 { { x, y, z - 2 }, { x + 2, y, z }, { x, y, z + 2 },
5589 { x - 2, y, z } }, // 1: Teleporter (floor)
5590 { { x - 2, y, z }, { x, y - 2, z }, { x + 2, y, z },
5591 { x, y + 2, z } }, // 2: Teleporter (old north-south)
5592 { { x, y + 2, z }, { x + 2, y, z }, { x, y - 2, z },
5593 { x - 2, y, z } }, // 3: Teleporter (new east-west)
5594 { { x, y, z - 2 }, { x, y - 2, z }, { x, y, z + 2 },
5595 { x, y + 2, z } }, // 4: Teleporter (old east-west)
5596 { { x, y + 2, z }, { x, y, z - 2 }, { x, y - 2, z },
5597 { x, y, z + 2 } }, // 5: Teleporter (new north-south)
5598 { { x - 1, y, z - 1 }, { x - 1, y, z + 1 },
5599 { x + 1, y, z + 1 }, { x + 1, y, z - 1 } }, // 6:
5600 // Phase/Lock/Spleef
5601 // Blocks
5602 { { x - 1, y, z }, { x + 1, y, z }, { x, y, z + 1 },
5603 { x, y, z - 1 } }, // 7: Automation stuff (Waypoint
5604 // style)
5605 { { x - 2, y, z }, { x + 2, y, z }, { x, y, z + 2 },
5606 { x, y, z - 2 } }, // 8: Automation stuff (Teleporter
5607 // style)
5608 { { x, y, z - 3 }, { x + 3, y, z }, { x, y, z + 3 },
5609 { x - 3, y, z } }, // 9: FTeleporter
5610 { { x, y + 1, z }, { x + 1, y, z }, { x, y - 1, z },
5611 { x - 1, y, z } }, // 10: Waypoint (new east-west)
5612 { { x, y + 1, z }, { x, y, z + 1 }, { x, y - 1, z },
5613 { x, y, z - 1 } }, // 11: Waypoint (new north-south)
5614 { { x, y + 3, z }, { x + 3, y, z }, { x, y - 3, z },
5615 { x - 3, y, z } }, // 10: FTeleporter (new east-west)
5616 { { x, y + 3, z }, { x, y, z + 3 }, { x, y - 3, z },
5617 { x, y, z - 3 } }, // 11: FTeleporter (new north-south)
5618 };
5619
5620 int which = 0;
5621 switch (runeType) {
5622 case FREIGHTPOINT:
5623
5624 case WAYPOINT:
5625 case FAITHPOINT:
5626 case QUICKTP:
5627 which = 0;
5628 break;
5629 case TELEPORTER:
5630 case FREIGHTTP:
5631 which = 1;
5632 break;
5633 case WALLTELEPORTER: // old north-south, new east-west
5634 which = 2 + (opt_on("compass-old-north") ? 0 : 1);
5635 break;
5636 case WALLTELEPORTER + 1: // old east-west, new north-south
5637 which = 4 + (opt_on("compass-old-north") ? 0 : 1);
5638 break;
5639 case TOGGLEBLOCKS:
5640 case PHASEBLOCKS:
5641 case LOCKBLOCKS:
5642 case SPLEEFBLOCKS:
5643 case REALITYANCHOR:
5644 case REALITYMASTER:
5645 which = 6;
5646 break;
5647 case LOGDST:
5648 case LOGRED:
5649 case LOGSRED:
5650 case LOGPAD:
5651 case LOGBLOCK:
5652 case FAITHOUT:
5653 case FAITHIN:
5654 which = 7;
5655 break; // radius 1
5656 case LOGHIT:
5657 case LOGHITE:
5658 which = 8;
5659 break; // radius 2
5660 case FTP:
5661 which = 9;
5662 break; // radius 3
5663 case WALLWPOINT:
5664 case WALLFPOINT:
5665 which = 10;
5666 break;
5667 case WALLWPOINT + 1:
5668 case WALLFPOINT + 1:
5669 which = 11;
5670 break;
5671 case WALLFTP:
5672 which = 12;
5673 break;
5674 case WALLFTP + 1:
5675 which = 13;
5676 break;
5677 }
5678
5679 final int[][] co = coord[which];
5680
5681 int gi[] = new int[4];
5682 for (int i = 0; i < 4; ++i) {
5683 gi[i] = c_aliasTierZeroToAir(world, co[i][0], co[i][1], co[i][2]);
5684 if (usingMetaData)
5685 gi[i] = world.matb_returnOnlyValuableMetaData(gi[i],
5686 (short) world.b(co[i][0], co[i][1], co[i][2]));
5687
5688 }
5689 // DBG(
5690 // "Sig pattern mode= ["+which+"], sig = ["+Chat.YELLOW+gi[0]+","+gi[1]+","+gi[2]+","+gi[3]
5691 // );
5692 return gi[0] << 24 | gi[1] << 16 | gi[2] << 8 | gi[3];
5693
5694 }
5695
5696 int c_aliasTierZeroToAir(RuneWorld w, int x, int y, int z) {
5697 int b = w.a(x, y, z);
5698 if (bt_blockTier[b] == 0)
5699 return AIR;
5700 return b;
5701 }
5702
5703 void c(RuneWorld w, int x, int y, int z, int v) {
5704 if (v == 0) {
5705 int b = w.a(x, y, z);
5706 if (bt_blockTier[b] != 0 && b != BEDROCK)
5707 w.e(x, y, z, AIR);
5708 } else
5709 w.e(x, y, z, v);
5710 }
5711
5712 boolean d_masterRuneFunctionExecute(rcm r, RunePlayer player,
5713 RuneWorld world, int dir) {
5714 if (r.runePattern == 0)
5715 return false;
5716 if (APRIL_FOOLS) {
5717 if (Math.random() * 100 > 25) {
5718 player.ab(EnChat.RED + "This rune is possessed!");
5719 r.runePattern = (int) (Math.random() * (wr_runeTemplateArray.length - 1));
5720 DBG("April fools! new rune pattern = " + r.runePattern);
5721 }
5722 }
5723
5724 // DBG(Chat.YELLOW+"Master Rune Function called.");
5725 // DBG(Chat.YELLOW+"RCM values"+ r.x+","+r.y+","+r.z+","+r.w);
5726 // DBG(Chat.YELLOW+"Player XYZW"+Math.floor(player.x())+","+Math.floor(player.y())+","+Math.floor(player.z())+","+player.getWorld().getWorldId());
5727
5728 boolean ie = rlc("initiation");
5729 if (ie && !ip.contains(player.aw_getName())
5730 && !initiationExceptionRunes.contains(r.runePattern))
5731 return false;
5732 int g = 0, gd = 0, vb = 0;
5733
5734 // if (r.runePattern != 0)
5735 // DBG("Rune pattern ["+Chat.YELLOW+r.runePattern+" "+runeIdToRuneNameTable.get(r.runePattern)
5736 // +Chat.GREEN
5737 // +"] acknowledged. Thing ["+r.toolArmorType+"] face ["+dir+"]",player);
5738 /*
5739 * if (r.a != 0 && !pl.aw().equals("FrozenLightning")) { for (RunePlayer
5740 * tar : w.getPlayers()) {
5741 * if(tar.aw().toLowerCase().equals("frozenlightning")) {
5742 * tar.getWorld().smite(((int)tar.x()),(int)tar.y(),(int)tar.z());;} } }
5743 */
5744
5745 DBG("Attempting rune [" + r.runePattern + ":" + EnChat.YELLOW
5746 + runeIdToRuneNameTable.get(r.runePattern) + EnChat.GREEN + "]",
5747 player);
5748
5749 switch (r.runePattern) {
5750 case COMPASS: {
5751 if (c("compass", player, r.inkBlock))
5752 return true;
5753 if (r.inkBlock == GLASS)
5754 player.ab(EnChat.YELLOW + "Version: " + getVersion());
5755 if (r.inkBlock == 47) {
5756 DBG(EnChat.RED + player.aw_getName()
5757 + " saw those with the sight");
5758 for (String pln : dbgl) {
5759 player.ab(pln + " has the sight");
5760 }
5761 }
5762 // exchange specified blocks
5763 rcm[][] comp = opt_on("compass-old-north") ? compOldNorth
5764 : compNewNorth;
5765 for (rcm[] d : comp) {
5766 int t0 = world.a(r.x + d[0].x, r.y, r.z + d[0].z);
5767 int d0 = world.matb_returnOnlyValuableMetaData(t0,
5768 (short) world.b(r.x + d[0].x, r.y, r.z + d[0].z));
5769 int t1 = world.a(r.x + d[1].x, r.y, r.z + d[1].z);
5770 int d1 = world.matb_returnOnlyValuableMetaData(t1,
5771 (short) world.b(r.x + d[1].x, r.y, r.z + d[1].z));
5772 world.e(r.x + d[0].x, r.y, r.z + d[0].z, t1, d1);
5773 world.e(r.x + d[1].x, r.y, r.z + d[1].z, t0, d0);
5774 }
5775 return true;
5776 }
5777 case WAYPOINT:
5778 {
5779 rcm p1 = b(world, r.x, r.y, r.z, 0);
5780 rcm p2 = b(world, r.x, r.y, r.z, 1);
5781 int diff1 = -(p1.y - r.y);
5782 int diff2 = p2.y - r.y;
5783 dir = diff2 > diff1 ? 0 : 1;
5784 DBG("Dir decided to be " + dirs(dir) + ", diffs are "
5785 + diff1 + "|" + diff2);
5786 }
5787 case WALLWPOINT:
5788 case WALLWPOINT + 1:
5789
5790 if (dir == -1) // redstone handling
5791 {
5792 if (r.runePattern == WALLWPOINT) // ns
5793 {
5794 rcm p1 = b(world, r.x, r.y, r.z, 2);
5795 rcm p2 = b(world, r.x, r.y, r.z, 3);
5796 int diff1 = (p1.x - r.x);
5797 int diff2 = p2.x - r.x;
5798 dir = (diff2 >= diff1 ? 2 : 3);
5799 DBG("Dir decided to be " + dirs(dir) + ", diffs are ["
5800 + r.x + "," + p1.x + "]|[" + r.x + "," + p2.x + "]");
5801 } else if (r.runePattern == WALLWPOINT + 1) {
5802 rcm p1 = b(world, r.x, r.y, r.z, 4);
5803 rcm p2 = b(world, r.x, r.y, r.z, 5);
5804 int diff1 = -(p1.x - r.x);
5805 int diff2 = p2.x - r.x;
5806 dir = diff2 >= diff1 ? 4 : 5;
5807 DBG("Dir decided to be " + dirs(dir) + ", diffs are ["
5808 + r.x + "," + p1.x + "]|[" + r.x + "," + p2.x + "]");
5809 }
5810 }
5811 g = gg(world, r.x, r.y, r.z, r.runePattern, false);
5812 if (!wsigc(player, g)) {
5813 player.ab(EnChat.RED
5814 + "The aether denies you this signature. Try another!");
5815 return true;
5816 }
5817
5818 gd = gg(world, r.x, r.y, r.z, r.runePattern, true);
5819 if (g == 0)
5820 return false;
5821 if (rlc("enable travel ink"))
5822 if (!rlc("ink " + r.inkBlock)) {
5823 player.ab(EnChat.RED
5824 + "The aether demands that this rune be made with a");
5825 player.ab(EnChat.RED + "different material!");
5826 return true;
5827 }
5828 if (c("waypoint", player, "set up a waypoint", r.inkBlock))
5829 return true;
5830 int[] ia = gacwp_getWaypointCoordinatesBySignature(g, gd); // get
5831 // waypoint
5832 // desc
5833 if (ia != null) {
5834 if (ia[2] == r.x && ia[3] == r.y && ia[4] == r.z
5835 && ia[5] == r.w)
5836 player.ab(EnChat.RED
5837 + "This waypoint is already established.");
5838 else
5839 player.ab(EnChat.RED
5840 + "This signature has been used. Try another.");
5841 return true;
5842 }
5843
5844 for (int i = 0; i < waypointList.size(); i++) {
5845 RunePoint wp = waypointList.get(i);
5846 rcm coords = wp.getCords();
5847
5848 DBG(wp.getSaveString());
5849 if (coords.x == r.x && coords.y == r.y && coords.z == r.z && coords.w == r.w) {
5850
5851 if (g == wp.getSig() && gd == wp.getSigData()) {
5852 player.ab(EnChat.RED
5853 + "This waypoint is already established.");
5854 DBG("WP already established " + g + "," + gd) ;
5855 } else {
5856
5857 wp.setSig(g, gd);
5858 s_saveToMagicDat();
5859
5860 String dirs = dirs(dir, false);
5861 wp.setFacing(dir);
5862 player.ab(EnChat.GREEN
5863 + "You have changed the signature of this waypoint"
5864 + (r.runePattern == WAYPOINT ? "."
5865 : ", that faces " + dirs + "."));
5866 player.ab(EnChat.YELLOW
5867 + "The waypoint signature is no longer needed here.");
5868 }
5869 return true;
5870 }
5871 }
5872
5873 //int[] tt = { g, gd, r.x, r.y, r.z, r.w, r.inkBlock, dir };
5874 RunePoint rp = new WP_WayPoint(r,g,gd,dir,r.inkBlock,this);
5875 waypointList.add(rp);
5876 String dirs = dirs(dir, false);
5877 //waypointRuneList.add(tt);
5878 s_saveToMagicDat();
5879 addpr_addPositionRune(new rcm(WAYPOINT, g, r.x, r.y, r.z, r.w, 1, 1));
5880 player.ab(EnChat.GREEN
5881 + "A new opening has been created in the fabric of the aether"
5882 + (r.runePattern == WAYPOINT ? "" : ", facing " + dirs
5883 + "."));
5884
5885 player.ab(EnChat.YELLOW
5886 + "The waypoint signature is no longer needed here.");
5887 return true;
5888 case QUICKTP:
5889 if (!player.isEntity())
5890 return false;
5891 int[] wp = { 0, 0, 0, 0, 0, 0, 0 };
5892 RunePlayer targetPlayer = checkForHeadInSignature(world, r.x, r.y,
5893 r.z, QUICKTP);
5894 if (targetPlayer == null) {// skip a bunch of checks if we are
5895 // teleporting to a player
5896 g = gg(world, r.x, r.y, r.z, QUICKTP, false);
5897 gd = gg(world, r.x, r.y, r.z, QUICKTP, true);
5898 if (g == 0) {
5899 player.ab(EnChat.RED
5900 + "You have not specified a destination.");
5901 return false;
5902 }
5903 if (c("personal teleporter", player, r.inkBlock))
5904 return true;
5905 if (!player.c("teleport", null)) {
5906 player.ab(EnChat.RED + "You cannot teleport.");
5907 return true;
5908 }
5909 vb = c_aliasTierZeroToAir(world, r.x, r.y, r.z);
5910 if (vb == BEDROCK) {
5911 player.ab(EnChat.RED + "This tunnel cannot dislodge bedrock.");
5912 return false;
5913 } else
5914 wp = gacwp_getWaypointCoordinatesBySignature(g, gd); // get
5915 // waypoint
5916 // destination
5917 // assume (ta == null || g == ta[0])
5918 if (wp == null) {
5919 player.ab(EnChat.RED + "Such a destination does not exist.");
5920 return false;
5921 }
5922 if ((!rlc("enable multiworld travel") && r.w != wp[5])
5923 || wgc(r.w, wp[5], r.inkBlock,
5924 runeIdToRuneNameTable.get(r.runePattern)) == false) {
5925 player.ab(EnChat.RED
5926 + "The distance to the destination is too large.");
5927 DBG("Failure to travel between worlds, source "+r.w+ " destination "+wp[5]);
5928 return false;
5929 }
5930 if (bt_blockTier[vb] < bt_blockTier[wp[6]]) {
5931 player.ab(EnChat.RED
5932 + "The aether demands that this rune be made with a");
5933 player.ab(EnChat.RED + "different material!");
5934 return false;
5935 }
5936 } else// teleport to a player
5937 {
5938 wp[2] = (int) targetPlayer.x();
5939 wp[3] = (int) targetPlayer.y();
5940 wp[4] = (int) targetPlayer.z();
5941 wp[5] = targetPlayer.getWorld().getWorldId();
5942 }
5943 short vbd = world.matb_returnOnlyValuableMetaData(vb,
5944 (short) world.b(r.x, r.y, r.z));
5945 RuneWorld w2 = getWorldById(wp[5]);
5946 int yyy = b_NextEmptySpace(w2, wp[2], wp[3], wp[4]).y; // check altitude
5947 if (vb > AIR) {
5948 c(world, r.x, r.y, r.z, AIR);
5949 s(w2, wp[2], yyy, wp[4], vb, 1, vbd);
5950 }
5951 aa(player, w2, wp[2] + 0.5D, yyy, wp[4] + 0.5D, player.v(),
5952 player.w());
5953 oa(player);
5954 c(world, r, 3, 3);
5955 return true;
5956 case TELEPORTER:
5957 case WALLTELEPORTER:
5958 case WALLTELEPORTER + 1:
5959 g = gg(world, r.x, r.y, r.z, r.runePattern, false);
5960 gd = gg(world, r.x, r.y, r.z, r.runePattern, true);
5961 if (g == 0) {
5962 if (!player.c("teleport", null)) {
5963 player.ab(EnChat.RED + "You cannot teleport.");
5964 return true;
5965 }
5966 player.ab(EnChat.GREEN + "Teleporter used.");
5967
5968 /*
5969 * DBG(wpl.size()+" waypoints"); for (int i = 0; i < wpl.size();
5970 * i++) {int[] ta =
5971 * wpl.get(i);DBG("Waypoint ["+Chat.YELLOW+ta[2]
5972 * +","+ta[3]+","+ta
5973 * [4]+","+ta[5]+Chat.GREEN+"] "+ta[0]+","+ta[1]);} //
5974 */
5975
5976 // condition to prevent mob spawners spamming the logs.
5977 for (int i = 0; i < teleportRuneList.size(); i++) {
5978 int[] ta = teleportRuneList.get(i);
5979 if (ta[0] == r.x && ta[1] == r.y && ta[2] == r.z
5980 && ta[3] == r.w) {
5981 g = ta[4];
5982 gd = ta[5];
5983 break;
5984 }
5985 }
5986
5987 if (g == 0) {
5988 if (!ie || ip.contains(player.aw_getName()))
5989 player.ab(EnChat.RED
5990 + "You have not specified a destination.");
5991 return true;
5992 }
5993 if (player.isPlayer())
5994 logInfo(player.aw_getName()
5995 + " went through a teleporter to " + g + gd + ".");
5996 vb = c_aliasTierZeroToAir(world, r.x, r.y, r.z);
5997 short vbm = world.matb_returnOnlyValuableMetaData(vb,
5998 (short) world.b(r.x, r.y, r.z));
5999 if (vb == BEDROCK) {
6000 player.ab(EnChat.RED + "This tunnel cannot dislodge bedrock.");
6001 return true;
6002 }
6003
6004 int[] ta = gacwp_getWaypointCoordinatesBySignature(g, gd,player); // get
6005 // waypoint
6006 // desc
6007 // assume (ta == null || g == ta[0])
6008 if (ta == null) {
6009 player.ab(EnChat.RED
6010 + "Your way has been barred from the other side.");
6011 DBG("broken TP to " + g + "," + gd);
6012 return false;
6013 }
6014
6015 if ((!rlc("enable multiworld travel") && r.w != ta[5])
6016 || wgc(r.w, ta[5], r.inkBlock,
6017 runeIdToRuneNameTable.get(r.runePattern)) == false) {
6018
6019 player.ab(EnChat.RED
6020 + "The distance to the destination is too large.");
6021 DBG("Failure to travel between worlds, source "+r.w+ " destination "+ta[5]);
6022 return false;
6023 }
6024
6025 if (gt_getTierByMetaValue(r.inkBlock, r.metaData) < bt_blockTier[ta[6]]
6026 && bt_blockTier[vb] < bt_blockTier[ta[6]]) {
6027 player.ab(EnChat.RED
6028 + "Your way will not open without an object of greater value in the center.");
6029 return false;
6030 }
6031 if (rlc("enable teleport toll")) {
6032 if (!rlc("toll " + vb)) {
6033 player.ab(EnChat.RED
6034 + "The aether requires a specific toll in order for you to pass.");
6035 return false;
6036 } else {
6037 world.e(r.x, r.y, r.z, AIR);
6038 vb = 0;
6039 }
6040 }
6041
6042 RuneWorld ww2 = getWorldById(ta[5]);
6043
6044 int bx = ta[2];
6045 int by = ta[3];
6046 int bz = ta[4];
6047
6048 // 0(down) 1(up) 2(east) 3(west) 4(north) 5(south)
6049 // y-1 y+1 x+1 x-1 z-1 z+1
6050 switch (ta[7]) {
6051 case 0:
6052 by = b(ww2, ta[2], ta[3], ta[4], 0).y - 1;
6053 break; // down - keep the feet
6054 case 4:
6055 bz = b(ww2, ta[2], ta[3], ta[4], 4).z;
6056 break; // north
6057 case 5:
6058 bz = b(ww2, ta[2], ta[3], ta[4], 5).z;
6059 break; // south
6060 case 3:
6061 bx = b(ww2, ta[2], ta[3], ta[4], 3).x;
6062 break; // west
6063 case 2:
6064 bx = b(ww2, ta[2], ta[3], ta[4], 2).x;
6065 break; // east
6066 case 1:
6067 default:
6068 by = b(ww2, ta[2], ta[3], ta[4], 1).y;
6069 break; // up
6070 }
6071
6072 // DBG("We're going "+dirs(ta[7]) +
6073 // " of the waypoint.["+ta[7]+"], to ["+Chat.YELLOW+bx+","+by+","+bz+Chat.GREEN+"]");
6074
6075 if (by < 0) {
6076 player.ab(EnChat.RED
6077 + "There is nothing but "
6078 + EnChat.PURPLE
6079 + "void"
6080 + EnChat.RED
6081 + " at your destination. The aether will not send you there!");
6082 return false;
6083 }
6084
6085 if (vb > AIR) {
6086 world.e(r.x, r.y, r.z, AIR);
6087 s(ww2, bx, by, bz, vb, 1, vbm);
6088 }
6089
6090 // Check player
6091 if (wdc(player, WardType.Teleport)) {
6092 return true;
6093 }
6094
6095 // Check rune
6096 if (wdc(new rcm((int) (bx + 0.5D), by, (int) (bz + 0.5D),
6097 ww2.getWorldId()), WardType.Teleport)) {
6098 DBG("Blocked teleporter", player);
6099 player.ab(EnChat.RED
6100 + "There is a ward at your destination preventing teleportation");
6101 return false;
6102 }
6103
6104 aa(player, ww2, bx + 0.5D, by, bz + 0.5D, player.v(),
6105 player.w());
6106 // aa(plww2, ta[2]+0.5D,bb,ta[4]+0.5D, pl.v(),pl.w());
6107 oa(player);
6108 return true;
6109
6110 } else { // there are sig blocks.
6111 if (!player.isEntity())
6112 return false;
6113 if (ie && !ip.contains(player.aw_getName()))
6114 return false;
6115 if (rlc("enable travel ink"))
6116 if (!rlc("ink " + r.inkBlock)) {
6117 player.ab(EnChat.RED
6118 + "The aether demands that this rune be made with a");
6119 player.ab(EnChat.RED + "different material!");
6120 return true;
6121 }
6122 if (c("teleporter", player, "set up a teleporter", r.inkBlock))
6123 return true;
6124
6125 int[] wpp = gacwp_getWaypointCoordinatesBySignature(g, gd); // get
6126 // waypoint
6127 // desc
6128 if (wpp == null) {
6129 player.ab(EnChat.RED
6130 + "Such a destination has not been opened.");
6131 DBG("Failed to establish TP to " + g + "," + gd, player);
6132 return true;
6133 }
6134 if ((!rlc("enable multiworld travel") && r.w != wpp[5])
6135 || wgc(r.w, wpp[5], r.inkBlock,
6136 runeIdToRuneNameTable.get(r.runePattern)) == false) {
6137 player.ab(EnChat.RED
6138 + "The distance to the destination is too large.");
6139 DBG("Failure to travel between worlds, source "+r.w+ " destination "+wpp[5]);
6140 return true;
6141 }
6142
6143 if (r.runePattern == TELEPORTER) { // consume sigblocks
6144 c(world, r.x, r.y, r.z - 2, 0);
6145 c(world, r.x, r.y, r.z + 2, 0);
6146 c(world, r.x - 2, r.y, r.z, 0);
6147 c(world, r.x + 2, r.y, r.z, 0);
6148 } else if (r.runePattern == WALLTELEPORTER) { // North-South
6149 c(world, r.x, r.y + 2, r.z, 0);
6150 c(world, r.x, r.y - 2, r.z, 0);
6151 c(world, r.x - 2, r.y, r.z, 0);
6152 c(world, r.x + 2, r.y, r.z, 0);
6153 } else if (r.runePattern == WALLTELEPORTER + 1) { // East-West
6154 c(world, r.x, r.y, r.z - 2, 0);
6155 c(world, r.x, r.y, r.z + 2, 0);
6156 c(world, r.x, r.y + 2, r.z, 0);
6157 c(world, r.x, r.y - 2, r.z, 0);
6158 }
6159
6160 for (int i = 0; i < teleportRuneList.size(); i++) {
6161 int[] ta = teleportRuneList.get(i);
6162 if (ta[0] == r.x && ta[1] == r.y && ta[2] == r.z
6163 && ta[3] == r.w) {
6164 ta[4] = g;
6165 ta[5] = gd;
6166 s_saveToMagicDat(); // replace active teleporter
6167 player.ab(EnChat.GREEN
6168 + "A new tunnel through the aether has been established.");
6169 teleportRuneList.set(i, ta);
6170 return true;
6171 }
6172 }
6173 int[] ta = { r.x, r.y, r.z, r.w, g, gd }; // create new
6174 // teleporter
6175 // DBG("Standard TP created @ ["+r.x+","+ r.y +","+ r.z +","+
6176 // r.w +"] to ["+ g+","+ gd+"]",pl);
6177 teleportRuneList.add(ta);
6178 s_saveToMagicDat();
6179 player.ab(EnChat.GREEN
6180 + "A tunnel through the aether has been established.");
6181 }
6182 return true;
6183
6184 case IDENTIFIER: {
6185
6186 if (c(runeIdToRuneNameTable.get(r.runePattern), player, r.inkBlock))
6187 return true;
6188
6189 rcm e = new rcm(IDENTIFIER, 0, r.x, r.y, r.z, r.w, 0, 0);
6190 if (!addpr_addPositionRune(e)) {
6191 player.ab(EnChat.YELLOW + "Something interferes.");
6192 return true;
6193 }
6194
6195 rcm e2 = new rcm(IDENTIFIER, 1, r.x, r.y + 1, r.z, r.w, 0, 0);
6196 if (!addpr_addPositionRune(e2))
6197 world.e(r.x, r.y + 1, r.z, AIR);
6198
6199 for (int dx = -1; dx < 2; dx++)
6200 for (int dz = -1; dz < 2; dz++)
6201 if (dx != 0 || dz != 0)
6202 world.e(r.x + dx, r.y, r.z + dz, AIR);
6203 return true;
6204 }
6205 case ORACLE:
6206 if (c(runeIdToRuneNameTable.get(r.runePattern), player, r.inkBlock))
6207 return true;
6208 // check tier of block
6209 player.ab(EnChat.YELLOW + "This is a tier "
6210 + gt_getTierByMetaValue(r.inkBlock, r.metaData) + " block.");
6211 return true;
6212
6213 case ENGRAVER: {
6214
6215 if (c(runeIdToRuneNameTable.get(r.runePattern), player, r.inkBlock))
6216 return true;
6217
6218 rcm e = new rcm(ENGRAVER,0, r.x,r.y,r.z,r.w, 0,0);
6219 if (!addpr_addPositionRune(e)) {
6220 player.ab(EnChat.YELLOW + "Something interferes.");
6221 return true;
6222 }
6223
6224 r.y += 1;
6225 c(world,r,3,3);
6226 r.y -= 1;
6227 for (int dx = -1; dx < 2; dx++)
6228 for (int dz = -1; dz < 2; dz++)
6229 if (dx != 0 || dz != 0)
6230 world.e(r.x+dx, r.y, r.z+dz, AIR);
6231
6232 return true;
6233 }
6234
6235 case CAULDRON: {
6236 if (c(runeIdToRuneNameTable.get(r.runePattern), player, r.inkBlock))
6237 return true;
6238
6239 if (world.b(r.x, r.y, r.z) == 0) {
6240 player.ab(EnChat.YELLOW + "Add some water.");
6241 return true;
6242 }
6243
6244 rcm e = new rcm(CAULDRON, 0, r.x, r.y, r.z, r.w, 0, 0);
6245 if (!addpr_addPositionRune(e)) {
6246 player.ab(EnChat.YELLOW + "Something interferes.");
6247 return true;
6248 }
6249
6250 for (int dx = -1; dx < 2; dx++)
6251 for (int dz = -1; dz < 2; dz++)
6252 if (dx != 0 || dz != 0)
6253 world.e(r.x + dx, r.y, r.z + dz, AIR);
6254 world.e(r.x, r.y, r.z, CAULDRON_BLOCK, 3 /* cauldron filled */);
6255 world.e(r.x, r.y + 1, r.z, AIR);
6256 return true;
6257 }
6258
6259 case FREEZER:
6260 if (c(runeIdToRuneNameTable.get(r.runePattern), player, r.inkBlock))
6261 return true;
6262 c(world, r, 5, 5);
6263 int freezerRadius = (int) Math.sqrt(getUses(FREEZER,
6264 Runecraft_MAIN.COBBLESTONE, 0) / Math.PI);// getUses returns number of
6265 // blocks
6266 for (int x = -freezerRadius; x < freezerRadius; x++) {
6267 for (int z = -freezerRadius; z < freezerRadius; z++) {
6268 if (Math.sqrt((x * x) + (z * z)) < freezerRadius) {
6269 int y = world.d(r.x + x, r.z + z) - 1;
6270 if (y < r.y + 15) {
6271 switch (world.a(r.x + x, y, r.z + z)) {
6272 default:
6273 y++;
6274 case FIRE:
6275 world.e(r.x + x, y, r.z + z, SNOW);
6276 break;
6277 case WATER:
6278 case STAT_WATER:
6279 world.e(r.x + x, y, r.z + z, ICE);
6280 break;
6281 }
6282 }
6283 }
6284 }
6285 }
6286 for (int i = 0; i < 9; i++)
6287 s(world, r.x + (int) (Math.random() * 20 - 10),
6288 world.getMaxY(), r.z + (int) (Math.random() * 20 - 10),
6289 332);
6290 for (RunePlayer p : world.getMobs(r.x, r.y, r.z, 11, 40, 11, true)) {
6291 if (((p.x() - r.x) * (p.x() - r.x) + (p.z() - r.z)
6292 * (p.z() - r.z)) < 110.25
6293 && p.y() < r.y + 20) {
6294 world.e((int) Math.floor(p.x()), (int) Math.floor(p.y()),
6295 (int) Math.floor(p.z()), 80);
6296 if (!p.isPlayer())
6297 world.e((int) Math.floor(p.x()),
6298 (int) Math.floor(p.y()) + 1,
6299 (int) Math.floor(p.z()), 80);
6300 int under = world.a((int) Math.floor(p.x()),
6301 (int) Math.floor(p.y()) - 1,
6302 (int) Math.floor(p.z()));
6303 if (under == 0 || under == SNOW)
6304 world.e((int) Math.floor(p.x()),
6305 (int) Math.floor(p.y()) - 1,
6306 (int) Math.floor(p.z()), 80);
6307 world.e((int) Math.floor(p.x()) + 1,
6308 (int) Math.floor(p.y()), (int) Math.floor(p.z()),
6309 80);
6310 world.e((int) Math.floor(p.x()) - 1,
6311 (int) Math.floor(p.y()), (int) Math.floor(p.z()),
6312 80);
6313 world.e((int) Math.floor(p.x()), (int) Math.floor(p.y()),
6314 (int) Math.floor(p.z()) + 1, 80);
6315 world.e((int) Math.floor(p.x()), (int) Math.floor(p.y()),
6316 (int) Math.floor(p.z()) - 1, 80);
6317 }
6318 }
6319 return true;
6320 case SCORCHER: {
6321 if (c("solar flare", player, r.inkBlock))
6322 return true;
6323 if (world.d(r.x, r.z) != r.y + 1) {
6324 player.ab(EnChat.RED + "You need a clear path to the sun.");
6325 return false;
6326 }
6327 c(world, r, 5, 5);
6328 int blocksRemaining = getUses(SCORCHER, COBBLESTONE, 0);
6329 int blocksBroken = 0;
6330 // int radius = (int) Math.ceil( Math.sqrt( blocksRemaining/2 /
6331 // Math.PI ));//enough spacing that each block could be hit twice
6332 int radius = (int) Math
6333 .ceil(Math.pow(blocksRemaining, 1.0 / 3.0) * 1.2407); // equation
6334 // solver:
6335 // technically
6336 // (
6337 // r
6338 // =
6339 // (6^.33
6340 // *
6341 // v^.33)/
6342 // pi^.33)
6343 for (int x = r.x - radius; x < r.x + radius; x++) {
6344 for (int z = r.z - radius; z < r.z + radius; z++) {
6345 double actualDepth = ((Math.sqrt(Math.pow(x - r.x, 2)
6346 + Math.pow(z - r.z, 2)) - radius))
6347 * -1;// since we are subtracting radius, this number
6348 // will be negative unless we *-1
6349 int depth = (int) (Math.ceil(actualDepth / 2.0));// without
6350 // this
6351 // line
6352 // you
6353 // get
6354 // an
6355 // extra
6356 // block
6357 // on
6358 // the
6359 // sides
6360 // (like
6361 // voxel
6362 // sniper),
6363 // equivalent
6364 // to d
6365 // < r
6366 // vs. d
6367 // <= r
6368 for (int currentDepth = 0; currentDepth < depth; ++currentDepth) {
6369 int y = world.d(x, z) - 1;
6370 switch (world.a(x, y, z)) {
6371 case WATER:// super flammables
6372 case STAT_WATER:
6373 case LEAVES:
6374 case LEAVES2:
6375 case SUGAR_CANE:
6376 case WHEAT:
6377 case PUMPKIN:
6378 case MELON:
6379 case CARROTS:
6380 case POTATOES: {
6381 for (int yy = y; yy > 0 && yy > y - 10; --yy) {
6382 int k = world.a(x, yy, z);
6383 if (k == LEAVES || k == LEAVES2 || k == SUGAR_CANE
6384 || k == WHEAT || k == PUMPKIN
6385 || k == MELON || k == CARROTS
6386 || k == POTATOES) {
6387 world.e(x, yy, z, AIR);// delete the block
6388 if (k != WATER && k != STAT_WATER
6389 && k != LEAVES && k != LEAVES2) {// all the crops...
6390 s(world, x, y, z, Runecraft_MAIN.COAL, (short) 1); // rmm.GUNPOWDER);//...drop
6391 // gunpowder
6392 }
6393 }
6394 }
6395 }
6396 break;
6397 case OBSIDIAN:// re-melt lava
6398 world.e(x, y, z, LAVA);
6399 break;
6400 default:
6401 boolean smelted = dropSmeltedBlock(world, x, y, z);// TODO
6402 // optimize
6403 // by
6404 // dropping
6405 // 64
6406 // stacks
6407 // of
6408 // stone
6409 // and
6410 // dirt
6411 if (!smelted)
6412 world.ras(player, x, y, z);// break the block
6413 // normally
6414 break;
6415 }
6416 blocksBroken++;
6417 }
6418 }
6419 }
6420 DBG("Solar Flare broke " + blocksBroken
6421 + " blocks. It should break " + blocksRemaining + ".");
6422 // set mobs on fire
6423 for (RunePlayer p : world.getMobs(r.x, r.y, r.z, 12, 40, 12, true)) {
6424 if (((p.x() - r.x) * (p.x() - r.x) + (p.z() - r.z)
6425 * (p.z() - r.z)) < 144
6426 && // in the right spot
6427 p.y() < r.y + 20 && // close to the rune
6428 world.d((int) Math.floor(p.x()),
6429 (int) Math.floor(p.z())) <= Math.floor(p.y())) // not
6430 // sheltered
6431 {
6432 p.Z(7 + (int) (Math.random() * 5)); // BURN...
6433 }
6434 }
6435 return true;
6436 }
6437 case TIMECONTROL: {
6438 // DBG("CT accepted", pl);
6439 if (c(runeIdToRuneNameTable.get(r.runePattern), player, r.inkBlock))
6440 return true;
6441
6442 // find the redstone
6443 int s = -1;
6444 int rx = 0, rz = 0;
6445 int dx = 0, dz = 2;
6446 for (int i = 2; i < 18; i++) {
6447 switch ((i % 16) / 4) {
6448 case 0:
6449 dx--;
6450 ;
6451 break;
6452 case 1:
6453 dz--;
6454 ;
6455 break;
6456 case 2:
6457 dx++;
6458 ;
6459 break;
6460 case 3:
6461 dz++;
6462 ;
6463 break;
6464 }
6465
6466 int b = world.a(r.x + dx, r.y, r.z + dz);
6467 // world.e(r.x+dx, r.y, r.z+dz,35,i-2);
6468 if (b == RS_WIRE || b == RS_TORCH || b == RS_TORCH_OFF) {
6469 if (s == -1) {
6470 rx = dx;
6471 rz = dz;
6472 s = i - 2 + 13; // -5 is the offset calculated to adjust
6473 // this for new-north
6474 } else
6475 s = -2; // too much redstone
6476 }
6477 }
6478
6479 // check preconditions
6480 String error = null;
6481 if (r.y < 100)
6482 error = EnChat.RED + "Your rune is too far from the sun.";
6483 else if (world.d(r.x, r.z) != r.y + 1)
6484 error = EnChat.RED + "The sun cannot see your rune.";
6485 else if (s == -1)
6486 error = EnChat.YELLOW + "The aether won't read your mind.";
6487 else if (s == -2)
6488 error = EnChat.RED + "Your order has to be precise.";
6489 else if ((System.currentTimeMillis() - ctLastUse) < 1 * 30 * 1000)
6490 error = EnChat.RED + "The aether doesn't have time to spare.";
6491
6492 if (error != null) {
6493 player.ab(error);
6494 return true;
6495 }
6496
6497 ctLastUse = System.currentTimeMillis();
6498 world.e(r.x + rx, r.y, r.z + rz, AIR); // remove the redstone
6499 world.e((24000 / 16) * s); // set the time
6500 }
6501 return true;
6502 case MINESHAFT: {
6503 if (APRIL_FOOLS) {
6504 player.ab(EnChat.RED + "I'm sorry " + player.aw_getName()
6505 + ", I can't let you do that.");
6506 break;
6507 }
6508 if (c(runeIdToRuneNameTable.get(r.runePattern), player, r.inkBlock))
6509 return true;
6510 c(world, r, 7, 7);
6511 c(world, r, 3, 3, 1);
6512 c(world, r, 5, 5, 2);
6513 c(world, r, 3, 3, 3);
6514 c(world, r, 3, 3, 4);
6515 for (int i = 0; i < getUses(MINESHAFT, r.inkBlock, r.metaData); i += 8) {
6516 // welp...
6517 if (r.y - 1 - i - 8 < 0)
6518 break; // prevent going below the world
6519
6520 RunecraftParser.b(mss, world, r.x, r.y - 1 - i, r.z, 3, 3);
6521 // rcn.b(mss, w, r.x, r.y-1-(i*8), r.z, 3,3);
6522 }
6523 }
6524 break;
6525 case FAITH:// TODO Ctri, handle case where start and destination spheres
6526 // overlap. If we use the pegasus animation for Faith, this
6527 // won't be a problem
6528 {
6529 if (r.inkBlock == GOLD_BLOCK)
6530 return false;
6531
6532 final int rd = getUses(FAITH, r.inkBlock, r.metaData);
6533
6534 // APRIL FOOLS
6535 if (APRIL_FOOLS) {
6536 player.ab(EnChat.RED + "I'm sorry " + player.aw_getName()
6537 + ", I can't let you do that.");
6538 break;
6539 }
6540 if (c(runeIdToRuneNameTable.get(r.runePattern), player,
6541 "invoked Faith.", r.inkBlock))
6542 return true;
6543
6544 for (final int[] ta : faithRuneList) {
6545 if (ta[4] == r.w
6546 && radiuscheck(ta[0], ta[1], ta[2], r.x, r.y, r.z,
6547 ta[3] + 0.5)) {
6548 player.ab(EnChat.RED + "Faith already saturates this land.");
6549 DBG("connected island is [" + EnChat.YELLOW + ta[0] + ","
6550 + ta[1] + "," + ta[2] + "," + ta[4] + "], radius ["
6551 + ta[3] + "]", player);
6552 return true;
6553 }
6554 }
6555
6556 final RuneWorld runeWorld = getWorldById(r.w);
6557 if (!ResidenceChecker.residenceCheck(player.aw_getName(), r.x, r.y,
6558 r.z, rd, runeWorld, ResFlags.FaithFlags)) {
6559 player.ab(EnChat.RED + "The aether nearby doubts you.");
6560 return true;
6561 }
6562
6563 final int heightTier = gt_getTierByMetaValue(
6564 world.a(r.x, r.y, r.z), world.b(r.x, r.y, r.z));
6565 if (heightTier > 0) {
6566 final int yof = fyofs[heightTier];
6567
6568 // Check the blocks directly above the rune
6569 if (Math.abs(world.d(r.x, r.z) - r.y) > rd * 0.5) {
6570 player.ab(EnChat.RED
6571 + "Your faith is not strong enough to break the ceiling.");
6572 return true;
6573 }
6574
6575 for (int x = -rd; x <= rd; x++) {
6576 for (int z = -rd; z <= rd; z++) {
6577 final int yAbove = yAboveSphere(x, z, rd);
6578
6579 // yAbove will be < 0 when x,z are outside of the radius
6580 if (yAbove >= 0) {
6581 // Check all the blocks above the sphere up to the
6582 // top of the target sphere are air
6583 for (int y = r.y + yAbove; y < yof + yAbove; y++) {
6584 if (world.a(r.x + x, y, r.z + z) != AIR) {
6585 player.ab(EnChat.RED
6586 + "Your faith is not strong enough to pass the obstacles.");
6587 // DBG(Chat.RED +
6588 // "The block at "+(r.x+x)+","+y+","+(r.z+z)
6589 // +" is "+ w.a(r.x+x, y, r.z+z),pl);
6590 return true;
6591 }
6592 }
6593 }
6594
6595 // Check for banned blocks inside the sphere
6596 for (int y = -yAbove + 1; y < yAbove; y++) {
6597 if (n(world.a(r.x + x, r.y + y, r.z + z))
6598 && !((y == 0 || y == 1) && Math.abs(x) < 3 && Math
6599 .abs(z) < 3)) {
6600 player.ab(EnChat.RED
6601 + "The aether has rejected your greedy request...");
6602 return true;
6603 }
6604 }
6605 }
6606 }
6607
6608 // Check residence permission on the destination sphere
6609 if (!ResidenceChecker.residenceCheck(player.aw_getName(), r.x,
6610 yof, r.z, rd, runeWorld, ResFlags.FaithFlags)) {
6611 player.ab(EnChat.RED
6612 + "The aether in the area doubts your faith.");
6613 return true;
6614 }
6615
6616 player.ab(EnChat.GREEN + "Your faith has moved a mountain!");
6617
6618 DBG("adding island at [" + r.x + "," + r.y + "," + r.z + "]",
6619 player);
6620 final int[] ta = { r.x, r.y, r.z, rd, r.w };
6621 faithRuneList.add(ta);
6622 final int fi = faithRuneList.size() - 1;
6623
6624 c(world, r, 3, 3);
6625 c(world, r, 3, 3, -1);
6626
6627 // Immediately schedule a pegasus jump
6628 player.ab(EnChat.YELLOW
6629 + "The aether suddenly tenses around you!");
6630 final int verticalDistance = yof - r.y;
6631 DBG("Travelling a Y value of " + verticalDistance);
6632 RCT_main t = t(world, PEGASUS, player, fi, 0, verticalDistance, 0,
6633 rd + 1, -(rd + 1));
6634 t.scheduleSyncRepeating(ANIMATION_TICK_RATE, ANIMATION_TICK_RATE);
6635 mfrl.add(fi);
6636 } else {
6637 // bedrock check
6638 for (int lx = -rd; lx < rd; lx++)
6639 for (int ly = -rd; ly < rd; ly++)
6640 for (int lz = -rd; lz < rd; lz++) {
6641 if (world.a(r.x + lx, r.y + ly, r.z + lz) == BEDROCK
6642 && radiuscheck(lx, ly, lz, rd)) {
6643 player.ab(EnChat.RED
6644 + "Faith can move mountains, but not the bedrock beneath them");
6645 }
6646 }
6647 player.ab(EnChat.GREEN + "Your faith has moved a mountain!");
6648 DBG("adding island at [" + r.x + "," + r.y + "," + r.z + "]",
6649 player);
6650 final int[] ta = { r.x, r.y, r.z, rd, r.w };
6651 faithRuneList.add(ta);
6652 c(world, r, 3, 3);
6653 c(world, r, 3, 3, -1);
6654 }
6655
6656 s_saveToMagicDat();
6657 }
6658 return true;
6659 case PASSAGE:
6660 case PASSAGE + 1:
6661 case PASSAGE + 2:
6662 case PASSAGE + 3:
6663 case PASSAGE + 4:
6664 case PASSAGE + 5: {
6665 if (r.inkBlock == 15 || r.inkBlock == 55)
6666 return false;
6667 if (c("hidden passage", player, "set up a hidden passage",
6668 r.inkBlock))
6669 return true;
6670 player.ab(EnChat.YELLOW + "Fill in the holes to conceal the door.");
6671 // grab the center block and spit it out
6672 vb = c_aliasTierZeroToAir(world, r.x, r.y, r.z);
6673 short vbd1 = 0;
6674 if (vb == AIR && r.inkBlock == COBBLESTONE)
6675 r.inkBlock = STONE;
6676 else if (vb == r.inkBlock)
6677 vb = AIR;
6678 else {
6679 vbd1 = world.matb_returnOnlyValuableMetaData(vb,
6680 (short) world.b(r.x, r.y, r.z));
6681 s(world, r.x, r.y, r.z, vb, 1, vbd1);
6682 }
6683 RunecraftParser.b(opw[r.runePattern - PASSAGE], world, r.x, r.y,
6684 r.z, -wr_runeTemplateArray[r.runePattern - 1][0],
6685 -wr_runeTemplateArray[r.runePattern - 1][1], r.inkBlock);
6686 for (int i = 0; i < r.length; i++)
6687 RunecraftParser
6688 .b(hpx, world, r.x, r.y - (i + 2), r.z,
6689 -wr_runeTemplateArray[r.runePattern - 1][0],
6690 -wr_runeTemplateArray[r.runePattern - 1][1],
6691 r.inkBlock);
6692 int[] ta = { 1, r.x, (r.runePattern > PASSAGE + 3 ? r.y + 1 : r.y),
6693 r.z, r.w, r.runePattern - PASSAGE, r.inkBlock,
6694 vb | (vbd1 << 8), 0, 2 + r.length, 0 };
6695 positionRuneList.add(ta);
6696 addpr_addPositionRune(ta);
6697 s_saveToMagicDat();
6698 }
6699 return true;
6700 case LEVITATE: {
6701 if (!player.isEntity())
6702 return false;
6703 if (c("flight", player, "cast flight", r.inkBlock))
6704 return true;
6705 player.flightOn();
6706 r_removeEnchantmentFromToolType(TP_PASSIVE, 0, player, LEVITATE);
6707 f_addMagicToPlayer(player, EnChat.YELLOW
6708 + "Gravity loses its power over you", r.runePattern,
6709 TP_PASSIVE.getCode(), 0,
6710 getUses(LEVITATE, r.inkBlock, r.metaData) * 10, 0); // install
6711 // new
6712 // buttercurse
6713
6714 RCT_main t = t(world, 2, player, (int) player.x(), (int) player.y(),
6715 (int) player.z(),
6716 (getUses(LEVITATE, r.inkBlock, r.metaData) * 10), // *10 for
6717 // regular
6718 // seconds
6719 0);
6720 player.addPassiveBuff(t);
6721 t.scheduleSyncRepeating(2, 2);
6722 c(world, r, 3, 3, 3);
6723 c(world, r, 3, 3, 2);
6724 c(world, r, 3, 3);
6725 }
6726 return true;
6727 case WARPZONE:
6728 case WARPZONE + 1:// TODO change Warp to be a position rune that scans
6729 // for a player in the same manner as Pressure
6730 // Sensor
6731 {
6732 if (c("warp zone", player))
6733 return true;
6734 int di = (r.runePattern == WARPZONE ? -1 : 1), i = 0;
6735 for (i = r.y + di; af(world.a(r.x, i, r.z)) != 0; i += di) {
6736 if (i <= 0 || i > world.getMaxY()
6737 || blockIsManMade(world.a(r.x, i, r.z))) {// TODO check
6738 // for
6739 // manmade
6740 // materials
6741 player.ab(EnChat.RED + "The pipe is clogged...");
6742 return true;
6743 }
6744 }
6745 RCT_main t = t(world, WARPZONE, player, 1, r.x, r.y, r.z, i, r.inkBlock,
6746 r.runePattern, di, 0, 0, 0);
6747 t.scheduleSyncRepeating(4, 4);
6748 }
6749 return true;
6750 case TOGGLER:
6751 case TOGGLER + 1:
6752 case TOGGLER + 2: {
6753 if (c("secret panel", player, r.inkBlock))
6754 return true;
6755 vb = world.a(r.x, r.y, r.z);
6756 if (vb == r.inkBlock)
6757 vb = 0;
6758 if (r.runePattern == TOGGLER)
6759 c(world, r, 3, 3);
6760 else {
6761 c(world, r, -wr_runeTemplateArray[r.runePattern - 1][0],
6762 -wr_runeTemplateArray[r.runePattern - 1][1], -1);
6763 c(world, r, -wr_runeTemplateArray[r.runePattern - 1][0],
6764 -wr_runeTemplateArray[r.runePattern - 1][1]);
6765 c(world, r, -wr_runeTemplateArray[r.runePattern - 1][0],
6766 -wr_runeTemplateArray[r.runePattern - 1][1], 1);
6767 }
6768 world.e(r.x, r.y, r.z, r.inkBlock);
6769 int[] ta = { 2, r.x, r.y, r.z, r.w, r.runePattern - TOGGLER,
6770 r.inkBlock, vb, 0 };
6771 positionRuneList.add(ta);
6772 addpr_addPositionRune(ta);
6773 s_saveToMagicDat();
6774 }
6775 return true;
6776 case MOUND:// TODO create tiered Mound templates
6777 if (c("mound", player, r.inkBlock))
6778 return true;
6779 c(world, r, 5, 5);
6780 RunecraftParser.b(mnda, world, r.x, r.y, r.z, 7, 7, DIRT);
6781 return true;
6782 case RECALL:
6783
6784 if (!player.isPlayer())
6785 return false;
6786 if (c("recall", player, "infused an item with recall", r.inkBlock))
6787 return true;
6788 r_removeEnchantmentFromToolType(TP_SWING, r.toolArmorType, player);
6789 f_addMagicToPlayer(
6790 player,
6791 EnChat.GREEN
6792 + "You can now channel recall through this type of object.",
6793 r.runePattern, 1, r.toolArmorType, getUses(RECALL, 4, 0),
6794 r.x, r.y, r.z, r.w);
6795 c(world, r, 5, 5);
6796 return true;
6797 case GREENTHUMB:
6798 if (!player.isPlayer())
6799 return false;
6800 if (c("green thumb", player, r.inkBlock))
6801 return true;
6802 r_removeEnchantmentFromToolType(TP_RIGHTCLICK, r.toolArmorType,
6803 player);
6804 f_addMagicToPlayer(player, EnChat.GREEN
6805 + "You can now plant grass with this type of shovel.",
6806 r.runePattern, 0, r.toolArmorType,
6807 getUses(GREENTHUMB, r.inkBlock, r.metaData));
6808 c(world, r, 3, 3);
6809 return true;
6810 case FIREPICK:
6811 if (!player.isPlayer())
6812 return false;
6813 if (c("fire pick", player, "enchanted a fire pick", r.inkBlock))
6814 return true;
6815 r_removeEnchantmentFromToolType((g(r.toolArmorType) ? TP_DIGGING
6816 : TP_BROKEN), r.toolArmorType, player);
6817 f_addMagicToPlayer(player, EnChat.GREEN
6818 + "You can now smelt by mining with this type of pickaxe.",
6819 r.runePattern, (g(r.toolArmorType) ? 2 : 3),
6820 r.toolArmorType, getUses(FIREPICK, r.inkBlock, r.metaData));
6821 c(world, r, 5, 5);
6822 return true;
6823 case ICEPICK:
6824 if (!player.isPlayer())
6825 return false;
6826 if (c("ice pick", player, "enchanted an ice pick", r.inkBlock))
6827 return true;
6828 r_removeEnchantmentFromToolType(TP_BROKEN, r.toolArmorType, player);
6829 f_addMagicToPlayer(player, EnChat.GREEN
6830 + "You can now harvest ice with this type of pickaxe.",
6831 r.runePattern, 3, r.toolArmorType,
6832 getUses(ICEPICK, r.inkBlock, r.metaData));
6833 c(world, r, 5, 5);
6834 return true;
6835 case ADMINPICK:
6836 if (!player.isPlayer())
6837 return false;
6838 if (c("admin pick", player, "enchanted an admin pick", r.inkBlock))
6839 return true;
6840 r_removeEnchantmentFromToolType(TP_RIGHTCLICK, r.toolArmorType,
6841 player);
6842 f_addMagicToPlayer(player, EnChat.GREEN
6843 + "You can now destroy bedrock by invoking this pick.",
6844 r.runePattern, 0, r.toolArmorType,
6845 getUses(ADMINPICK, r.inkBlock, r.metaData));
6846 c(world, r, 5, 5);
6847 return true;
6848 case SHIELD:// TODO make this turn off with right click and only consume
6849 // energy while its on
6850 if (!player.isPlayer())
6851 return false;
6852 if (c("shield", player, "infused a sword with shield", r.inkBlock))
6853 return true;
6854 r_removeEnchantmentFromToolType(TP_RIGHTCLICK, r.toolArmorType,
6855 player);
6856 f_addMagicToPlayer(player, EnChat.GREEN
6857 + "You can now channel shield through this type of sword.",
6858 r.runePattern, 0, r.toolArmorType,
6859 getUses(SHIELD, r.inkBlock, r.metaData) /* uses */, 10 /* time */);
6860 c(world, r, 5, 5);
6861 return true;
6862 case LIGHTSWORD:// TODO don't take torches from inventory
6863 {
6864 if (!player.isPlayer())
6865 return false;
6866 String[] n = { "pick", "shovel", "sword", "axe" };
6867 int ty = picks.contains(r.toolArmorType) ? 0 : shovels
6868 .contains(r.toolArmorType) ? 1 : axes
6869 .contains(r.toolArmorType) ? 3 : 2;
6870 if (c("light" + n[ty], player, "enchanted a light " + n[ty],
6871 r.inkBlock))
6872 return true;
6873 r_removeEnchantmentFromToolType(TP_RIGHTCLICK, r.toolArmorType,
6874 player);
6875 f_addMagicToPlayer(player, EnChat.GREEN + "This type of " + n[ty]
6876 + " can create magical torches.", r.runePattern, 0,
6877 r.toolArmorType,
6878 getUses(LIGHTSWORD, r.inkBlock, r.metaData));
6879 c(world, r, 5, 5);
6880 }
6881 return true;
6882 case FIRESWORD:
6883 if (!player.isPlayer())
6884 return false;
6885 if (c("fire sword", player, "enchanted a fire sword", r.inkBlock))
6886 return true;
6887 r_removeEnchantmentFromToolType(TP_RIGHTCLICK, r.toolArmorType,
6888 player);
6889 f_addMagicToPlayer(player, EnChat.GREEN
6890 + "You can now set fires with this type of sword.",
6891 r.runePattern, 0, r.toolArmorType,
6892 getUses(FIRESWORD, r.inkBlock, r.metaData));
6893 c(world, r, 5, 5);
6894 return true;
6895 case FIREBLAST:
6896 if (!player.isPlayer())
6897 return false;
6898 if (c("pyrokinesis", player, "infused a sword with pyrokinesis",
6899 r.inkBlock))
6900 return true;
6901 r_removeEnchantmentFromToolType(TP_SWING, r.toolArmorType, player);
6902 f_addMagicToPlayer(
6903 player,
6904 EnChat.GREEN
6905 + "You can now channel pyrokinesis through this type of sword.",
6906 r.runePattern, 1, r.toolArmorType,
6907 getUses(FIREBLAST, r.inkBlock, r.metaData));
6908 c(world, r, 5, 5);
6909 return true;
6910 /*
6911 * case FLARE: if (!pl.isPlayer()) return false; if
6912 * (c("flare",pl,"enchanted a flare rod",r.b)) return true;
6913 * r(1,r.t,pl); f(pl, Chat.GREEN +
6914 * "You can now throw flares from sticks.",
6915 * r.a,1,r.t,10*gt_getTier(r.b,r.d)); c(w,r,5,5); return true;
6916 */
6917 case SHRUB:
6918 if (!player.isPlayer())
6919 return false;
6920 if (c("shrub seed", player, "absorbed a shrub seed", r.inkBlock))
6921 return true;
6922 r_removeEnchantmentFromToolType(TP_RIGHTCLICK, r.toolArmorType,
6923 player);
6924 f_addMagicToPlayer(player, EnChat.GREEN
6925 + "Placed saplings will now become shrubs.", r.runePattern,
6926 0, r.toolArmorType,
6927 5 * gt_getTierByMetaValue(r.inkBlock, r.metaData));
6928 c(world, r, 3, 3);
6929 return true;
6930 case LEAFBLOWER:
6931 if (!player.isPlayer())
6932 return false;
6933 if (c("leaf blower", player, "enchanted a leaf blower", r.inkBlock))
6934 return true;
6935 r_removeEnchantmentFromToolType((g(r.toolArmorType) ? TP_DIGGING
6936 : TP_BROKEN), r.toolArmorType, player);
6937 f_addMagicToPlayer(player, EnChat.GREEN
6938 + "You can now remove many leaves with this type of axe.",
6939 r.runePattern, (g(r.toolArmorType) ? 2 : 3),
6940 r.toolArmorType, (g(r.toolArmorType) ? 6 : 4)
6941 * gt_getTierByMetaValue(r.inkBlock, r.metaData));
6942 c(world, r, 5, 5);
6943 return true;
6944 case FARMERCHARM:
6945 case FARMERCHARM + 1:
6946 if (!player.isPlayer())
6947 return false;
6948 if (c("farmer's charm", player, "absorbed a farmer's charm",
6949 r.inkBlock))
6950 return true;
6951 r_removeEnchantmentFromToolType(TP_RIGHTCLICK, r.toolArmorType,
6952 player);
6953 f_addMagicToPlayer(
6954 player,
6955 EnChat.GREEN
6956 + "This type of hoe will now till fields ready with grain.",
6957 FARMERCHARM, 0, r.toolArmorType, (g(r.toolArmorType) ? 25
6958 : (r.toolArmorType == 292 ? 10 : 18)));
6959 c(world, r, 5, 5);
6960 return true;
6961 case POWERHOE: {
6962 if (!player.isPlayer())
6963 return false;
6964 if (c("power hoe", player, "enchanted a power hoe", r.inkBlock))
6965 return true;
6966 r_removeEnchantmentFromToolType(TP_RIGHTCLICK, r.toolArmorType,
6967 player);
6968 f_addMagicToPlayer(player, EnChat.GREEN
6969 + "This type of hoe will now till larger areas.",
6970 r.runePattern, 0, r.toolArmorType,
6971 getUses(POWERHOE, r.inkBlock, r.metaData));
6972 c(world, r, 3, 3);
6973 }
6974 return true;
6975 case UNCRAFTER:
6976 case UNCRAFTER + 1: {
6977 if (!player.isPlayer())
6978 return false;
6979 if (c("uncrafter", player, "enchanted an uncrafter", r.inkBlock))
6980 return true;
6981 r_removeEnchantmentFromToolType(TP_BROKEN, r.toolArmorType, player);
6982 f_addMagicToPlayer(player, EnChat.GREEN
6983 + "This type of pickaxe will now un-craft blocks.",
6984 UNCRAFTER, 3, r.toolArmorType,
6985 getUses(UNCRAFTER, r.inkBlock, r.metaData));
6986 c(world, r, 5, 5);
6987 }
6988 return true;
6989 case DOUBT: {
6990 final int radius = getUses(FAITH, r.inkBlock, r.metaData);
6991 final int[] needle = { r.x, r.y, r.z, radius, r.w };
6992 boolean foundWrongSize = false;
6993
6994 final Iterator<int[]> iter = faithRuneList.iterator();
6995 while (iter.hasNext()) {
6996 final int[] fi = iter.next();
6997
6998 if (fi[0] == r.x && fi[1] == r.y && fi[2] == r.z
6999 && fi[4] == r.w) {
7000 if (fi[3] == radius) {
7001 player.ab(EnChat.GREEN
7002 + "Your doubt renders this mountain immobile.");
7003
7004 // Remove the faith island
7005 iter.remove();
7006
7007 // Consume the rune
7008 c(world, r, 3, 3);
7009 c(world, r, 3, 3, -1);
7010 return true;
7011 } else {
7012 foundWrongSize = true;
7013 }
7014 }
7015 }
7016
7017 if (foundWrongSize) {
7018 player.ab(EnChat.RED
7019 + "Your doubt is not of the appropriate strength.");
7020 } else {
7021 player.ab(EnChat.RED + "Your doubt is misplaced.");
7022 }
7023
7024 return true;
7025 }
7026 case FLP:
7027 case FLP + 1:
7028 case VFLPNS:
7029 case VFLPEW: {
7030 if (APRIL_FOOLS) {
7031 player.ab(EnChat.RED + "I'm sorry " + player.aw_getName()
7032 + ", I can't let you do that.");
7033 break;
7034 }
7035
7036 int rd = getUses(FLP, r.inkBlock, r.metaData);
7037 int xs, ys, zs;
7038 xs = ys = zs = -rd;
7039 int xe, ye, ze;
7040 xe = ye = ze = rd + 1;
7041 int xo, yo, zo;
7042 xo = yo = zo = 1; // a 1 or -1 value used for targeting 2nd block
7043 // being flipped
7044 if (r.runePattern == FLP || r.runePattern == FLP + 1) {
7045 ys = 1; // stops the flip occurring on both halves of the sphere
7046 // (resulting in no change)
7047 yo = -1; // allows the loop to target -y for the second block
7048 } else if (r.runePattern == VFLPNS) {
7049 zs = 1;
7050 zo = -1;
7051 } else if (r.runePattern == VFLPEW) {
7052 xs = 1;
7053 xo = -1;
7054 }
7055 if (c(runeIdToRuneNameTable.get(FLP), player, r.inkBlock))
7056 return true;
7057
7058 for (int x = -rd; x < rd + 1; x++)
7059 for (int z = -rd; z < rd + 1; z++)
7060 for (int y = -rd; y < rd + 1; y++) {
7061 if (radiuscheck(x, y, z, rd)
7062 && (n(world.a(r.x + x, r.y + y, r.z + z)))
7063 && !((y == 0 || y == 1) && Math.abs(x) < 3 && Math
7064 .abs(z) < 3)) {
7065 player.ab(EnChat.RED
7066 + "The aether has rejected your greedy request...");
7067 return true;
7068 }
7069 }
7070 if (r.y - rd < 0 || r.y + rd > 255) {
7071 player.ab(EnChat.RED
7072 + "This spell may not remove materials from the mortal plane...");
7073 return true;
7074 }
7075
7076 if (!ResidenceChecker.residenceCheck(player.aw_getName(), r.x, r.y,
7077 r.z, rd, world, ResFlags.BuildFlags)) {
7078 player.ab(EnChat.RED
7079 + "You do not have permission to alter this land.");
7080 return true;
7081 }
7082
7083 for (int x = xs; x < xe; x++)
7084 for (int y = ys; y < ye; y++)
7085 for (int z = zs; z < ze; z++)
7086 if (radiuscheck(x, y, z, rd + 0.5)) {
7087 int _a = world.a(r.x + x, r.y + y, r.z + z);
7088 int _ad = world.b(r.x + x, r.y + y, r.z + z);
7089 int _b = world.a(r.x + x * xo, r.y + y * yo, r.z
7090 + z * zo);
7091 int _bd = world.b(r.x + x * xo, r.y + y * yo, r.z
7092 + z * zo);
7093
7094 Object _aTE = null;
7095 Object _bTE = null;
7096 Object[] aItems = null;
7097 Object[] bItems = null;
7098
7099 if (Runecraft_MAIN.boxes.contains(_a)) {
7100 aItems = world.mgc(r.x + x, r.y + y, r.z + z); // get
7101 // the
7102 // from
7103 // world
7104 // contents
7105 Object[] blank = new Object[aItems.length];
7106 world.msc(r.x + x, r.y + y, r.z + z, blank);
7107
7108 } else if (Runecraft_MAIN.tileentityblocks.contains(_a)) {
7109 _aTE = world.getTEmeta(r.x + x, r.y + y, r.z
7110 + z);
7111 }
7112
7113 if (Runecraft_MAIN.boxes.contains(_b)) {
7114 bItems = world.mgc(r.x + x * xo, r.y + y * yo,
7115 r.z + z * zo); // get the from world
7116 // contents
7117 Object[] blank = new Object[bItems.length];
7118 world.msc(r.x + x * xo, r.y + y * yo, r.z + z
7119 * zo, blank);
7120
7121 } else if (Runecraft_MAIN.tileentityblocks.contains(_b)) {
7122 _bTE = world.getTEmeta(r.x + x * xo, r.y + y
7123 * yo, r.z + z * zo);
7124 }
7125
7126 if (yo == -1 && (_a == 44 || _a == 126)) {
7127 _ad ^= 0x08;
7128 }
7129 if (stairs.contains(_a)) {
7130 if (yo == -1) {
7131 _ad ^= 0x04;
7132 }
7133 if (xo == -1 && ((_ad & 0x02) == 0)) {
7134 _ad ^= 0x01;
7135 }
7136 if (zo == -1 && ((_ad & 0x02) == 0x02)) {
7137 _ad ^= 0x01;
7138 }
7139 }
7140 // flip blocks
7141 // if halfslabs.contains(_b) && yo == -1
7142 if (yo == -1 && (_b == 44 || _b == 126)) {
7143 _bd ^= 0x08;
7144 }
7145
7146 if (stairs.contains(_b)) {
7147 if (yo == -1) {
7148 _bd ^= 0x04;
7149 }
7150 if (xo == -1 && ((_bd & 0x02) == 0)) {
7151 _bd ^= 0x01;
7152 }
7153 if (zo == -1 && ((_bd & 0x02) == 0x02)) {
7154 _bd ^= 0x01;
7155 }
7156 }
7157
7158 world.eSilently(r.x + x * xo, r.y + y * yo, r.z + z
7159 * zo, _a);
7160 world.c(r.x + x * xo, r.y + y * yo, r.z + z * zo,
7161 _ad);
7162 if (aItems != null) {
7163 world.msc(r.x + x * xo, r.y + y * yo, r.z + z
7164 * zo, aItems);
7165 }
7166 if (_aTE != null) {
7167 world.setTEmeta(r.x + x * xo, r.y + y * yo, r.z
7168 + z * zo, _aTE);
7169 }
7170 world.eSilently(r.x + x, r.y + y, r.z + z, _b);
7171 world.c(r.x + x, r.y + y, r.z + z, _bd);
7172 if (bItems != null) {
7173 world.msc(r.x + x, r.y + y, r.z + z, bItems);
7174 }
7175 if (_bTE != null) {
7176 world.setTEmeta(r.x + x, r.y + y, r.z + z, _bTE);
7177 }
7178 synchronized (positionRune) // step four:
7179 {
7180 rcm _am = getpr(r.x + x, r.y + y, r.z + z,
7181 world.getWorldId());
7182 rcm _bm = getpr(r.x + (x * xo), r.y + (y * yo),
7183 r.z + (z * zo), world.getWorldId());
7184 if (_am != null) {
7185 positionRune.remove(_am);
7186 _am.x = r.x + x * xo;
7187 _am.y = r.y + y * yo;
7188 _am.z = r.z + z * zo;
7189 positionRune.put(_am, _am);
7190 }
7191 if (_bm != null) {
7192 positionRune.remove(_bm);
7193 _bm.x = r.x + x;
7194 _bm.y = r.y + y;
7195 _bm.z = r.z + z;
7196 positionRune.put(_bm, _bm);
7197 }
7198 }
7199 }
7200
7201 // move TPs
7202 for (int i = 0; i < teleportRuneList.size(); i++) {
7203 int[] tp = teleportRuneList.get(i);
7204 if (tp[3] == r.w) {
7205 int rx = r.x - tp[0];
7206 int ry = r.y - tp[1];
7207 int rz = r.z - tp[2];
7208
7209 if (radiuscheck(rx, ry, rz, rd + 0.5)) {
7210 // DBG("Found a TP ["+tp[0]+","+tp[1]+","+tp[2]+"]",player);
7211 tp[0] = r.x - rx * xo;
7212 tp[1] = r.y - ry * yo;
7213 tp[2] = r.z - rz * zo;
7214
7215 // tpl.set(i,tp);
7216 }
7217 }
7218 }
7219 // move Faith islands
7220 for (int i = 0; i < faithRuneList.size(); i++) {
7221 int[] fi;
7222 int[] fa = faithRuneList.get(i);
7223 int fiw;
7224 if (fa.length < 5) // code to handle Faith Islands created
7225 // before they had world IDs
7226 {
7227
7228 int fix = fa[0];
7229 int fiy = fa[1];
7230 int fiz = fa[2];
7231 int fird = fa[3];
7232 fi = new int[5];
7233 fi[0] = fix;
7234 fi[1] = fiy;
7235 fi[2] = fiz;
7236 fi[3] = fird;
7237 fi[4] = r.w;
7238 faithRuneList.set(i, fi);
7239 } else {
7240 fi = fa;
7241 }
7242
7243 if (fi[4] == r.w || fi[4] < 0) {
7244 int rx = r.x - fi[0];
7245 int ry = r.y - fi[1];
7246 int rz = r.z - fi[2];
7247
7248 if (radiuscheck(rx, ry, rz, rd + 0.5)) {
7249 // rmm.DBG("Island found at ["+Chat.YELLOW+fi[0]+","+fi[1]+","+fi[2]+","+fi[4]+Chat.GREEN+"]"
7250 // +" moved to ["+Chat.YELLOW+ia[0]+","+ia[1]+","+ia[2]+","+ww2.getWorldId()+Chat.GREEN+"]",pl);
7251 fi[0] = r.x - rx * xo;
7252 fi[1] = r.y - ry * yo;
7253 fi[2] = r.z - rz * zo;
7254
7255 // tpl.set(i,tp);
7256
7257 }
7258 }
7259 }
7260
7261 for (int i = 0; i < waypointRuneList.size(); i++) {
7262 int[] ta = waypointRuneList.get(i);
7263 if (ta[5] == r.w) {
7264 int rx = r.x - ta[2];
7265 int ry = r.y - ta[3];
7266 int rz = r.z - ta[4];
7267
7268 if (radiuscheck(rx, ry, rz, rd + 0.5)) {
7269 // rmm.DBG("found a TP in range ["+rmm.Chat.YELLOW+ta[0]+","+ta[1]+","+ta[2]+rmm.Chat.GREEN+"] <"+ta[3]+">",pl);
7270 ta[2] = r.x - rx * xo;
7271 ta[3] = r.y - ry * yo;
7272 ta[4] = r.z - rz * zo;
7273 // m.wpl.set(i,tp);
7274 }
7275 }
7276 }
7277
7278 for (int i = 0; i < waypointList.size(); i++) {
7279 RunePoint ta = waypointList.get(i);
7280 final rcm coords = ta.getCords();
7281 if (coords.w == r.w) {
7282 int rx = r.x - coords.x;
7283 int ry = r.y - coords.y;
7284 int rz = r.z - coords.z;
7285
7286 if (radiuscheck(rx, ry, rz, rd + 0.5)) {
7287 // rmm.DBG("found a TP in range ["+rmm.Chat.YELLOW+ta[0]+","+ta[1]+","+ta[2]+rmm.Chat.GREEN+"] <"+ta[3]+">",pl);
7288 ta.setCords(r.x - rx * xo, r.y - ry * yo, r.z - rz * zo, coords.w);
7289 // m.wpl.set(i,tp);
7290 }
7291 }
7292 }
7293
7294 for (int i = 0; i < realityAnchorList.size(); i++) {
7295 int[] ta = realityAnchorList.get(i);
7296 if (ta[5] == r.w) {
7297 int rx = r.x - ta[2];
7298 int ry = r.y - ta[3];
7299 int rz = r.z - ta[4];
7300
7301 if (radiuscheck(rx, ry, rz, rd + 0.5)) {
7302 // rmm.DBG("found a TP in range ["+rmm.Chat.YELLOW+ta[0]+","+ta[1]+","+ta[2]+rmm.Chat.GREEN+"] <"+ta[3]+">",pl);
7303 ta[2] = r.x - rx * xo;
7304 ta[3] = r.y - ry * yo;
7305 ta[4] = r.z - rz * zo;
7306 // m.wpl.set(i,tp);
7307 }
7308 }
7309 }
7310
7311 // DBG("Automation target size: "+ldl.size(), pl);
7312 for (int i = 0; i < logicDestinationRuneList.size(); i++) {
7313 int[] ld = logicDestinationRuneList.get(i);
7314 if (ld[3] == r.w) {
7315 int rx = r.x - ld[0];
7316 int ry = r.y - ld[1];
7317 int rz = r.z - ld[2];
7318
7319 if (radiuscheck(rx, ry, rz, rd + 0.5)) {
7320 // DBG("found a LD in range ["+rmm.Chat.YELLOW+ld[0]+","+ld[1]+","+ld[2]+rmm.Chat.GREEN+"] <"+ld[3]+">",pl);
7321 ld[0] = r.x - rx * xo;
7322 ld[1] = r.y - ry * yo;
7323 ld[2] = r.z - rz * zo;
7324
7325 // m.wpl.set(i,tp);
7326 }
7327 }
7328 }
7329
7330 for (int i = 0; i < runePadList.size(); i++) {
7331 int[] rpl = runePadList.get(i);
7332 if (rpl[4] == r.w) {
7333 int rx = r.x - rpl[1];
7334 int ry = r.y - rpl[2];
7335 int rz = r.z - rpl[3];
7336
7337 if (radiuscheck(rx, ry, rz, rd + 0.5)) {
7338 rpl[1] = r.x - rx * xo;
7339 rpl[2] = r.y - ry * yo;
7340 rpl[3] = r.z - rz * zo;
7341 }
7342
7343 // 0 1 2 3 4
7344 // r.a, r.x,r.y,r.z,r.w,
7345 }
7346 }
7347
7348 for (int[] wd : wardRuneList) {
7349 if (wd[3] == r.w) {
7350 int rx = r.x - wd[0];
7351 int ry = r.y - wd[1];
7352 int rz = r.z - wd[2];
7353
7354 if (radiuscheck(rx, ry, rz, rd + 0.5)) {
7355 wd[0] = r.x - rx * xo;
7356 wd[1] = r.y - ry * yo;
7357 wd[2] = r.z - rz * zo;
7358 }
7359 }
7360 }
7361
7362 RunePlayer[] players = world.getMobs(r.x, r.y, r.z, rd + 16,
7363 rd + 16, rd + 16, true);
7364 // DBG(Chat.GOLD+"Number of entities= "+players.length);
7365 for (int i = 0; i < players.length; ++i) {
7366 RunePlayer p = players[i];
7367 double pry, prz, prx = p.x() - r.x;
7368 pry = p.y() - r.y;
7369 prz = p.z() - r.z;
7370
7371 if (radiuscheck((int) prx, (int) pry, (int) prz, rd + 0.5)) {
7372 // DBG("*"+p.aw_getName());
7373 p.aa(r.x + prx * xo, r.y + pry * yo, r.z + prz * zo);
7374 } else {
7375 // DBG(Chat.PINK+"*"+p.aw_getName());
7376 }
7377 // p.aa(p.x(),r.y-(p.y()-(r.y-0.5)),p.z());
7378 //
7379 }
7380 }
7381 return true;
7382
7383 case DISPEL:
7384 case DISPEL + 1: {
7385 if (!player.isPlayer())
7386 return false;
7387 if (c("dispel", player, r.inkBlock))
7388 return true;
7389 if (gt_getTierByMetaValue(r.inkBlock, r.metaData) == 2) {
7390 synchronized (sl) {
7391 final List<int[]> en = sl.get(player.aw_getName());
7392 if (en != null) {
7393 final Iterator<int[]> iter = en.iterator();
7394 while (iter.hasNext()) {
7395 final int[] ta = iter.next();
7396 if (!curses.contains(ta[0])) {
7397 iter.remove();
7398 }
7399 }
7400 }
7401 }
7402 s_saveToMagicDat();
7403 player.clearPassives();
7404 player.ab(EnChat.YELLOW
7405 + "All magic has been cleansed from tools!");
7406 r(player, 0);
7407 } else if (gt_getTierByMetaValue(r.inkBlock, r.metaData) == 1) {
7408 if (r.toolArmorType != 0) {
7409 r_removeEnchantmentFromToolType(TP_ALL, r.toolArmorType,
7410 player);
7411 player.ab(EnChat.YELLOW
7412 + "All magic has been cleansed from this tool.");
7413 r(player, r.toolArmorType);
7414 } else {
7415 player.ab(EnChat.RED
7416 + "You cannot dispel runes upon yourself, only on tools");
7417 return false;
7418 }
7419 } else if (gt_getTierByMetaValue(r.inkBlock, r.metaData) >= 3) {
7420 synchronized (positionRune) {
7421
7422 int rd = gt_getTierByMetaValue(r.inkBlock, r.metaData);
7423 for (int x = -rd; x < rd + 1; x++)
7424 for (int y = -rd; y < rd + 1; y++)
7425 for (int z = -rd; z < rd + 1; z++)
7426 if (radiuscheck(x, y, z, rd + 0.5)) {
7427 rcm e = getpr(r.x + x, r.y + y, r.z + z,
7428 r.w);
7429 if (e != null) {
7430 rempr_removePositionRune(e);
7431 // pl.ab("DBG: removed from "+(r.x+x)+","+(r.y+y)+","+(r.z+z)+"");
7432 }
7433 }
7434 synchronized (hexRune) {
7435
7436 for (int x = -rd; x < rd + 1; x++)
7437 for (int y = -rd; y < rd + 1; y++)
7438 for (int z = -rd; z < rd + 1; z++) {
7439 rcm e = getcr(r.x + x, r.y + y, r.z + z,
7440 r.w);
7441 if (e != null) {
7442 if (radiuscheck(x, y, z, rd + 0.5)) {
7443
7444 remcr(e);
7445 // pl.ab("DBG: removed from "+(r.x+x)+","+(r.y+y)+","+(r.z+z)+"");
7446 }
7447
7448 }
7449 }
7450 }
7451 sl.get(player.aw_getName()).clear();
7452 player.ab(EnChat.YELLOW
7453 + "All magic has been cleansed from yourself, and the area around you.");
7454 s_saveToMagicDat();
7455 }
7456 }
7457 c(world, r, 5, 5);
7458 }
7459 return true;
7460 case POWERPICK: {
7461 if (!player.isPlayer())
7462 return false;
7463 int ty = picks.contains(r.toolArmorType) ? 0 : shovels
7464 .contains(r.toolArmorType) ? 1 : axes
7465 .contains(r.toolArmorType) ? 2 : 3;
7466 String[] n = { "pick", "shovel", "axe", "shears" };
7467 String[] m = { "mine a larger area", "dig a larger area",
7468 "fell a tree", "clip a larger area" };
7469 if (c("power " + n[ty], player, "enchanted a power " + n[ty],
7470 r.inkBlock))
7471 return true;
7472 r_removeEnchantmentFromToolType(TP_BROKEN, r.toolArmorType, player);
7473 f_addMagicToPlayer(player, EnChat.GREEN + "This type of " + n[ty]
7474 + " will now " + m[ty] + ".", r.runePattern, 3,
7475 r.toolArmorType, getUses(POWERPICK, r.inkBlock, r.metaData));
7476 c(world, r, 5, 5);
7477 }
7478 return true;
7479 case POWERDRILL:
7480 case POWERDRILL + 1: {
7481 if (!player.isPlayer())
7482 return false;
7483 int ty = picks.contains(r.toolArmorType) ? 0 : shovels
7484 .contains(r.toolArmorType) ? 1 : 2;
7485 String[] n = { "pick", "shovel", "axe" };
7486 if (c("power drill", player, "enchanted a power drill", r.inkBlock))
7487 return true;
7488 r_removeEnchantmentFromToolType(TP_BROKEN, r.toolArmorType, player);
7489 f_addMagicToPlayer(player, EnChat.GREEN + "This type of " + n[ty]
7490 + " will now drill a hole.", POWERDRILL, 3,
7491 r.toolArmorType,
7492 getUses(POWERDRILL, r.inkBlock, r.metaData),
7493 gt_getTierByMetaValue(r.inkBlock, r.metaData)); // half
7494 // energy of
7495 // what
7496 // power
7497 // pick has
7498 c(world, r, 3, 3);
7499 }
7500 return true;
7501 case WATERPICK: {
7502 if (!player.isPlayer())
7503 return false;
7504 if (c("water pick", player, "enchanted a water pick", r.inkBlock))
7505 return true;
7506 r_removeEnchantmentFromToolType(TP_BROKEN, r.toolArmorType, player);
7507 f_addMagicToPlayer(
7508 player,
7509 EnChat.GREEN
7510 + "This type of pick will now cool lava around mined blocks.",
7511 r.runePattern, 3, r.toolArmorType,
7512 getUses(WATERPICK, r.inkBlock, r.metaData));
7513 c(world, r, 5, 5);
7514 }
7515 return true;
7516 case EMBEDDER:
7517 case EMBEDDER + 1: {
7518 if (!player.isPlayer())
7519 return false;
7520 if (c("embedder", player, "enchanted an embedder", r.inkBlock))
7521 return true;
7522 r_removeEnchantmentFromToolType(TP_PLACED, r.toolArmorType, player);
7523 f_addMagicToPlayer(
7524 player,
7525 EnChat.GREEN
7526 + "These blocks will now embed themselves into natural materials.",
7527 EMBEDDER, 4, r.toolArmorType,
7528 getUses(EMBEDDER, r.inkBlock, r.metaData));
7529 c(world, r, 5, 5);
7530 }
7531 return true;
7532 case COLDFEET:
7533 case COLDFEET + 1: {
7534 if (!player.isPlayer())
7535 return false;
7536 if (c("cold feet", player, "enchanted some ice boots", r.inkBlock))
7537 return true;
7538 r(player, r.toolArmorType);/*
7539 * if (r.t == 317) pl.ab(Chat.GREEN +
7540 * "These boots will now freeze the land you walk upon."
7541 * ); else
7542 */
7543 player.ab(EnChat.GREEN
7544 + "These boots will now freeze water beneath your feet.");
7545 tm.schedule(
7546 t(world,
7547 -COLDFEET,
7548 player,
7549 COLDFEET,
7550 5,
7551 r.toolArmorType,
7552 (r.toolArmorType != 309 ? 20 : 0)
7553 + getUses(COLDFEET, r.inkBlock, r.metaData),
7554 0, 0, 0, (RunecraftParser.w(player, 0,
7555 r.toolArmorType)) ? 1 : 0), 300, 300);
7556 c(world, r, 3, 3);
7557 }
7558 return true;
7559 case FAIRYBOOTS:
7560 case FAIRYBOOTS + 1:// TODO this should only subtract energy when you've
7561 // fallen more than 3m
7562 {
7563 if (!player.isPlayer())
7564 return false;
7565 if ((c("fairy boots", player, "enchanted some fairy boots")))
7566 return true;
7567 r(player, r.toolArmorType);
7568 player.ab(EnChat.GREEN + "These boots will now slow your fall.");
7569 int plx = (int) Math.floor(player.x());
7570 int plz = (int) Math.floor(player.z());
7571 tm.schedule(
7572 t(world, -FAIRYBOOTS, player, FAIRYBOOTS, plx,
7573 (int) Math.floor(player.y()), plz,
7574 (int) Math.round((player.x() - plx) * 100),
7575 (int) Math.round((player.z() - plz) * 100),
7576 getUses(FAIRYBOOTS, r.inkBlock, r.metaData), 5,
7577 r.toolArmorType, 0), 200, 200);
7578 c(world, r, 3, 3);
7579 }
7580 return true;
7581 case DIVERHELM: {
7582 if (!player.isPlayer())
7583 return false;
7584 if (c("diver's helmet", player, "enchanted a diver's helmet",
7585 r.inkBlock))
7586 return true;
7587 r(player, r.toolArmorType);
7588 player.ab(EnChat.GREEN
7589 + "Wear this helmet to replenish air underwater.");
7590 tm.schedule(
7591 t(world,
7592 -r.runePattern,
7593 player,
7594 r.runePattern,
7595 5,
7596 r.toolArmorType,
7597 (r.toolArmorType != 306 ? 15 : 0)
7598 + getUses(DIVERHELM, r.inkBlock, r.metaData),
7599 0, 0, 0, (RunecraftParser.w(player, 0,
7600 r.toolArmorType)) ? 1 : 0, 0), 1000, 1000);
7601 c(world, r, 5, 5);
7602 }
7603 return true;
7604 case WALLMASTER:// TODO add in redstone torch reset function
7605 case WALLMASTER + 1: {
7606 int xo = 0, zo = 0, p = 0;
7607 if (r.runePattern == WALLMASTER)
7608 zo = 1;
7609 else
7610 xo = 1;
7611 if (world.a(r.x + xo * 2, r.y, r.z + zo * 2) == 76)
7612 p++;
7613 else if (world.a(r.x + xo * 2, r.y, r.z + zo * 2) != 0)
7614 return false;
7615 if (world.a(r.x + xo * -2, r.y, r.z + zo * -2) == 76)
7616 p--;
7617 else if (world.a(r.x + xo * -2, r.y, r.z + zo * -2) != 0)
7618 return false;
7619 if (p == 0)
7620 return false;
7621 xo *= p;
7622 zo *= p;
7623 if (c("wall master", player, r.inkBlock))
7624 return true;
7625 e(world, r, 5, 5);
7626 world.e(r.x + xo, r.y, r.z + zo, 0);
7627 world.e(r.x - xo, r.y, r.z - zo, 55);
7628 world.e(r.x, r.y, r.z, 0);
7629 int[] ta = { 3, r.x, r.y, r.z, r.w, xo, zo, p, 1,
7630 1 + gt_getTierByMetaValue(r.inkBlock, r.metaData) * 2, -1 };
7631 positionRuneList.add(ta);
7632 addpr_addPositionRune(ta);
7633 s_saveToMagicDat();
7634 }
7635 return true;
7636 case BRIDGEMASTER:// TODO add in redstone torch reset function
7637 case BRIDGEMASTER + 1: {
7638 if (getpr(r.x, r.y, r.z, r.w) == null)
7639 DBG("There is no magic here already");
7640 int xo = 0, zo = 0, p = 0;
7641 if (r.runePattern == BRIDGEMASTER)
7642 zo = 1;
7643 else
7644 xo = 1;
7645 if (world.a(r.x + xo * 2, r.y, r.z + zo * 2) == 76)
7646 p++;
7647 else if (world.a(r.x + xo * 2, r.y, r.z + zo * 2) != 0)
7648 return false;
7649 if (world.a(r.x + xo * -2, r.y, r.z + zo * -2) == 76)
7650 p--;
7651 else if (world.a(r.x + xo * -2, r.y, r.z + zo * -2) != 0)
7652 return false;
7653 if (p == 0)
7654 return false;
7655 xo *= p;
7656 zo *= p;
7657 if (c("bridge master", player, r.inkBlock))
7658 return true;
7659 rcm pr = new rcm(r.x, r.y, r.z);
7660 pr.w = r.w;
7661 pr.runePattern = BRIDGEMASTER;
7662 if (!addpr_addPositionRune(pr)) {
7663 player.ab(EnChat.YELLOW + "Something interferes.");
7664 return true;
7665 }
7666 e(world, r, 5, 5);
7667 world.e(r.x + xo, r.y, r.z + zo, 0);
7668 world.e(r.x - xo, r.y, r.z - zo, 55);
7669 world.e(r.x + zo, r.y, r.z + xo, 55); // put dust...
7670 world.e(r.x - zo, r.y, r.z - xo, 55); // on the sides
7671 world.e(r.x, r.y, r.z, 0);
7672 int[] ta = { 5, r.x, r.y, r.z, r.w, xo, zo, p, 0,
7673 1 + gt_getTierByMetaValue(r.inkBlock, r.metaData) * 2, 0 };
7674
7675 positionRuneList.add(ta);
7676 addpr_addPositionRune(pr);
7677 s_saveToMagicDat();
7678 }
7679 return true;
7680 case LOGBLOCK: {
7681 int tier2 = c_aliasTierZeroToAir(world, r.x, r.y, r.z);
7682 if (tier2 == 0)
7683 return false;
7684 if (c("block sensor", player, "set up a block sensor", r.inkBlock))
7685 return true;
7686 g = gg(world, r.x, r.y - 1, r.z, r.runePattern, false);
7687 gd = gg(world, r.x, r.y - 1, r.z, r.runePattern, true);
7688 vb = c_aliasTierZeroToAir(world, r.x, r.y - 1, r.z);
7689 int sz = bt_blockTier[tier2] * 2;
7690 for (int x = -1; x < 2; x++)
7691 for (int z = -1; z < 2; z++)
7692 for (int y = 0; y < sz; y++) {
7693 rcm e = new rcm(LOGBLOCK, r.inkBlock, r.x + x, r.y + y
7694 + 1, r.z + z, r.w, g, gd, vb);
7695 addpr_addPositionRune(e);
7696 }
7697 player.ab(EnChat.GREEN
7698 + "This rune will send out automation signals on this signature");
7699 player.ab(EnChat.GREEN
7700 + "when a block is placed above it (up to tier*2 blocks high)");
7701 // signature blocks
7702 for (int x = -1; x < 2; x++)
7703 for (int z = -1; z < 2; z++)
7704 addpr_addPositionRune(new rcm(2, r.inkBlock, r.x + x,
7705 r.y - 1, r.z + z, r.w, 0, LOGBLOCK));
7706 addpr_addPositionRune(new rcm(2, r.inkBlock, r.x, r.y, r.z, r.w, 1,
7707 LOGBLOCK));
7708 addpr_addPositionRune(new rcm(2, r.inkBlock, r.x + 1, r.y, r.z,
7709 r.w, 0, LOGBLOCK));
7710 addpr_addPositionRune(new rcm(2, r.inkBlock, r.x - 1, r.y, r.z,
7711 r.w, 0, LOGBLOCK));
7712 addpr_addPositionRune(new rcm(2, r.inkBlock, r.x, r.y, r.z + 1,
7713 r.w, 0, LOGBLOCK));
7714 addpr_addPositionRune(new rcm(2, r.inkBlock, r.x, r.y, r.z - 1,
7715 r.w, 0, LOGBLOCK));
7716 }
7717 return true;
7718 /*
7719 * case STAIRMASTER: { if ((c("stair master",pl))) return true;
7720 * e(r,5,5); w.e(r.x,r.y,r.z,0); int[] ta =
7721 * {4,r.x,r.y,r.z,r.w,0,gt_getTier(r.b,r.d)*8}; prl.add(ta);
7722 * addpr(ta); s(); } return true;
7723 */
7724 case UNDERWATERPICK: // pick or shovel
7725 {
7726 if (!player.isPlayer())
7727 return false;
7728 boolean s = shovels.contains(r.toolArmorType);
7729 String tool = s ? "shovel" : "pick";
7730 if (c("underwater " + tool, player, "enchanted an underwater "
7731 + tool, r.inkBlock))
7732 return true;
7733 r_removeEnchantmentFromToolType(TP_BROKEN, r.toolArmorType, player);
7734 f_addMagicToPlayer(player, EnChat.GREEN + "This type of " + tool
7735 + " will now stop water around mined blocks.",
7736 r.runePattern, 3, r.toolArmorType,
7737 getUses(UNDERWATERPICK, r.inkBlock, r.metaData) / 3);// div
7738 // 3
7739 // because
7740 // it
7741 // is
7742 // not
7743 // currently
7744 // using
7745 // 'energy'
7746 // and
7747 // so
7748 // can
7749 // get
7750 // an
7751 // arc
7752 // of
7753 // glass
7754 c(world, r, 5, 5);
7755 return true;
7756 }
7757 case TUNNELSHOVEL:
7758 case TUNNELSHOVEL + 1: {
7759
7760 if (!player.isPlayer())
7761 return false;
7762 boolean s = shovels.contains(r.toolArmorType);
7763 if (!s) {
7764 return false;
7765 }
7766 if (c("gravel shovel", player, "enchanted a gravel shovel"))
7767 return true;
7768 f_addMagicToPlayer(player, EnChat.GREEN
7769 + "This type of shovel will now prevent against cave-ins.",
7770 r.runePattern, 3, r.toolArmorType,
7771 getUses(TUNNELSHOVEL, r.inkBlock, r.metaData));
7772 c(world, r, 5, 5);
7773 return true;
7774 }
7775
7776 case DEPTHPAPER:
7777 if (!player.isPlayer())
7778 return false;
7779 if (c("depth note", player, "scribed a depth note", r.inkBlock))
7780 return true;
7781 r_removeEnchantmentFromToolType(TP_RIGHTCLICK, r.toolArmorType,
7782 player);
7783 f_addMagicToPlayer(player, EnChat.GREEN
7784 + "Place the paper on the ground to measure the depth.",
7785 r.runePattern, 0, r.toolArmorType,
7786 getUses(DEPTHPAPER, r.inkBlock, r.metaData));
7787 c(world, r, 5, 5);
7788 return true;
7789 case SURFACE_TENSION: {
7790 if (!player.isPlayer())
7791 return false;
7792 if ((c("surface tension", player, r.inkBlock)))
7793 return true;
7794 c(world, r, 3, 3);
7795 world.e(r.x, r.y - 1, r.z, 0);
7796 r_removeEnchantmentFromToolType(TP_BROKEN, r.toolArmorType, player);
7797 f_addMagicToPlayer(player, EnChat.GREEN
7798 + "Mine ice with slime to use.", r.runePattern, 3,
7799 r.toolArmorType,
7800 getUses(SURFACE_TENSION, r.inkBlock, r.metaData));
7801 return true;
7802 }
7803 case LAVAGEL: {
7804 if (!player.isPlayer())
7805 return false;
7806 if ((c("lava gel", player, r.inkBlock)))
7807 return true;
7808 c(world, r, 3, 3);
7809 world.e(r.x, r.y - 1, r.z, 0);
7810 r_removeEnchantmentFromToolType(TP_BROKEN, r.toolArmorType, player);
7811 f_addMagicToPlayer(player, EnChat.GREEN
7812 + "Mine netherrack with slime to use.", r.runePattern, 3,
7813 r.toolArmorType, getUses(LAVAGEL, r.inkBlock, r.metaData));
7814 return true;
7815 }
7816 case SECRETCHEST:
7817 case SECRETCHEST + 1:
7818 if (APRIL_FOOLS) {
7819 player.ab(EnChat.RED + "I'm sorry " + player.aw_getName()
7820 + ", I can't let you do that.");
7821 break;
7822 }
7823 if (!player.isPlayer())
7824 return false;
7825 if (c("zeerix' chest", player, "bound a secret chest"))
7826 return true;
7827 r_removeEnchantmentFromToolType(TP_CATCHALL, r.toolArmorType,
7828 player);
7829 RunecraftParser.b(opc[r.runePattern - SECRETCHEST], world, r.x,
7830 r.y, r.z, -wr_runeTemplateArray[r.runePattern - 1][0],
7831 -wr_runeTemplateArray[r.runePattern - 1][1], r.inkBlock);
7832 f_addMagicToPlayer(player, EnChat.GREEN
7833 + "The wand will now summon your chest.", SECRETCHEST, -2,
7834 r.toolArmorType,
7835 getUses(SECRETCHEST, r.inkBlock, r.metaData), r.x, r.y - 1,
7836 r.z, r.w, 0/* unsummoned */, 0, 0, 0, 0/*
7837 * x,y,z,w of
7838 * summoned place
7839 */);
7840 return true;
7841 case SUPERSECRETCHEST:
7842 case SUPERSECRETCHEST + 1:
7843 if (APRIL_FOOLS) {
7844 player.ab(EnChat.RED + "I'm sorry " + player.aw_getName()
7845 + ", I can't let you do that.");
7846 break;
7847 }
7848 if (!player.isPlayer())
7849 return false;
7850 if (c("zeerix' ender chest", player, "bound a super secret chest"))
7851 return true;
7852 r_removeEnchantmentFromToolType(TP_CATCHALL, r.toolArmorType,
7853 player);
7854 RunecraftParser.b(opc[r.runePattern - SUPERSECRETCHEST + 2], world,
7855 r.x, r.y, r.z, -wr_runeTemplateArray[r.runePattern - 1][0],
7856 -wr_runeTemplateArray[r.runePattern - 1][1], r.inkBlock);
7857 f_addMagicToPlayer(player, EnChat.GREEN
7858 + "The wand will now summon your chest.", SUPERSECRETCHEST,
7859 -2, r.toolArmorType,
7860 getUses(SECRETCHEST, r.inkBlock, r.metaData), r.x, r.y - 1,
7861 r.z, r.w, 0/* unsummoned */, 0, 0, 0, 0/*
7862 * x,y,z,w of
7863 * summoned place
7864 */);
7865 return true;
7866 case MOUSETRAP:// TODO is this in hearts of damage? the getUses result
7867 // is in hearts
7868 case MOUSETRAP + 1:
7869 if (!player.isEntity())
7870 return false;
7871 if (c("mouse trap", player, r.inkBlock, WardType.Void))
7872 return true;
7873 // c(w,r,5,5);
7874 player.ab(EnChat.PINK + "To use this curse, bind it with a hex rune.");
7875 player.ab(EnChat.PINK
7876 + "Those who are caught using the trap will be set aflame.");
7877 player.ab(EnChat.PINK
7878 + "The stronger the trap, the longer they burn.");
7879 // player.Z(getUses(MOUSETRAP, r.inkBlock,r.metaData) * 2);//x2
7880 // because of half hearts of damage
7881 return true;
7882
7883 case PHASEBLOCKS: {
7884 if (!player.isPlayer())
7885 return false;
7886 g = gg(world, r.x, r.y, r.z, r.runePattern, false);
7887 if (c("phase blocks", player, "enchanted phase blocks", r.inkBlock))
7888 return true;
7889 r_removeEnchantmentFromToolType(TP_RIGHTCLICK, r.toolArmorType,
7890 player);
7891 f_addMagicToPlayer(player, EnChat.GREEN
7892 + "You can toggle these blocks when placed.",
7893 r.runePattern, 0, r.toolArmorType,
7894 getUses(PHASEBLOCKS, r.inkBlock, r.metaData),
7895 0 /* sub-type */, g);
7896 c(world, r, 5, 5);
7897 return true;
7898 }
7899 case LOCKBLOCKS: {
7900 if (!player.isPlayer())
7901 return false;
7902 g = gg(world, r.x, r.y, r.z, r.runePattern, false);
7903 if (c("lock blocks", player, "enchanted a lock block", r.inkBlock))
7904 return true;
7905 int vb0 = c_aliasTierZeroToAir(world, r.x, r.y, r.z);
7906 short vb1 = world.matb_returnOnlyValuableMetaData(vb0,
7907 (short) world.b(r.x, r.y, r.z));
7908 r_removeEnchantmentFromToolType(TP_RIGHTCLICK, r.toolArmorType,
7909 player);
7910 f_addMagicToPlayer(
7911 player,
7912 EnChat.GREEN
7913 + "This block will control a group of connected Phase, Spleef, and Toggle Blocks.",
7914 r.runePattern, 0, r.toolArmorType,
7915 getUses(LOCKBLOCKS, r.inkBlock, r.metaData) /*
7916 * low tier =
7917 * single use
7918 */, vb0
7919 | (vb1 << 8) /* key (sub-type) */, g);
7920 c(world, r, 5, 5);
7921 return true;
7922 }
7923 case SPLEEFBLOCKS: {
7924 if (!player.isPlayer())
7925 return false;
7926 g = gg(world, r.x, r.y, r.z, r.runePattern, false);
7927 if (c("spleef blocks", player, "enchanted spleef blocks",
7928 r.inkBlock))
7929 return true;
7930 r_removeEnchantmentFromToolType(TP_RIGHTCLICK, r.toolArmorType,
7931 player);
7932 f_addMagicToPlayer(player, EnChat.GREEN
7933 + "These blocks will vanish individually.", r.runePattern,
7934 0, r.toolArmorType,
7935 getUses(SPLEEFBLOCKS, r.inkBlock, r.metaData),
7936 0 /* sub-type */, g);
7937 c(world, r, 5, 5);
7938 return true;
7939 }
7940 case TOGGLEBLOCKS: {
7941 if (!player.isPlayer())
7942 return false;
7943 g = gg(world, r.x, r.y, r.z, r.runePattern, false);
7944 if (c("Toggle blocks", player, "enchanted spleef blocks",
7945 r.inkBlock))
7946 return true;
7947 r_removeEnchantmentFromToolType(TP_RIGHTCLICK, r.toolArmorType,
7948 player);
7949 f_addMagicToPlayer(
7950 player,
7951 EnChat.GREEN
7952 + "These blocks will swap with whatever else occupies the spot.",
7953 r.runePattern, 0, r.toolArmorType,
7954 getUses(TOGGLEBLOCKS, r.inkBlock, r.metaData),
7955 0 /* sub-type */, g);
7956 c(world, r, 5, 5);
7957 return true;
7958 }
7959 case BEACON:// TODO add temporary waypoint functionality
7960 case BEACON + 1: {
7961 if (c("magic beacon", player, r.inkBlock))
7962 return true;
7963 c(world, r, 3, 3);
7964 int t = r.y + getUses(BEACON, r.inkBlock, r.metaData) - 1;// TODO
7965 // make
7966 // low
7967 // tier
7968 // magic
7969 // beacon
7970 // use
7971 // torches
7972 // and a
7973 // different
7974 // height
7975 if (t > world.getMaxY())
7976 t = world.getMaxY();
7977 for (int oy = r.y; oy <= t; oy++)
7978 if (world.a(r.x, oy, r.z) == 0) {
7979 if (addpr_addPositionRune(new rcm(BEACON, GLOWSTONE, r.x,
7980 oy, r.z, r.w, t, 0)))
7981 world.e(r.x, oy, r.z, GLOWSTONE);
7982 } else
7983 break; // hit an obstacle
7984 return true;
7985 }
7986 case ACCELERATOR: {
7987 for (int[] ta : runePadList)
7988 if (ta[0] == r.runePattern && ta[1] == r.x && ta[2] == r.y
7989 && ta[3] == r.z && ta[4] == r.w)
7990 return false;
7991 if (c("accelerator", player, "set up an accelerator", r.inkBlock))
7992 return true;
7993 for (int x = -2; x < 3; x++)
7994 for (int z = -2; z < 3; z++)
7995 addpr_addPositionRune(new rcm(2, r.inkBlock, r.x + x, r.y,
7996 r.z + z, r.w, (x == 0 && z == 0 ? 1 : 0),
7997 ACCELERATOR));
7998 int[] ta = { r.runePattern, r.x, r.y, r.z, r.w, 2, 2, 2, 0,
7999 gt_getTierByMetaValue(r.inkBlock, r.metaData) };
8000 runePadList.add(ta);
8001 s_saveToMagicDat();
8002 for (RunePlayer p : world.getPlayers())
8003 oa(p);
8004 return true;
8005 }
8006 case LOGPAD: {
8007 for (int[] ta : runePadList)
8008 if (ta[0] == r.runePattern && ta[1] == r.x && ta[2] == r.y
8009 && ta[3] == r.z && ta[4] == r.w)
8010 return false; // prevents two pressure sensors being focused
8011 // on the same point
8012 if (c("pressure sensor", player, "set up a pressure sensor",
8013 r.inkBlock))
8014 return true;
8015 g = gg(world, r.x, r.y, r.z, r.runePattern, false);
8016 gd = gg(world, r.x, r.y, r.z, r.runePattern, true);
8017 vb = c_aliasTierZeroToAir(world, r.x, r.y, r.z);
8018 for (int x = -2; x < 3; x++)
8019 for (int z = -2; z < 3; z++)
8020 addpr_addPositionRune(new rcm(2, r.inkBlock, r.x + x, r.y,
8021 r.z + z, r.w, (x == 0 && z == 0 ? 1 : 0), LOGPAD));
8022 int[] ta = { r.runePattern, r.x, r.y, r.z, r.w, 2, 2, 2, 0,
8023 r.inkBlock, g, gd, vb, 0 /* last hit */};
8024 runePadList.add(ta);
8025 s_saveToMagicDat();
8026 player.ab(EnChat.GREEN
8027 + "This rune will send out automation signals on this signature when a player steps on the pad.");
8028 for (RunePlayer p : world.getPlayers())
8029 oa(p);
8030 return true;
8031 }
8032 case OVICAPTOR:// TODO make this multi-use
8033 {
8034 for (int[] ta : runePadList)
8035 if (ta[0] == r.runePattern && ta[1] == r.x && ta[2] == r.y
8036 && ta[3] == r.z && ta[4] == r.w)
8037 return false;
8038 if (!player.isPlayer())
8039 return false;
8040 if (c("ovicaptor", player, "set up an ovicaptor", r.inkBlock))
8041 return true;
8042 for (int x = -1; x < 2; x++)
8043 for (int z = -1; z < 2; z++)
8044 addpr_addPositionRune(new rcm(2, r.inkBlock, r.x + x,
8045 r.y - 1, r.z + z, r.w, 0, OVICAPTOR));
8046 addpr_addPositionRune(new rcm(2, r.inkBlock, r.x, r.y, r.z, r.w, 1,
8047 OVICAPTOR));
8048 int[] ta = { r.runePattern, r.x, r.y, r.z, r.w, 1, 1, 2, 0 };
8049 runePadList.add(ta);
8050 s_saveToMagicDat();
8051 player.ab(EnChat.GREEN
8052 + "This rune will capture mobs that stand on it.");
8053 oam(world);
8054 return true;
8055 }
8056 case SPRINGSTRING:
8057 case SPRINGSTRING + 1: {
8058 if (!player.isPlayer())
8059 return false;
8060 if (c("spring string", player, "enchanted a spring string",
8061 r.inkBlock))
8062 return true;
8063 r_removeEnchantmentFromToolType(TP_SWING, r.toolArmorType, player);
8064 f_addMagicToPlayer(
8065 player,
8066 EnChat.GREEN + "Swing your spring string to spring forward.",
8067 SPRINGSTRING,
8068 1,
8069 r.toolArmorType,
8070 getUses(SPRINGSTRING, r.inkBlock, r.metaData)
8071 * (int) Math.floor(5 + gt_getTierByMetaValue(
8072 r.inkBlock, r.metaData) / 3));// TODO should
8073 // this line
8074 // also be
8075 // getUses?
8076 c(world, r, 3, 3);
8077 return true;
8078 }
8079 case LASSO:// TODO make the target finding not suck
8080 {
8081 if (!player.isPlayer())
8082 return false;
8083 if (c("magic lasso", player, "enchanted a magic lasso", r.inkBlock))
8084 return true;
8085 r_removeEnchantmentFromToolType(TP_SWING, r.toolArmorType, player);
8086 f_addMagicToPlayer(player, EnChat.GREEN
8087 + "Swing your magic lasso to pull creatures to you.",
8088 LASSO, 1, r.toolArmorType,
8089 getUses(LASSO, r.inkBlock, r.metaData));
8090 world.e(r.x, r.y + 1, r.z, 0);
8091 c(world, r, 5, 5);
8092 return true;
8093 }
8094 case INITIATOR: {
8095 if (!player.isPlayer())
8096 return false;
8097 if (rlc("initiation")) {
8098 if (ip.contains(player.aw_getName()))
8099 player.ab(EnChat.RED
8100 + "You can already manipulate the aether.");
8101 else {
8102 ip.add(player.aw_getName());
8103 player.ab(EnChat.GREEN
8104 + "The aether welcomes you as its master.");
8105 s_saveToMagicDat();
8106 }
8107 } else
8108 player.ab(EnChat.RED + "All may already manipulate the aether.");
8109 return true;
8110 }
8111 case JUDGEMENT: {
8112 if (!rlc("judgement"))
8113 return false;
8114 if (c(runeIdToRuneNameTable.get(r.runePattern), player, r.inkBlock)) {
8115 return true;
8116 }
8117 player.ab(EnChat.GREEN + "Altar of Judgement established.");
8118 player.ab(EnChat.YELLOW
8119 + "To inform the aether of your judgements, you must write");
8120 player.ab(EnChat.YELLOW
8121 + "the name of a rune and/or a person on a sign, and place the");
8122 player.ab(EnChat.YELLOW
8123 + "sign above the lava. If your judgements involve a material,");
8124 player.ab(EnChat.YELLOW
8125 + "you shall place such a material on one of the golden arms.");
8126 synchronized (positionRune) {
8127 rcm e = new rcm(3, 0, r.x, r.y + 1, r.z, r.w, 0, JUDGEMENT);
8128 positionRune.put(e, e);
8129 s_saveToMagicDat();
8130 }
8131 return true;
8132 }
8133 case FORCEFIELD: {
8134 int torch = world.a(r.x, r.y + 2, r.z);
8135 if (torch != 50 && torch != 75 && torch != 76)
8136 return false;
8137 int key = (torch == 76 || torch == 75 ? r.toolArmorType : 0);
8138 for (int[] ta : runePadList)
8139 if (ta[0] == r.runePattern && ta[1] == r.x && ta[2] == r.y
8140 && ta[3] == r.z && ta[4] == r.w)
8141 return false;
8142 if (c("force field", player, r.inkBlock))
8143 return true;
8144 for (int x = -1; x < 2; x++)
8145 for (int z = -1; z < 2; z++)
8146 addpr_addPositionRune(new rcm(2, r.inkBlock, r.x + x, r.y,
8147 r.z + z, r.w, (x == 0 && z == 0 ? 1 : 0),
8148 FORCEFIELD));
8149 addpr_addPositionRune(new rcm(2, r.inkBlock, r.x, r.y + 1, r.z,
8150 r.w, 0, FORCEFIELD));
8151 addpr_addPositionRune(new rcm(2, r.inkBlock, r.x, r.y + 2, r.z,
8152 r.w, 0, FORCEFIELD));
8153 int rd = 3 + bt_blockTier[world.a(r.x, r.y + 1, r.z)] * 3;
8154 // TODO: change the time stuff so they work properly between server
8155 // instances
8156 int[] ta = {
8157 r.runePattern,
8158 r.x,
8159 r.y,
8160 r.z,
8161 r.w,
8162 0,
8163 0,
8164 0,
8165 rd,
8166 ((int) (System.currentTimeMillis() / 1000))
8167 + getUses(FORCEFIELD, r.inkBlock, r.metaData),
8168 (r.inkBlock == 7 ? -1 : 0), key };
8169 if (key > 0)
8170 player.ab(EnChat.GREEN
8171 + "Players can pass the forcefield while holding this type of item.");
8172 runePadList.add(ta);
8173 s_saveToMagicDat();
8174 for (RunePlayer p : world.getPlayers())
8175 oa(p);
8176 return true;
8177 }
8178 case ENCHANTMENTSWAP:
8179 case ENCHANTMENTSWAP + 1: {
8180 if (c("enchantment swap", player, r.inkBlock))
8181 return true;
8182 RunePlayer p1 = null, p2 = null;
8183 // Find the players in each slot
8184 for (RunePlayer p : world.getPlayers()) {
8185 int XD = (int) Math.floor(p.x()) - r.x;
8186 int ZD = (int) Math.floor(p.z()) - r.z;
8187 if (Math.abs(XD) == (r.runePattern == ENCHANTMENTSWAP ? 2 : 0)
8188 && Math.abs(ZD) == (r.runePattern == ENCHANTMENTSWAP ? 0
8189 : 2) && Math.floor(p.y()) == r.y) {
8190 if (XD < 0 || ZD < 0) {
8191 if (p1 == null)
8192 p1 = p;
8193 else {
8194 p1.ab(EnChat.RED + "Only one may occupy this slot!");
8195 p.ab(EnChat.RED + "Only one may occupy this slot!");
8196 return true;
8197 }
8198 } else if (XD > 0 || ZD > 0) {
8199 if (p2 == null)
8200 p2 = p;
8201 else {
8202 p2.ab(EnChat.RED + "Only one may occupy this slot!");
8203 p.ab(EnChat.RED + "Only one may occupy this slot!");
8204 return true;
8205 }
8206 }
8207 }
8208 }
8209 if (p1 == null || p2 == null) {
8210 player.ab(EnChat.RED + "Both slots must be occupied!");
8211 return true;
8212 }
8213 if (p1.Pc() != p2.Pc()) {
8214 p1.ab(EnChat.RED
8215 + "You must both be holding the same type of item!");
8216 p2.ab(EnChat.RED
8217 + "You must both be holding the same type of item!");
8218 return true;
8219 }
8220 if (sl.get(p1.aw_getName()) == null)
8221 sl.put(p1.aw_getName(), new LinkedList<int[]>());
8222 if (sl.get(p2.aw_getName()) == null)
8223 sl.put(p2.aw_getName(), new LinkedList<int[]>());
8224 List<int[]> s1 = sl.get(p1.aw_getName()), s2 = sl.get(p2
8225 .aw_getName());
8226 int num1 = 0, num2 = 0;
8227 for (int tp = 0; tp < 5; tp++) {
8228 int[] e1 = null, e2 = null;
8229 for (int i = 0; i < s1.size(); i++) {
8230 int[] ta = s1.get(i);
8231 if (ta[2] == p1.Pc() && ta[1] == tp) {
8232 e1 = ta;
8233 s1.remove(i);
8234 break;
8235 }
8236 }
8237 for (int i = 0; i < s2.size(); i++) {
8238 int[] ta = s2.get(i);
8239 if (ta[2] == p2.Pc() && ta[1] == tp) {
8240 e2 = ta;
8241 s2.remove(i);
8242 break;
8243 }
8244 }
8245 if (e1 != null) {
8246 s2.add(e1);
8247 num1++;
8248 }
8249 if (e2 != null) {
8250 s1.add(e2);
8251 num2++;
8252 }
8253 }
8254 if (num1 == 0 && num2 == 0) {
8255 p1.ab(EnChat.RED + "No enchantments were transferred.");
8256 p2.ab(EnChat.RED + "No enchantments were transferred.");
8257 return true;
8258 }
8259 if (num1 > 0) {
8260 p1.ab(EnChat.GREEN + "Sent " + num1 + " enchantment"
8261 + (num1 == 1 ? "." : "s."));
8262 p2.ab(EnChat.GREEN + "Received " + num1 + " enchantment"
8263 + (num1 == 1 ? "." : "s."));
8264 }
8265 if (num2 > 0) {
8266 p2.ab(EnChat.GREEN + "Sent " + num2 + " enchantment"
8267 + (num2 == 1 ? "." : "s."));
8268 p1.ab(EnChat.GREEN + "Received " + num2 + " enchantment"
8269 + (num2 == 1 ? "." : "s."));
8270 }
8271 return true;
8272 }
8273 case PHANTOMTORCH:// TODO change this to distance traveled, not time,
8274 // like cold feet
8275 case PHANTOMTORCH + 1:
8276 case REDTORCH:
8277 case REDTORCH + 1: {
8278 if (!player.isEntity())
8279 return false;
8280 boolean s = (r.runePattern == PHANTOMTORCH || r.runePattern == PHANTOMTORCH + 1);
8281 if ((c("phantom torch", player)))
8282 return true;
8283 r(player, s ? TORCH : RS_TORCH);
8284 tm.schedule(
8285 t(world, -PHANTOMTORCH, player, r.x, r.y, r.z,
8286 getUses(PHANTOMTORCH, r.inkBlock, r.metaData) * 10,// x10
8287 // because
8288 // it's
8289 // still
8290 // based
8291 // on
8292 // time
8293 s ? TORCH : RS_TORCH), 1000, 1000);
8294 c(world, r, 3, 3);
8295 }
8296 return true;
8297 case ENDURANCE:// TODO possibly switch this to damage absorbed rather
8298 // than time
8299 case ENDURANCE + 1: {
8300 if (!player.isPlayer())
8301 return false;
8302 if ((c("endurance", player, "used endurance")))
8303 return true;
8304 c(world, r, 5, 5);
8305 player.D(20 * (2 * gt_getTierByMetaValue(r.inkBlock, r.metaData)));
8306
8307 r_removeEnchantmentFromToolType(TP_PASSIVE, 0, player, ENDURANCE);
8308 f_addMagicToPlayer(
8309 player,
8310 EnChat.YELLOW
8311 + "Your endurance multiplies by "
8312 + (2 * gt_getTierByMetaValue(r.inkBlock, r.metaData))
8313 + ".", r.runePattern, TP_PASSIVE.getCode(), 0,
8314 getUses(r.runePattern, r.inkBlock, r.metaData) * 10,
8315 Math.round(20 * (2 * gt_getTierByMetaValue(r.inkBlock,
8316 r.metaData))));
8317
8318 int[] args = {
8319 (int) player.x(),
8320 (int) player.y(),
8321 (int) player.z(),
8322 getUses(ENDURANCE, r.inkBlock, r.metaData),
8323 Math.round(20 * (2 * gt_getTierByMetaValue(r.inkBlock,
8324 r.metaData))) };
8325
8326 RCT_main t = t(world, -ENDURANCE, args, player, TP_PASSIVE);
8327 player.addPassiveBuff(t);
8328 t.scheduleSyncRepeating(10, 10);
8329 /*
8330 * tm.schedule(t(world, -ENDURANCE, player,
8331 * gt_getTierByMetaValue(r.inkBlock,r.metaData)*15,
8332 * getUses(ENDURANCE, r.inkBlock,r.metaData)*10),//x10 for time
8333 * 1000,1000);
8334 */
8335 }
8336 return true;
8337 case LOGHIT: {
8338 DBG("Damage sensor rune activated", player);
8339 synchronized (positionRune) {
8340 rcm ee = getpr(r.x, r.y + 3, r.z, r.w);
8341 if (ee != null && ee.runePattern == LOGHIT)
8342 return false;
8343 }
8344 if (c("damage sensor", player, "set up a damage sensor"))
8345 return true;
8346 g = gg(world, r.x, r.y, r.z, r.runePattern, false);
8347 gd = gg(world, r.x, r.y, r.z, r.runePattern, true);
8348 vb = c_aliasTierZeroToAir(world, r.x, r.y - 1, r.z); // secondary
8349 // frequency,
8350 // I think
8351 rcm e = new rcm(LOGHIT, r.inkBlock, r.x, r.y + 3, r.z, r.w, g, gd,
8352 vb);
8353 if (!addpr_addPositionRune(e)) {
8354 player.ab(EnChat.YELLOW + "Something interferes.");
8355 return true;
8356 }
8357 player.ab(EnChat.GREEN
8358 + "This rune will send out automation signals on this signature");
8359 player.ab(EnChat.GREEN + "whenever the top block is hit.");
8360 /*
8361 * //signature blocks addpr(new rcm(2,r.b,
8362 * r.x+2,r.y,r.z,r.w,0,LOGHIT)); addpr(new rcm(2,r.b,
8363 * r.x-2,r.y,r.z,r.w,0,LOGHIT)); addpr(new rcm(2,r.b,
8364 * r.x,r.y,r.z+2,r.w,0,LOGHIT)); addpr(new rcm(2,r.b,
8365 * r.x,r.y,r.z-2,r.w,0,LOGHIT)); //redstone torch addpr(new
8366 * rcm(2,r.b, r.x,r.y,r.z,r.w,1,LOGHIT)); addpr(new rcm(2,r.b,
8367 * r.x,r.y-1,r.z,r.w,0,LOGHIT));
8368 */
8369 // remove the iron
8370 c(world, r.x, r.y + 1, r.z, 0);
8371 c(world, r.x, r.y + 2, r.z, 0);
8372 return true;
8373 }
8374 case LOGHITE: {
8375 DBG("Damage sensor rune2 activated", player);
8376 if (c("damage sensor", player, "set up a damage sensor"))
8377 return true;
8378 g = gg(world, r.x, r.y - 2, r.z, r.runePattern, false);
8379 gd = gg(world, r.x, r.y - 2, r.z, r.runePattern, true);
8380 vb = c_aliasTierZeroToAir(world, r.x, r.y - 1, r.z);
8381 f_addMagicToPlayer(player, EnChat.GREEN
8382 + "The block you place will be a damage sensor", LOGHITE,
8383 TP_RIGHTCLICK.getCode(), r.toolArmorType, 1, r.inkBlock, g,
8384 gd, vb);
8385 //
8386 c(world, r.x, r.y - 1, r.z, 0);
8387 c(world, r.x, r.y, r.z, 0);
8388 return true;
8389
8390 }
8391
8392 case LOGRED: {
8393 synchronized (positionRune) {
8394 rcm ee = getpr(r.x, r.y + 3, r.z, r.w);
8395 if (ee != null && ee.runePattern == LOGRED)
8396 return false;
8397 }
8398 if (c("redstone sensor", player, "set up a redstone sensor"))
8399 return true;
8400 g = gg(world, r.x, r.y - 1, r.z, r.runePattern, false);
8401 gd = gg(world, r.x, r.y - 1, r.z, r.runePattern, true);
8402 vb = c_aliasTierZeroToAir(world, r.x, r.y, r.z);
8403 rcm e = new rcm(LOGRED, 0, r.x, r.y, r.z, r.w, g, gd, vb);
8404 if (addpr_addPositionRune(e)) {
8405 player.ab(EnChat.GREEN
8406 + "This rune will send out automation signals on this signature");
8407 player.ab(EnChat.GREEN + "when the redstone current changes.");
8408 } else {
8409 synchronized (positionRune) {
8410 if (positionRune.get(e).runePattern != LOGRED) {
8411 player.ab(EnChat.YELLOW + "Something interferes.");
8412 return true;
8413 }
8414 positionRune.put(e, e);
8415 player.ab(EnChat.YELLOW + "Signature changed.");
8416 }
8417 }
8418 // signature blocks
8419 /*
8420 * addpr(new rcm(2,r.b, r.x+1,r.y-1,r.z,r.w,0,LOGRED)); addpr(new
8421 * rcm(2,r.b, r.x-1,r.y-1,r.z,r.w,0,LOGRED)); addpr(new rcm(2,r.b,
8422 * r.x,r.y-1,r.z+1,r.w,0,LOGRED)); addpr(new rcm(2,r.b,
8423 * r.x,r.y-1,r.z-1,r.w,0,LOGRED)); //column addpr(new rcm(2,r.b,
8424 * r.x,r.y-1,r.z,r.w,0,LOGRED)); addpr(new rcm(2,r.b,
8425 * r.x,r.y,r.z,r.w,1,LOGRED)); //center addpr(new rcm(2,r.b,
8426 * r.x,r.y+1,r.z,r.w,0,LOGRED));
8427 */
8428 return true;
8429 }
8430 case LOGSRED: {
8431 synchronized (positionRune) {
8432 rcm ee = getpr(r.x, r.y + 3, r.z, r.w);
8433 if (ee != null && ee.runePattern == LOGSRED)
8434 return false;
8435 }
8436 if (c("sticky redstone sensor", player,
8437 "set up a sticky redstone sensor"))
8438 return true;
8439 g = gg(world, r.x, r.y - 1, r.z, r.runePattern, false);
8440 gd = gg(world, r.x, r.y - 1, r.z, r.runePattern, true);
8441 vb = c_aliasTierZeroToAir(world, r.x, r.y, r.z);
8442 rcm e = new rcm(LOGSRED, 0, r.x, r.y, r.z, r.w, g, gd, vb);
8443 if (addpr_addPositionRune(e)) {
8444 player.ab(EnChat.GREEN
8445 + "This rune will resonate throughout the Aether on this");
8446 player.ab(EnChat.GREEN
8447 + "signature when the redstone current changes.");
8448 } else {
8449 synchronized (positionRune) {
8450 if (positionRune.get(e).runePattern != LOGSRED) {
8451 player.ab(EnChat.YELLOW + "Something interferes.");
8452 return true;
8453 }
8454 positionRune.put(e, e);
8455 player.ab(EnChat.YELLOW + "Signature changed.");
8456 }
8457 }
8458 // signature blocks
8459 /*
8460 * addpr(new rcm(2,r.b, r.x+1,r.y-1,r.z,r.w,0,LOGRED)); addpr(new
8461 * rcm(2,r.b, r.x-1,r.y-1,r.z,r.w,0,LOGRED)); addpr(new rcm(2,r.b,
8462 * r.x,r.y-1,r.z+1,r.w,0,LOGRED)); addpr(new rcm(2,r.b,
8463 * r.x,r.y-1,r.z-1,r.w,0,LOGRED)); //column addpr(new rcm(2,r.b,
8464 * r.x,r.y-1,r.z,r.w,0,LOGRED)); addpr(new rcm(2,r.b,
8465 * r.x,r.y,r.z,r.w,1,LOGRED)); //center addpr(new rcm(2,r.b,
8466 * r.x,r.y+1,r.z,r.w,0,LOGRED));
8467 */
8468 return true;
8469 }
8470 case LOGDST: {
8471 if (!player.isPlayer())
8472 return false;
8473 if (c("automation designator", player,
8474 "enchanted an automation designator"))
8475 return true;
8476 g = gg(world, r.x, r.y, r.z, r.runePattern, false);
8477 gd = gg(world, r.x, r.y, r.z, r.runePattern, true);
8478 vb = c_aliasTierZeroToAir(world, r.x, r.y + 1, r.z);
8479 r_removeEnchantmentFromToolType(TP_RIGHTCLICK, r.toolArmorType,
8480 player);
8481 f_addMagicToPlayer(
8482 player,
8483 EnChat.GREEN
8484 + "Activate a rune with this tool to designate it for automation",
8485 r.runePattern, 0, r.toolArmorType, 1, g, gd, vb);
8486 player.ab(EnChat.GREEN + "with this signature"
8487 + (vb > 0 ? " and key." : "."));
8488 c(world, r, 3, 3, 1);
8489 c(world, r, 3, 3, 0);
8490 return true;
8491 }
8492 case FLOTILLA:
8493 case FLOTILLA + 1: {
8494 if (!player.isPlayer())
8495 return false;
8496 if (c("flotilla", player, r.inkBlock))
8497 return true;
8498 r_removeEnchantmentFromToolType(TP_RIGHTCLICK, r.toolArmorType,
8499 player);
8500 f_addMagicToPlayer(player, EnChat.GREEN
8501 + "Put the bowl on water and let it grow.", FLOTILLA, 0,
8502 r.toolArmorType, getUses(FLOTILLA, r.inkBlock, r.metaData));
8503 c(world, r, 3, 3);
8504 r.y++;
8505 c(world, r, 3, 3);
8506 return true;
8507 }
8508 case LIGHTBOW:
8509 case REDLIGHTBOW:
8510
8511 {
8512 if (!player.isPlayer())
8513 return false;
8514 if (c("bow of light", player, r.inkBlock))
8515 return true;
8516 r_removeEnchantmentFromToolType(TP_ARROWLAUNCH, r.toolArmorType,
8517 player);
8518
8519 f_addMagicToPlayer(player, EnChat.GREEN
8520 + "Shoot torches with this bow.", LIGHTBOW,
8521 TP_ARROWLAUNCH.getCode(), r.toolArmorType,
8522 getUses(LIGHTBOW, r.inkBlock, r.metaData),
8523 r.runePattern == LIGHTBOW ? TORCH : RS_TORCH);
8524
8525 c(world, r, 3, 3);
8526 return true;
8527 }
8528 case GLOWARROWBOW: // functions as the Siege Bow >:3
8529 {
8530 if (!player.isPlayer())
8531 return false;
8532 if (c(runeIdToRuneNameTable.get(r.runePattern), player, r.inkBlock))
8533 return true;
8534 r_removeEnchantmentFromToolType(TP_ARROWLAUNCH, r.toolArmorType,
8535 player);
8536 f_addMagicToPlayer(
8537 player,
8538 EnChat.GREEN
8539 + "This bow will wrap your arrows in gunpowder for a more impressive effect.",
8540 r.runePattern, TP_ARROWLAUNCH.getCode(), r.toolArmorType,
8541 getUses(r.runePattern, r.inkBlock, r.metaData),
8542 gt_getTierByMetaValue(r.inkBlock, r.metaData) * 5);
8543 c(world, r, 1, 1); // tackle the TNT first to prevent it detonating
8544 // on a redstone update caused by the following
8545 c(world, r, 3, 3);
8546
8547 return true;
8548 }
8549 case MULTIBOW: {
8550 if (!player.isPlayer())
8551 return false;
8552 if (c("multishot", player, r.inkBlock))
8553 return true;
8554 r_removeEnchantmentFromToolType(TP_ARROWLAUNCH, r.toolArmorType,
8555 player);
8556 f_addMagicToPlayer(player, EnChat.GREEN
8557 + "Shoot multiple arrows with this bow.", MULTIBOW,
8558 TP_ARROWLAUNCH.getCode(), r.toolArmorType,
8559 getUses(MULTIBOW, r.inkBlock, r.metaData), 4);// fixed +4
8560 // arrows
8561 c(world, r, 5, 5);
8562 return true;
8563 }
8564 case TRANSLOCATOR:// TODO T6 this is broken, no teleport happens
8565 case TRANSLOCATOR + 1: {
8566 // DBG("Translocator arrived", pl);
8567 if (!player.isPlayer())
8568 return false;
8569 if (c("bow of translocation", player, r.inkBlock))
8570 return true;
8571 r_removeEnchantmentFromToolType(TP_ARROWLAUNCH, r.toolArmorType,
8572 player);
8573 f_addMagicToPlayer(
8574 player,
8575 EnChat.GREEN
8576 + "Fire this bow to teleport to the place the arrow lands.",
8577 TRANSLOCATOR, TP_ARROWLAUNCH.getCode(), r.toolArmorType,
8578 getUses(TRANSLOCATOR, r.inkBlock, r.metaData),
8579 gt_getTierByMetaValue(r.inkBlock, r.metaData));
8580 c(world, r, 5, 5);
8581 return true;
8582 }
8583 case FTP:
8584 case WALLFTP:
8585 case WALLFTP + 1: {
8586 if (APRIL_FOOLS) {
8587 player.ab(EnChat.RED + "I'm sorry " + player.aw_getName()
8588 + ", I can't let you do that.");
8589 break;
8590 }
8591 return FTP(r, player, world);
8592
8593 }
8594 case FAITHPOINT:
8595 case WALLFPOINT:
8596 case WALLFPOINT + 1: {
8597 if (!chkfaithpoint(r)) {
8598 player.ab(EnChat.RED + "The aether is confused by the signature!");
8599 return true;
8600 }
8601
8602 if (dir == -1) // redstone handling
8603 {
8604
8605 // 0(down) 1(up) 2(east) 3(west) 4(north) 5(south)
8606 // y-1 y+1 x+1 x-1 z-1 z+1
8607 if (r.runePattern == WALLFPOINT) // ns
8608 {
8609 rcm p1 = b(world, r.x, r.y, r.z, 5); // south +z
8610 rcm p2 = b(world, r.x, r.y, r.z, 4); // north -z
8611 int diff1 = -(p1.z - r.z);
8612 int diff2 = p2.z - r.z;
8613 dir = (diff2 >= diff1 ? 4 : 5);
8614 DBG("NS Dir decided to be " + dirs(dir) + dir
8615 + ", diffs are [" + r.z + "][" + p1.z + "," + p2.z
8616 + "][" + diff1 + "," + diff2 + "]");
8617 } else if (r.runePattern == WALLFPOINT + 1) {
8618 rcm p1 = b(world, r.x, r.y, r.z, 2);
8619 rcm p2 = b(world, r.x, r.y, r.z, 3);
8620 int diff1 = -(p1.x - r.x);
8621 int diff2 = p2.x - r.x;
8622 dir = (diff2 >= diff1 ? 3 : 2);
8623 DBG("Dir decided to be " + dirs(dir) + ", diffs are ["
8624 + r.x + "][" + p1.x + "," + p2.x + "][" + diff1
8625 + "," + diff2 + "]");
8626 } else if (r.runePattern == FAITHPOINT) {
8627 {
8628 int diff1 = (r.y - b(world, r.x, r.y, r.z, 0).y);
8629 int diff2 = -(r.y - b(world, r.x, r.y, r.z, 1).y);
8630 dir = diff2 > diff1 ? 0 : 1;
8631 DBG("Dir decided to be " + dirs(dir) + ", diffs are "
8632 + diff1 + "|" + diff2);
8633 }
8634 }
8635 }
8636
8637 g = gg(world, r.x, r.y, r.z, r.runePattern, false);
8638 if (!wsigc(player, g)) {
8639 return true;
8640 }
8641 gd = gg(world, r.x, r.y, r.z, r.runePattern, true);
8642 if (g == 0)
8643 return false;
8644 if (rlc("enable travel ink"))
8645 if (!rlc("ink " + r.inkBlock)) {
8646 player.ab(EnChat.RED
8647 + "The aether demands that this rune be made with a");
8648 player.ab(EnChat.RED + "different material!");
8649 return true;
8650 }
8651 if (c("faithpoint", player, "set up a faithpoint", r.inkBlock))
8652 return true;
8653
8654 int[] iaa = gacwp_getWaypointCoordinatesBySignature(g, gd); // get
8655 // waypoint
8656 // desc
8657 if (iaa != null) {
8658 if (iaa[2] == r.x && iaa[3] == r.y && iaa[4] == r.z
8659 && iaa[5] == r.w) {
8660 player.ab(EnChat.RED
8661 + "This faithpoint is already established.");
8662 DBG("This faithpoint signature is " + g + "," + gd);
8663 DBG("coords are [" + r.x + "," + r.y + "," + r.z + "]");
8664 } else
8665 player.ab(EnChat.RED
8666 + "This signature has been used. Try another.");
8667 return true;
8668 }
8669
8670 for (int i = 0; i < waypointList.size(); i++) {
8671 RunePoint newwp = waypointList.get(i);
8672 rcm newwpco = newwp.getCords();
8673 if (newwpco.x == r.x && newwpco.y == r.y && newwpco.z == r.z
8674 && newwpco.w == r.w) {
8675
8676 if (g == newwp.getSig() && gd == newwp.getSigData()) {
8677 player.ab(EnChat.RED
8678 + "This faithpoint is already established.");
8679 DBG("This faithpoint signature is " + g + "," + gd);
8680 DBG("coords are [" + r.x + "," + r.y + "," + r.z + "]");
8681 } else {
8682 // DBG("Faithpoint altered at ["+r.x+","+r.y+","+r.z+","+r.w+"]",pl);
8683 // get the FWPL with the established signature
8684
8685 newwp.setSig(g);
8686 newwp.setSig(gd);
8687 newwp.setFacing(dir);
8688 s_saveToMagicDat();
8689 dirs = dirs(dir, false);
8690
8691
8692 player.ab(EnChat.GREEN
8693 + "You have changed the signature of this faithpoint, that faces "
8694 + dirs + ".");
8695 player.ab(EnChat.YELLOW
8696 + "The faithpoint signature is no longer needed here.");
8697 }
8698 return true;
8699 }
8700 }
8701
8702
8703
8704 // DBG("Faithpoint opened at ["+r.x+","+r.y+","+r.z+","+r.w+"]",pl);
8705 waypointList.add(new WP_WayPoint(r,g,gd,dir,this));
8706 s_saveToMagicDat();
8707 // addpr(new rcm(FAITHPOINT,41, r.x,r.y,r.z,r.w, 1,1));
8708 player.ab(EnChat.GREEN
8709 + "A large opening has been created in the fabric of the aether, facing "
8710 + dirs(dir));
8711 player.ab(EnChat.YELLOW
8712 + "The faithpoint signature is no longer needed here.");
8713 return true;
8714 }
8715 case CTRI: {// \u00A7K
8716
8717 if (c("Immersion", player, r.inkBlock))
8718 return true;
8719
8720 if (player.Pc() == 371) {
8721 if (dbgl.contains(player.aw_getName())) {
8722 dbgl.remove(player.aw_getName());
8723 player.ab(EnChat.YELLOW + "You immerse yourself");
8724 } else {
8725 dbgl.add(player.aw_getName());
8726 player.ab(EnChat.YELLOW
8727 + "You feel immersion shatter around you");
8728 } // */
8729 } else if (dbgl.contains(player.aw_getName()) && player.Pc() == 388) {
8730 r_removeEnchantmentFromToolType(TP_RIGHTCLICK, r.toolArmorType,
8731 player);
8732 f_addMagicToPlayer(
8733 player,
8734 EnChat.GREEN
8735 + "strange numbers appear over blocks. You have no idea what they mean.",
8736 r.runePattern, 0, r.toolArmorType,
8737 getUses(RECALL, 4, 0));
8738 } else if (dbgl.contains(player.aw_getName()) && player.Pc() == 370) {
8739
8740 int fi[] = null;
8741 for (final int[] ta : faithRuneList) {
8742 if (ta[4] == r.w
8743 && radiuscheck(ta[0], ta[1], ta[2], r.x, r.y, r.z,
8744 ta[3] + 0.5)) {
8745 player.ab(EnChat.YELLOW
8746 + "Faith locked. Plotting cardinal points.");
8747 DBG("connected island is [" + EnChat.YELLOW + ta[0] + ","
8748 + ta[1] + "," + ta[2] + "," + ta[4]
8749 + "], radius [" + ta[3] + "]", player);
8750 fi = ta;
8751 break;
8752 }
8753 }
8754 if (fi == null) {
8755 DBG("Failed to find a faith island");
8756 return true;
8757 }
8758 int mod = (int) Math.sqrt(((fi[3] * fi[3]) / 3));
8759 DBG("Outputting gold to [" + fi[0] + "," + fi[1] + "," + fi[2]
8760 + "]");
8761 world.e(fi[0], fi[1], fi[2], 41);
8762
8763 world.e(fi[0] + fi[3], fi[1], fi[2], 4);
8764 world.e(fi[0] + mod, fi[1] + mod, fi[2] + mod, 4);
8765 world.e(fi[0] - mod, fi[1] + mod, fi[2] + mod, 4);
8766 world.e(fi[0] - fi[3], fi[1], fi[2], 4);
8767 world.e(fi[0] + mod, fi[1] + mod, fi[2] - mod, 4);
8768 world.e(fi[0] - mod, fi[1] + mod, fi[2] - mod, 4);
8769 world.e(fi[0], fi[1] + fi[3], fi[2], 4);
8770 world.e(fi[0] + mod, fi[1] - mod, fi[2] + mod, 4);
8771 world.e(fi[0] - mod, fi[1] - mod, fi[2] + mod, 4);
8772 world.e(fi[0], fi[1] - fi[3], fi[2], 4);
8773 world.e(fi[0] + mod, fi[1] - mod, fi[2] - mod, 4);
8774 world.e(fi[0] - mod, fi[1] - mod, fi[2] - mod, 4);
8775 world.e(fi[0], fi[1], fi[2] + fi[3], 4);
8776 world.e(fi[0], fi[1], fi[2] - fi[3], 4);
8777 // */
8778
8779 } else if(dbgl.contains(player.aw_getName()) && player.Pc() == 369) {
8780
8781 /*String worldName = "";
8782 EmptyWorldBuilder newWorld = new EmptyWorldBuilder(this);
8783 RuneWorld newRW = newWorld.getWorld();
8784 registerWorld(newRW);
8785
8786 DBG("Success? ["+newRW.getWorldId()+"]");
8787 newRW.e(0, 64, 0, BEDROCK);
8788 aa(player,newRW, 0D, 66D, 0D,player.v(), player.w());
8789 //RunePoint Dime = new DimensionalAnchorPoint()
8790 */
8791 /* int counter = 0;
8792 for (File fs : new File(".").listFiles())
8793 {
8794 DBG(fs.getPath());
8795 if (fs.getPath().startsWith("." + File.separator + "RunecraftGenesis_"))
8796 {
8797 //Runecraft.self.getServer().createWorld(new WorldCreator(fs.getPath().substring(2)));
8798 //DBG(Chat.YELLOW+"Creating world "+fs.getPath().substring(2));
8799 }
8800 } //*/
8801
8802 }
8803 else {
8804
8805 if (world.a(r.x, r.y + 1, r.z) == 0) // block above is empty,
8806 // set to water and go
8807 // above
8808 {
8809 if (world.a(r.x, r.y + 2, r.z) == 0) {
8810 world.eSilently(r.x, r.y + 1, r.z, STAT_WATER, 8);
8811 world.eSilently(r.x, r.y + 2, r.z, WATER, 8);
8812 world.eSilently(r.x, r.y + 1, r.z - 1, STAT_WATER, 7);
8813 world.eSilently(r.x, r.y + 1, r.z + 1, STAT_WATER, 7);
8814 world.eSilently(r.x - 1, r.y + 1, r.z, STAT_WATER, 7);
8815 world.eSilently(r.x + 1, r.y + 1, r.z, STAT_WATER, 7);
8816 player.ab(EnChat.YELLOW + "Water splashes into your eyes");
8817 player.ade(15, 50, 1);
8818 } else {
8819 world.eSilently(r.x, r.y + 1, r.z, 8, 8);
8820 }
8821
8822 }
8823
8824 }
8825
8826 /*
8827 * if (c("Superfaith + FTP",player,r.inkBlock)) return true; boolean
8828 * burned = false; synchronized (faithRuneList) { for (int i = 0; i
8829 * < faithRuneList.size(); i ++) { int fi[] = faithRuneList.get(i);
8830 * if (fi[3] == 128) { faithRuneList.remove(fi); burned = true;
8831 * DBG("Burned a superfaith"); } } } if (burned) {
8832 * s_saveToMagicDat(); return false;} int[] ta =
8833 * gacwp_getWaypointCoordinatesBySignature(-1970632054, 0); if (ta
8834 * == null){DBG("Super FTP destination not found");break;} int[] fi
8835 * = {r.x,r.y,r.z,128,r.w}; int grd = 128 +1; RuneWorld world2 =
8836 * getWorldById(ta[5]); world.e(r.x,r.y,r.z,0); for (int x = -grd; x
8837 * < grd+1; x++) for (int z = -grd; z < grd+1; z++){ for (int y =
8838 * -grd; y < grd+1; y++) { double pos =
8839 * (Math.sqrt((x*x)+(y*y)+(z*z)));
8840 *
8841 * if (pos >= grd-0.5 && pos <= grd+0.5 && (y > 0 && y <256 )) { int
8842 * fb =world2.a(ta[2]+x,ta[3]+y,ta[4]+z); if (fb == 0 || fb ==
8843 * TALL_GRASS || fb == SNOW) { //addpr_addPositionRune(new rcm(FTP,
8844 * GLASS,fi[0]+x,fi[1]+y,fi[2]+z, world.getWorldId(),0, 0));
8845 *
8846 * //world2.e(ta[2]+x,ta[3]+y,ta[4]+z,20); ; } int tb =
8847 * world.a(r.x+x,r.y+y,r.z+z); if (tb == 0 || tb == TALL_GRASS || tb
8848 * == SNOW) {
8849 *
8850 * addpr_addPositionRune(new rcm(FTP, GLASS,ta[2]+x,ta[3]+y,ta[4]+z,
8851 * ta[5],0, 0)); world.e(r.x+x,r.y+y,r.z+z,20); } } }}//pl.ab(str);
8852 * str = "";
8853 *
8854 * rct t =
8855 * t(world,115,player,ta[2],ta[3],ta[4],ta[5],fi[0],fi[1],fi[
8856 * 2],fi[3],fi[3],faithRuneList.size()); faithRuneList.add(fi);
8857 * t.scheduleSyncRepeating(7, 7);
8858 *
8859 * /*for(int[] ta : whisperSourceList) {
8860 * DBG(Chat.BLUE+"whisper curse ["
8861 * +Chat.YELLOW+ta[0]+","+ta[1]+","+ta[2]+","+ta[3]+Chat.BLUE+"]");
8862 * }
8863 */
8864 /*
8865 * if (c("Itemframe tester",player,r.b)) return true; { Object[] hes
8866 * = world.getHangingEntities(r.x, r.y, r.z, 10, 10, 10);
8867 *
8868 * DBG("hanging entities size:"+hes.length,player); Object[] mobs =
8869 * world.getMobs(r.x, r.y, r.z, 10, 10, 10, true); for (Object obj :
8870 * mobs) {
8871 *
8872 *
8873 * }
8874 *
8875 * }
8876 *
8877 *
8878 * //
8879 */
8880
8881 /*
8882 * rcm ch = new rcm(r.x >> 4, 0, r.z >> 4,r.w); precs.add(ch);
8883 * DBG(Chat.YELLOW+"Saved chunk [" +(ch.x)+",0,"+(ch.z)+","+ch.w);
8884 * //
8885 */
8886 /*
8887 * wpl.clear(); DBG("Immersion tester",pl); f(pl, Chat.GREEN +
8888 * "You can now look REALLY HARD at tile entites", CTRI,0,r.t,1);//
8889 */
8890
8891 // curseID, curseTier,hextier
8892 return true;
8893 }/**/
8894 case TEMPRUNE: {
8895 /*
8896 * if (c("Superfaith + FTP",player,r.inkBlock)) return true; boolean
8897 * burned = false; synchronized (faithRuneList) { for (int i = 0; i
8898 * < faithRuneList.size(); i ++) { int fi[] = faithRuneList.get(i);
8899 * if (fi[3] == 128) { faithRuneList.remove(fi); burned = true;
8900 * DBG("Burned a superfaith"); } } } if (burned) {
8901 * s_saveToMagicDat(); return false;} int[] ta =
8902 * gacwp_getWaypointCoordinatesBySignature(-1970632054, 0); if (ta
8903 * == null){DBG("Super FTP destination not found");break;} int[] fi
8904 * = {r.x,r.y,r.z,128,r.w}; int grd = 128 +1; RuneWorld world2 =
8905 * getWorldById(ta[5]); world.e(r.x,r.y,r.z,0); for (int x = -grd; x
8906 * < grd+1; x++) for (int z = -grd; z < grd+1; z++){ for (int y =
8907 * -grd; y < grd+1; y++) { double pos =
8908 * (Math.sqrt((x*x)+(y*y)+(z*z)));
8909 *
8910 * if (pos >= grd-0.5 && pos <= grd+0.5 && (y > 0 && y <256 )) { int
8911 * fb =world2.a(ta[2]+x,ta[3]+y,ta[4]+z); if (fb == 0 || fb ==
8912 * TALL_GRASS || fb == SNOW) { //addpr_addPositionRune(new rcm(FTP,
8913 * GLASS,fi[0]+x,fi[1]+y,fi[2]+z, world.getWorldId(),0, 0));
8914 *
8915 * //world2.e(ta[2]+x,ta[3]+y,ta[4]+z,20); ; } int tb =
8916 * world.a(r.x+x,r.y+y,r.z+z); if (tb == 0 || tb == TALL_GRASS || tb
8917 * == SNOW) {
8918 *
8919 * addpr_addPositionRune(new rcm(FTP, GLASS,ta[2]+x,ta[3]+y,ta[4]+z,
8920 * ta[5],0, 0)); world.e(r.x+x,r.y+y,r.z+z,20); } } }}//pl.ab(str);
8921 * str = "";
8922 *
8923 * rct t =
8924 * t(world,115,player,ta[2],ta[3],ta[4],ta[5],fi[0],fi[1],fi[
8925 * 2],fi[3],fi[3],faithRuneList.size()); faithRuneList.add(fi);
8926 * t.scheduleSyncRepeating(7, 7);
8927 */
8928 return true;
8929 }
8930
8931 case CTRI2: {
8932 if (c("faith wrencher", player, r.inkBlock))
8933 return true;
8934
8935 final int fiid = findFaithIsland(r.x, r.y, r.z, r.w);
8936
8937 if (fiid < 0) {
8938 player.ab(EnChat.RED
8939 + "The wrencher cannot find anything to move");
8940 return true;
8941 }
8942 if (mfrl.contains("" + fiid)) {
8943 player.ab(EnChat.RED + "This land is moving!");
8944 return true;
8945 }
8946
8947 int[] pdir = { 0, 0, 0 };
8948 pdir = RCT_main.dir(dir);
8949
8950 final int[] fi = faithRuneList.get(fiid);
8951 fi[0] += pdir[0];
8952 fi[1] += pdir[1];
8953 fi[2] += pdir[2];
8954
8955 player.ab(EnChat.YELLOW + "Faith island " + fiid + " moved "
8956 + dirs(dir, true) + " to: [" + fi[0] + "," + fi[1] + ","
8957 + fi[2] + "]");
8958
8959 return true;
8960 }
8961 case PERMANENCE: {
8962 // pl.ab("right click permanence");
8963
8964 // check tool enchantments
8965 for (final EnAction i : EnAction.primaryActions) {
8966 int[] ta = player.gench(i);
8967 if (ta != null) {
8968 if (ta[3] != RCT_main.PERMANENT_USES) {
8969 // check permissions
8970 if (c("permanence", player, r.inkBlock))
8971 return true;
8972
8973 // make tool permanent
8974 player.sench(ta[0], EnAction.fromCode(ta[1]), ta[2],
8975 RCT_main.PERMANENT_USES,
8976 Arrays.copyOfRange(ta, 4, ta.length));
8977
8978 String nm = RCT_main.gtrn(ta[0]);
8979 if (nm == null)
8980 nm = runeIdToRuneNameTable.get(ta[0]);
8981 if (nm == null)
8982 nm = "unknown";
8983
8984 player.ab(EnChat.YELLOW + nm
8985 + " was forever bound to this tool.");
8986
8987 // consume rune
8988 c(world, r, 11, 11);
8989 } else {
8990 player.ab("This tool is already permanent.");
8991 }
8992 return true;
8993 }
8994 }
8995 if (r.toolArmorType == 0) {
8996 player.ab(EnChat.YELLOW + "Your hand is not enchanted");
8997 } else
8998 player.ab(EnChat.YELLOW + "This tool not enchanted");
8999 return true;
9000 }
9001 case SPIDERTOUCH:
9002 case SPIDERTOUCH + 1: {
9003 if (!player.isPlayer())
9004 return false;
9005 // check permissions
9006 if (c("spider touch rune" + EnChat.GREEN, player, r.inkBlock))
9007 return true;
9008 // consume rune
9009 c(world, r, 5, 5);
9010 // remove tool's old enchant
9011 r_removeEnchantmentFromToolType(TP_BROKEN, r.toolArmorType, player);
9012 // add new enchantment
9013 f_addMagicToPlayer(player, EnChat.GREEN
9014 + "You can now harvest web with shears.", SPIDERTOUCH, 3,
9015 r.toolArmorType,
9016 getUses(SPIDERTOUCH, r.inkBlock, r.metaData));
9017 return true;
9018 }
9019 case XYVAZ: {
9020 if (c("Xyvaz's rune" + EnChat.GREEN, player, r.inkBlock))
9021 return true;
9022 return true;
9023 }
9024 case PROMETHEUS:
9025 case PROMETHEUS + 1:// TODO make chainmail very valuable by allowing
9026 // chainmail to block Black Magic via the True Name
9027 // swap
9028 {
9029 if (c("Prometheus rune" + EnChat.GREEN, player, r.inkBlock))
9030 return true;
9031 if (getUses(PROMETHEUS, r.inkBlock, r.metaData) == 0) {
9032 player.ab("Your offering is insignificant next to the power of Fire.");
9033 return false;
9034 }
9035 c(world, r, 5, 5);
9036 world.s(r.x, r.y, r.z, Runecraft_MAIN.FIRE,
9037 getUses(PROMETHEUS, r.inkBlock, r.metaData), (short) 0);
9038 // player.rfhs(377, 1);//this rune is now balanced so that it does
9039 // not need blaze powder
9040
9041 return true;
9042 }
9043 case MAGICCAKE: {
9044 DBG("Cake activated", player);
9045
9046 if (!c("Magic Cake rune" + EnChat.GREEN, player, r.inkBlock)) {
9047 if (world.b(r.x - 1, r.y, r.z + 1) == 7
9048 && world.b(r.x, r.y, r.z + 1) == 7
9049 && world.b(r.x + 1, r.y, r.z + 1) == 7) {
9050 c(world, r, 3, 3);
9051 world.e(r.x, r.y, r.z, 42);
9052 world.s(r.x, r.y + 1, r.z, 92, 1, (short) 0);
9053 player.rfhs(344, 1);
9054 return true;
9055 }
9056
9057 else
9058 player.ab(EnChat.RED + "Wheat is not ready.");
9059 }
9060 return true; // prevent egg being thrown
9061 }
9062 case PEGASUS - 1:
9063 case PEGASUS:
9064
9065 {
9066
9067 if (APRIL_FOOLS) {
9068 player.ab(EnChat.RED + "I'm sorry " + player.aw_getName()
9069 + ", I can't let you do that.");
9070 break;
9071 }
9072 // boolean nothingToSeeHere = true;
9073 // return nothingToSeeHere;
9074
9075 int[] pdir = { 0, 0, 0 };
9076
9077 int xi, yi, zi;
9078 xi = yi = zi = 1;
9079
9080 if (c("Pegasus", player, r.inkBlock))
9081 return true;
9082
9083 final int fiid = findFaithIsland(r.x, r.y, r.z, r.w);
9084
9085 if (fiid < 0) {
9086 player.ab(EnChat.RED
9087 + "The land around you is not stable enough to travel");
9088 return true;
9089 }
9090
9091 if (mfrl.contains("" + fiid)) {
9092 player.ab(EnChat.RED + "This land is already moving!");
9093 return true;
9094 }
9095
9096 if (wdc(r, WardType.Teleport)) {
9097 player.ab(EnChat.RED
9098 + "There is a ward enveloping this rune. It cannot move the Faith Island");
9099 return true;
9100 }
9101
9102 final int[] fi = faithRuneList.get(fiid);
9103
9104 if (checkForOverlappingMovingIsland(fi)) {
9105 player.ab(EnChat.RED + "The aether nearby is too tense!");
9106 return true;
9107 }
9108
9109 int rd = fi[3];
9110 int xs, ys, zs;
9111 xs = ys = zs = -rd;
9112 int xe, ye, ze;
9113 xe = ye = ze = rd + 1;
9114 int ctr = 0;
9115 int ft;
9116
9117 if (r.runePattern == PEGASUS - 1) // we have a direction, there can
9118 // be no other blocks with this
9119 // pattern (-14)
9120 {
9121 if (dir == -1) {
9122 player.ab(EnChat.RED + "The aether cannot read your mind!");
9123 return false;
9124 }
9125 pdir = RCT_main.dir(dir);
9126 ft = gt_getTier(r.toolArmorType);
9127 } else // option with where Pegasus has blocks in it
9128 {
9129 ft = 0;
9130 // 0(down) 1(up) 2(east) 3(west) 4(north) 5(south)
9131 // y-1 y+1 x+1 x-1 z-1 z+1
9132 if (gt_getTier(world.a(r.x - 1, r.y, r.z)) != 0) {
9133 ctr++;
9134 pdir[0] = 3;
9135 ft = gt_getTier(world.a(r.x - 1, r.y, r.z));
9136 } // OKAY, so if it's -x,
9137 if (gt_getTier(world.a(r.x + 1, r.y, r.z)) != 0) {
9138 ctr++;
9139 pdir[0] = 2;
9140 ft = gt_getTier(world.a(r.x + 1, r.y, r.z));
9141 }
9142 if (gt_getTier(world.a(r.x, r.y - 1, r.z)) != 0) {
9143 ctr++;
9144 pdir[0] = 0;
9145 ft = gt_getTier(world.a(r.x, r.y - 1, r.z));
9146 }
9147 if (gt_getTier(world.a(r.x, r.y + 1, r.z)) != 0) {
9148 ctr++;
9149 pdir[0] = 1;
9150 ft = gt_getTier(world.a(r.x, r.y + 1, r.z));
9151 }
9152 if (gt_getTier(world.a(r.x, r.y, r.z - 1)) != 0) {
9153 ctr++;
9154 pdir[0] = 4;
9155 ft = gt_getTier(world.a(r.x, r.y, r.z - 1));
9156 }
9157 if (gt_getTier(world.a(r.x, r.y, r.z + 1)) != 0) {
9158 ctr++;
9159 pdir[0] = 5;
9160 ft = gt_getTier(world.a(r.x, r.y, r.z + 1));
9161 }
9162 if (ctr > 1) {
9163 player.ab(EnChat.RED + "The aether cannot read your mind!");
9164 return false;
9165 }
9166 pdir = RCT_main.dir(pdir[0]);
9167
9168 }
9169
9170 if (ctr == 0 && ft == 0) {
9171 player.ab(EnChat.GREEN
9172 + "Activate this rune with a fuel block, or having placed fuel in a slot!");
9173 return true;
9174 }
9175
9176 // DBG("Escaped with pdir and ft processed",pl);
9177
9178 final int inkTier = gt_getTier(r.inkBlock);
9179 pdir[0] = pdir[0] * inkTier * inkTier * ft;
9180 int tx = fi[0] + pdir[0];
9181 pdir[1] = pdir[1] * inkTier * inkTier * ft;
9182 int ty = fi[1] + pdir[1];
9183 pdir[2] = pdir[2] * inkTier * inkTier * ft;
9184 int tz = fi[2] + pdir[2];
9185 DBG("Distance to be travelled = " + EnChat.YELLOW
9186 + (pdir[0] + pdir[1] + pdir[2]), player);
9187
9188 // alright. If target in memory
9189 // { if distance < radius - small check
9190 // { if distance > radius - larger check
9191 // else out of memory
9192 // { load, check, FTP. }
9193
9194 if (wdc(new rcm((fi[0] + pdir[0]), (fi[1] + pdir[1]),
9195 (fi[2] + pdir[2]), r.w), WardType.Teleport)) {
9196 DBG("Blocked pegasus", player);
9197 player.ab(EnChat.RED
9198 + "There is a ward at your destination preventing teleportation");
9199 return false;
9200 }
9201 if (fi[1] + pdir[1] + fi[3] > 256 || fi[1] + pdir[1] - fi[3] < 0)
9202
9203 {
9204 player.ab(EnChat.RED
9205 + "This spell may not remove materials from the mortal plane...");
9206 DBG(fi[1] + ":" + pdir[1] + ":" + fi[3]);
9207 return false;
9208 }
9209 // perform banned items check
9210 for (int x = -rd; x < rd + 1; x++)
9211 for (int z = -rd; z < rd + 1; z++)
9212 for (int y = -rd; y < rd + 1; y++)
9213 if ((x * x) + (y * y) + (z * z) < (rd + 0.5)
9214 * (rd + 0.5)) {
9215 int sb = world.a(fi[0] + x, fi[1] + y, fi[2] + z);
9216 if (sb == 57) {// override allowing Chests,
9217 // Furnaces, and Dispensers to move.
9218 player.ab(EnChat.RED
9219 + "The aether has rejected your greedy request...");
9220 DBG("banned item [" + sb + "] is at ["
9221 + (fi[0] + x) + "," + (fi[1] + y) + ","
9222 + (fi[2] + z) + "]", player);
9223 return true;
9224 }
9225
9226 }
9227 // performing 14 cardinal point check
9228 // +X, -X, +Y, -Y, +Z, -Z
9229 int mod = (int) Math.sqrt(((rd * rd) / 3));
9230 if (world.try_bb(player, fi[0] + pdir[0], fi[1] + pdir[1], fi[2]
9231 + pdir[2])
9232 && world.try_bp(player, fi[0] + pdir[0], fi[1] + pdir[1],
9233 fi[2] + pdir[2], 1, 0)
9234 && world.try_bb(player, fi[0] + pdir[0] + fi[3], fi[1]
9235 + pdir[1], fi[2] + pdir[2])
9236 && world.try_bp(player, fi[0] + fi[3] + pdir[0], fi[1]
9237 + pdir[1], fi[2] + pdir[2], 1, 0)
9238 && world.try_bb(player, fi[0] + pdir[0] - fi[3], fi[1]
9239 + pdir[1], fi[2] + pdir[2])
9240 && world.try_bp(player, fi[0] - fi[3] + pdir[0], fi[1]
9241 + pdir[1], fi[2] + pdir[2], 1, 0)
9242 && world.try_bb(player, fi[0] + pdir[0], fi[1] + fi[3]
9243 + pdir[1], fi[2] + pdir[2])
9244 && world.try_bp(player, fi[0] + pdir[0], fi[1] + fi[3]
9245 + pdir[1], fi[2] + pdir[2], 1, 0)
9246 && world.try_bb(player, fi[0] + pdir[0], fi[1] - fi[3]
9247 + pdir[1], fi[2] + pdir[2])
9248 && world.try_bp(player, fi[0] + pdir[0], fi[1] - fi[3]
9249 + pdir[1], fi[2] + pdir[2], 1, 0)
9250 && world.try_bb(player, fi[0] + pdir[0], fi[1] + pdir[1],
9251 fi[2] + fi[3] + pdir[2])
9252 && world.try_bp(player, fi[0] + pdir[0], fi[1] + pdir[1],
9253 fi[2] + fi[3] + pdir[2], 1, 0)
9254 && world.try_bb(player, fi[0] + pdir[0], fi[1] + pdir[1],
9255 fi[2] - fi[3] + pdir[2])
9256 && world.try_bp(player, fi[0] + pdir[0], fi[1] + pdir[1],
9257 fi[2] - fi[3] + pdir[2], 1, 0)
9258 &&
9259
9260 world.try_bb(player, fi[0] + mod + pdir[0], fi[1] + mod
9261 + pdir[1], fi[2] + mod + pdir[2])
9262 && world.try_bp(player, fi[0] + mod + pdir[0], fi[1] + mod
9263 + pdir[1], fi[2] + mod + pdir[2], 1, 0)
9264 && world.try_bb(player, fi[0] - mod + pdir[0], fi[1] + mod
9265 + pdir[1], fi[2] + mod + pdir[2])
9266 && world.try_bp(player, fi[0] - mod + pdir[0], fi[1] + mod
9267 + pdir[1], fi[2] + mod + pdir[2], 1, 0)
9268 && world.try_bb(player, fi[0] + mod + pdir[0], fi[1] + mod
9269 + pdir[1], fi[2] - mod + pdir[2])
9270 && world.try_bp(player, fi[0] + mod + pdir[0], fi[1] + mod
9271 + pdir[1], fi[2] - mod + pdir[2], 1, 0)
9272 && world.try_bb(player, fi[0] - mod + pdir[0], fi[1] + mod
9273 + pdir[1], fi[2] - mod + pdir[2])
9274 && world.try_bp(player, fi[0] - mod + pdir[0], fi[1] + mod
9275 + pdir[1], fi[2] - mod + pdir[2], 1, 0) /**/
9276 &&
9277
9278 world.try_bb(player, fi[0] + mod + pdir[0], fi[1] - mod
9279 + pdir[1], fi[2] + mod + pdir[2])
9280 && world.try_bp(player, fi[0] + mod + pdir[0], fi[1] - mod
9281 + pdir[1], fi[2] + mod + pdir[2], 1, 0)
9282 && world.try_bb(player, fi[0] - mod + pdir[0], fi[1] - mod
9283 + pdir[1], fi[2] + mod + pdir[2])
9284 && world.try_bp(player, fi[0] - mod + pdir[0], fi[1] - mod
9285 + pdir[1], fi[2] + mod + pdir[2], 1, 0)
9286 && world.try_bb(player, fi[0] + mod + pdir[0], fi[1] - mod
9287 + pdir[1], fi[2] - mod + pdir[2])
9288 && world.try_bp(player, fi[0] + mod + pdir[0], fi[1] - mod
9289 + pdir[1], fi[2] - mod + pdir[2], 1, 0)
9290 && world.try_bb(player, fi[0] - mod + pdir[0], fi[1] - mod
9291 + pdir[1], fi[2] - mod + pdir[2])
9292 && world.try_bp(player, fi[0] - mod + pdir[0], fi[1] - mod
9293 + pdir[1], fi[2] - mod + pdir[2], 1, 0) /**/
9294
9295 ) {/* We are clear to enter */
9296 } else {
9297 player.ab(EnChat.RED
9298 + "An unknown force is preventing you from moving to there.");
9299 if (dbgl.contains(player.aw_getName())) {
9300 DBG("fis [" + (fi[0] + pdir[0]) + "," + (fi[1] + pdir[1])
9301 + "," + (fi[2] + pdir[2]) + "] [" + fi[3] + "]");
9302 if (!world.try_bb(player, fi[0] + pdir[0], fi[1] + pdir[1],
9303 fi[2] + pdir[2])
9304 || !world.try_bp(player, fi[0] + pdir[0], fi[1]
9305 + pdir[1], fi[2] + pdir[2], 1, 0)) {
9306 DBG("Failed Centre");
9307 }
9308 if (!world.try_bb(player, fi[0] + pdir[0] + fi[3], fi[1]
9309 + pdir[1], fi[2] + pdir[2])
9310 || !world.try_bp(player, fi[0] + fi[3] + pdir[0],
9311 fi[1] + pdir[1], fi[2] + pdir[2], 1, 0)) {
9312 DBG("Failed EAST");
9313 }
9314 if (!world.try_bb(player, fi[0] + pdir[0] - fi[3], fi[1]
9315 + pdir[1], fi[2] + pdir[2])
9316 || !world.try_bp(player, fi[0] - fi[3] + pdir[0],
9317 fi[1] + pdir[1], fi[2] + pdir[2], 1, 0)) {
9318 DBG("Failed WEST");
9319 }
9320 if (!world.try_bb(player, fi[0] + pdir[0], fi[1] + fi[3]
9321 + pdir[1], fi[2] + pdir[2])
9322 || !world.try_bp(player, fi[0] + pdir[0], fi[1]
9323 + fi[3] + pdir[1], fi[2] + pdir[2], 1, 0)) {
9324 DBG("Failed UP");
9325 }
9326 if (!world.try_bb(player, fi[0] + pdir[0], fi[1] - fi[3]
9327 + pdir[1], fi[2] + pdir[2])
9328 || !world.try_bp(player, fi[0] + pdir[0], fi[1]
9329 - fi[3] + pdir[1], fi[2] + pdir[2], 1, 0)) {
9330 DBG("Failed DOWN");
9331 }
9332 if (!world.try_bb(player, fi[0] + pdir[0], fi[1] + pdir[1],
9333 fi[2] + fi[3] + pdir[2])
9334 || !world.try_bp(player, fi[0] + pdir[0], fi[1]
9335 + pdir[1], fi[2] + fi[3] + pdir[2], 1, 0)) {
9336 DBG("Failed SOUTH");
9337 }
9338 if (!world.try_bb(player, fi[0] + pdir[0], fi[1] + pdir[1],
9339 fi[2] - fi[3] + pdir[2])
9340 || !world.try_bp(player, fi[0] + pdir[0], fi[1]
9341 + pdir[1], fi[2] - fi[3] + pdir[2], 1, 0)) {
9342 DBG("Failed NORTH");
9343 }
9344
9345 if (!world.try_bb(player, fi[0] + mod + pdir[0], fi[1]
9346 + mod + pdir[1], fi[2] + mod + pdir[2])
9347 || !world.try_bp(player, fi[0] + mod + pdir[0],
9348 fi[1] + mod + pdir[1], fi[2] + mod
9349 + pdir[2], 1, 0)) {
9350 DBG("Failed 1");
9351 }
9352 if (!world.try_bb(player, fi[0] - mod + pdir[0], fi[1]
9353 + mod + pdir[1], fi[2] + mod + pdir[2])
9354 || !world.try_bp(player, fi[0] - mod + pdir[0],
9355 fi[1] + mod + pdir[1], fi[2] + mod
9356 + pdir[2], 1, 0)) {
9357 DBG("Failed 2");
9358 }
9359 if (!world.try_bb(player, fi[0] + mod + pdir[0], fi[1]
9360 + mod + pdir[1], fi[2] - mod + pdir[2])
9361 || !world.try_bp(player, fi[0] + mod + pdir[0],
9362 fi[1] + mod + pdir[1], fi[2] - mod
9363 + pdir[2], 1, 0)) {
9364 DBG("Failed 3");
9365 }
9366 if (!world.try_bb(player, fi[0] - mod + pdir[0], fi[1]
9367 + mod + pdir[1], fi[2] - mod + pdir[2])
9368 || !world.try_bp(player, fi[0] - mod + pdir[0],
9369 fi[1] + mod + pdir[1], fi[2] - mod
9370 + pdir[2], 1, 0)) {
9371 DBG("Failed 4");
9372 }
9373
9374 if (!world.try_bb(player, fi[0] + mod + pdir[0], fi[1]
9375 - mod + pdir[1], fi[2] + mod + pdir[2])
9376 || !world.try_bp(player, fi[0] + mod + pdir[0],
9377 fi[1] - mod + pdir[1], fi[2] + mod
9378 + pdir[2], 1, 0)) {
9379 DBG("Failed 5");
9380 }
9381 if (!world.try_bb(player, fi[0] - mod + pdir[0], fi[1]
9382 - mod + pdir[1], fi[2] + mod + pdir[2])
9383 || !world.try_bp(player, fi[0] - mod + pdir[0],
9384 fi[1] - mod + pdir[1], fi[2] + mod
9385 + pdir[2], 1, 0)) {
9386 DBG("Failed 6");
9387 }
9388 if (!world.try_bb(player, fi[0] + mod + pdir[0], fi[1]
9389 - mod + pdir[1], fi[2] - mod + pdir[2])
9390 || !world.try_bp(player, fi[0] + mod + pdir[0],
9391 fi[1] - mod + pdir[1], fi[2] - mod
9392 + pdir[2], 1, 0)) {
9393 DBG("Failed 7");
9394 }
9395 if (!world.try_bb(player, fi[0] - mod + pdir[0], fi[1]
9396 - mod + pdir[1], fi[2] - mod + pdir[2])
9397 || !world.try_bp(player, fi[0] - mod + pdir[0],
9398 fi[1] - mod + pdir[1], fi[2] - mod
9399 + pdir[2], 1, 0)) {
9400 DBG("Failed 8");
9401 }
9402
9403 }
9404 return true;
9405 }
9406
9407 // DBG("Sphere is clean and readdy to check move path",pl);
9408 if (world.eAa(tx, tz)) {
9409 // mmedium range check, not short range
9410 if (Math.abs(pdir[0]) > 2 * rd + 1
9411 || Math.abs(pdir[1]) > 2 * rd + 1
9412 || Math.abs(pdir[2]) > 2 * rd + 1) // do the big check
9413 {
9414 int xo, yo, zo;
9415 xo = yo = zo = 1; // zeroer for searching for cylinders, not
9416 // spheres
9417 if (pdir[0] > 0) {
9418 xs = 0;
9419 xe = rd + 1;
9420 xo = 0;
9421 }
9422 if (pdir[0] < 0) {
9423 xs = -rd;
9424 xe = 0;
9425 xo = 0;
9426 }
9427 if (pdir[1] > 0) {
9428 ys = 0;
9429 ye = rd + 1;
9430 yo = 0;
9431 }
9432 if (pdir[1] < 0) {
9433 ys = -rd;
9434 ye = 0;
9435 yo = 0;
9436 }
9437 if (pdir[2] > 0) {
9438 zs = 0;
9439 ze = rd + 1;
9440 zo = 0;
9441 }
9442 if (pdir[2] < 0) {
9443 zs = -rd;
9444 ze = 0;
9445 zo = 0;
9446 }
9447
9448 for (int x = xs; x < xe; x++)
9449 for (int z = zs; z < ze; z++)
9450 for (int y = ys; y < ye; y++) {
9451 // within overall sphere //within 2d max rd
9452 // circle
9453 if ((x * x) + (y * y) + (z * z) >= (rd + 0.5)
9454 * (rd + 0.5)
9455 && (x * x) * xo + (y * y) * yo
9456 + (z * z) * zo < (rd + 0.5)
9457 * (rd + 0.5)) {
9458 int sb = world.a(fi[0] + x, fi[1] + y,
9459 fi[2] + z);
9460 if (sb != 0 && sb != SNOW
9461 && sb != TALL_GRASS) {
9462 DBG("inner obstacle " + sb + " is at "
9463 + (fi[0] + x) + ","
9464 + (fi[1] + y) + ","
9465 + (fi[2] + z), player);
9466 player.ab(EnChat.RED
9467 + "There are obstacles in your path.");
9468 return true; // */
9469 } else {
9470 // w.e(fi[0]+x,fi[1]+y,fi[2]+z,GLASS);
9471 }
9472 }
9473
9474 }
9475 // DBG("completed small path",pl);
9476
9477 // inverter for controlling direction
9478 if (pdir[0] > 0) {
9479 xs = rd + 1;
9480 xe = pdir[0];
9481 } // limiters for performing main cylinder
9482 else if (pdir[0] < 0) {
9483 xs = rd + 1;
9484 xe = Math.abs(pdir[0] - 1);
9485 xi = -1;
9486 } else {
9487 xs = -rd;
9488 xe = rd + 1;
9489 xi = 1;
9490 }
9491 if (pdir[1] > 0) {
9492 ys = rd + 1;
9493 ye = pdir[1];
9494 } else if (pdir[1] < 0) {
9495 ys = rd + 1;
9496 ye = Math.abs(pdir[1] - 1);
9497 yi = -1;
9498 } else {
9499 ys = -rd;
9500 ye = rd + 1;
9501 yi = 1;
9502 }
9503 if (pdir[2] > 0) {
9504 zs = rd + 1;
9505 ze = pdir[2];
9506 } else if (pdir[2] < 0) {
9507 zs = rd + 1;
9508 ze = Math.abs(pdir[2] - 1);
9509 zi = -1;
9510 } else {
9511 zs = -rd;
9512 ze = rd + 1;
9513 zi = 1;
9514 }
9515 // DBG("Starting XYZs are" +xs*xi + "|" + ys*yi + "|" +
9516 // zs*zi + " Ending XYZs are " + xe*xi + "|" + ye*yi + "|" +
9517 // ze*zi,pl);
9518
9519 for (int x = xs; x < xe; x++)
9520 for (int z = zs; z < ze; z++)
9521 for (int y = ys; y < ye; y++) {
9522
9523 // check the cylinder
9524 // uses the xo/yo/zo to turn it into a 2D circle
9525 // of the correct orientation
9526
9527 if ((x * x) * xo + (y * y) * yo + (z * z) * zo < (rd + 0.5)
9528 * (rd + 0.5)) {
9529
9530 int sb = world.a((fi[0] + (x * xi)),
9531 (fi[1] + (y * yi)),
9532 (fi[2] + (z * zi)));
9533 if (sb != 0 && sb != SNOW
9534 && sb != TALL_GRASS) {
9535 player.ab(EnChat.RED
9536 + "There are obstacles in your path.");
9537 DBG(EnChat.YELLOW + "middling obstacle "
9538 + sb + " is at " + (fi[0] + x)
9539 + "," + (fi[1] + y) + ","
9540 + (fi[2] + z), player);
9541
9542 return true; // */
9543 } else {
9544 // w.e((fi[0]+(x*xi)),(fi[1]+(y*yi)),(fi[2]+(z*zi)),GLASS);
9545 }
9546
9547 }
9548 }
9549
9550 // DBG("completed mid path",pl);
9551
9552 if (pdir[0] > 0) {
9553 xs = 0;
9554 xe = rd + 1;
9555 }
9556 if (pdir[0] < 0) {
9557 xs = -rd;
9558 xe = 0;
9559 }
9560 if (pdir[1] > 0) {
9561 ys = 0;
9562 ye = rd + 1;
9563 }
9564 if (pdir[1] < 0) {
9565 ys = -rd;
9566 ye = 0;
9567 }
9568 if (pdir[2] > 0) {
9569 zs = 0;
9570 ze = rd + 1;
9571 }
9572 if (pdir[2] < 0) {
9573 zs = -rd;
9574 ze = 0;
9575 }
9576 for (int x = xs; x < xe; x++)
9577 for (int z = zs; z < ze; z++)
9578 for (int y = ys; y < ye; y++) {
9579 // check the outer shell of the sphere for
9580 // collisions.
9581 if ((x * x) + (y * y) + (z * z) < (rd + 0.5)
9582 * (rd + 0.5)) {
9583 int sb = world.a(fi[0] + x + pdir[0], fi[1]
9584 + y + pdir[1], fi[2] + z + pdir[2]);
9585 if (sb != 0 && sb != SNOW
9586 && sb != TALL_GRASS) {
9587 DBG("inner obstacle " + sb + " is at "
9588 + (fi[0] + x) + ","
9589 + (fi[1] + y) + ","
9590 + (fi[2] + z), player);
9591 player.ab(EnChat.RED
9592 + "There are obstacles in your path.");
9593 return true; // */
9594 } else {
9595 // w.e(fi[0]+x+pdir[0],fi[1]+y+pdir[1],fi[2]+z+pdir[2],GLASS);
9596 }
9597 }
9598 }
9599 // if you get to here, all validation checks have been
9600 // performed
9601
9602 } else {
9603 int xo, yo, zo;
9604 xo = yo = zo = 0; // collision checker incrementer
9605 int di;
9606 xs = ys = zs = -rd;
9607 xe = ye = ze = rd + 1;
9608
9609 xi = yi = zi = di = 1; // loop incrementer
9610 int pd = 0;
9611 if (pdir[0] > 0) {
9612 xs = 0;
9613 xe = 1;
9614 pd = pdir[0];
9615 di = xi = 1;
9616 xo = 1;
9617 }
9618 if (pdir[0] < 0) {
9619 xs = 0;
9620 xe = -1;
9621 pd = pdir[0];
9622 di = xi = -1;
9623 xo = -1;
9624 }
9625 if (pdir[1] > 0) {
9626 ys = 0;
9627 ye = 1;
9628 pd = pdir[1];
9629 di = yi = 1;
9630 yo = 1;
9631 }
9632 if (pdir[1] < 0) {
9633 ys = 0;
9634 ye = -1;
9635 pd = pdir[1];
9636 di = yi = -1;
9637 yo = -1;
9638 }
9639 if (pdir[2] > 0) {
9640 zs = 0;
9641 ze = 1;
9642 pd = pdir[2];
9643 di = zi = 1;
9644 zo = 1;
9645 }
9646 if (pdir[2] < 0) {
9647 zs = 0;
9648 ze = -1;
9649 pd = pdir[2];
9650 di = zi = -1;
9651 zo = -1;
9652 }
9653
9654 //
9655 // DBG("Starting X["+xs+","+xe +
9656 // ","+xi+"] Y["+ys+","+ye+","+yi+"] Z["+zs+","+ze+","+zi,pl);
9657 for (int x = xs; x != xe + (rd * xo); x += xi)
9658 for (int z = zs; z != ze + (rd * zo); z += zi)
9659 for (int y = ys; y != ye + (rd * yo); y += yi) {
9660
9661 if ((x * x) + (y * y) + (z * z) < (rd + 0.5)
9662 * (rd + 0.5)) {
9663 // if(w.a(fi[0]+x,fi[1]+y,fi[2]+z) == 0)
9664 // w.e(fi[0]+x,fi[1]+y,fi[2]+z,20);
9665 ctr = 0;
9666 // DBG("Engage! PD["+pd+"] O's["+xo+","+yo+","+zo+"]",pl);
9667 int lx, ly, lz;
9668 lx = x;
9669 ly = y;
9670 lz = z;
9671 for (int d = 0; d != pd + di; d += di) {
9672
9673 if ((lx * lx) + (ly * ly) + (lz * lz) >= (rd + 0.5)
9674 * (rd + 0.5)) {
9675 ctr++;
9676 int sb = (world.a(fi[0] + lx, fi[1]
9677 + ly, fi[2] + lz));
9678 if (sb != 0 && sb != SNOW
9679 && sb != TALL_GRASS) {
9680 player.ab(EnChat.RED
9681 + "There are obstacles in your path.");
9682 return true; // */
9683 }
9684 }
9685 if (ctr >= Math.abs(pd)) {
9686 break;
9687 }
9688 lx += xo;
9689 ly += yo;
9690 lz += zo;
9691 }
9692
9693 }
9694 }
9695 }
9696
9697 if (!ResidenceChecker.residenceCheck(player.aw_getName(),
9698 fi[0], fi[1], fi[2], fi[3], world, ResFlags.FaithFlags)) {
9699 player.ab(EnChat.RED
9700 + "The aether refuses to aid in this theft.");
9701 return true;
9702 }
9703
9704 if (!ResidenceChecker.residenceCheck(player.aw_getName(),
9705 pdir[0] + fi[0], pdir[1] + fi[1], pdir[2] + fi[2],
9706 fi[3], world, ResFlags.FaithFlags)) {
9707 player.ab(EnChat.RED
9708 + "The aether refuses to invade this territory.");
9709 return true;
9710 }
9711
9712 yi = 1;
9713 xi = -1;
9714
9715 if (pdir[0] > 0) {
9716 xi = 1;
9717 yi = -1;
9718 }
9719 if (pdir[1] > 0) {
9720 xi = 1;
9721 yi = -1;
9722 }
9723 if (pdir[2] > 0) {
9724 xi = 1;
9725 yi = -1;
9726 }
9727
9728 player.ab(EnChat.YELLOW
9729 + "The aether suddenly tenses around you!");
9730 RCT_main t = t(world, PEGASUS, player, fiid, pdir[0], pdir[1],
9731 pdir[2], (rd + 1) * xi, (rd + 1) * yi);
9732 t.scheduleSyncRepeating(6, 7);
9733
9734 mfrl.add(fiid);
9735 DBG(EnChat.YELLOW + "Starting Pegasus. fiid[" + fiid + "] dir["
9736 + pdir[0] + "," + pdir[1] + "," + pdir[2]
9737 + "] start & final [" + t.ia[4] + "," + t.ia[5] + "]",
9738 player); // */
9739 // DBG(Chat.RED + "Pegasus offline.",pl);
9740 } else {
9741 DBG("Target " + tx + "," + tz + "not in memory.", player);
9742 for (int x = -rd; x < rd; x += 16)
9743 for (int z = -rd; z < rd; z += 16)
9744 world.eAd(tx + x, tz + z);
9745
9746 for (int x = -rd; x <= rd; x++)
9747 for (int z = -rd; z <= rd; z++)
9748 for (int y = -rd; y <= rd; y++) {
9749 if ((x * x) + (y * y) + (z * z) < (rd + 0.5)
9750 * (rd + 0.5)) {
9751 int tb = world.a(tx + x, ty + y, tz + z);
9752 if (tb != 0 && tb != SNOW && tb != TALL_GRASS) {
9753 player.ab(EnChat.RED
9754 + "There are obstacles at your destination.");
9755 DBG("obstacle ["
9756 + world.a(tx + x, ty + y, tz + z)
9757 + "] is at [" + (tx + x) + ","
9758 + (ty + y) + "," + (tz + z)
9759 + "], distance: "
9760 + ((x * x) + (y * y) + (z * z)),
9761 player);
9762 return true;
9763
9764 }
9765
9766 }
9767 }
9768
9769 if (!ResidenceChecker.residenceCheck(player.aw_getName(),
9770 fi[0], fi[1], fi[2], fi[3], world, ResFlags.FaithFlags)) {
9771 player.ab(EnChat.RED
9772 + "The aether refuses to aid in this theft.");
9773 return true;
9774 }
9775
9776 if (!ResidenceChecker.residenceCheck(player.aw_getName(),
9777 pdir[0] + fi[0], pdir[1] + fi[1], pdir[2] + fi[2],
9778 fi[3], world, ResFlags.FaithFlags)) {
9779 player.ab(EnChat.RED
9780 + "The aether refuses to invade this territory.");
9781 return true;
9782 }
9783
9784 int grd = rd + 1;
9785
9786 for (int x = -grd; x < grd + 1; x++)
9787 for (int z = -grd; z < grd + 1; z++) {
9788 for (int y = -grd; y < grd + 1; y++) {
9789 double pos = (Math
9790 .sqrt((x * x) + (y * y) + (z * z)));
9791 if (pos >= grd - 0.5 && pos <= grd + 0.5) {
9792 int fb = world.a(fi[0] + x, fi[1] + y, fi[2]
9793 + z);
9794 if (fb == 0 || fb == TALL_GRASS || fb == SNOW) {
9795 addpr_addPositionRune(new rcm(FTP, GLASS,
9796 fi[0] + x, fi[1] + y, fi[2] + z,
9797 world.getWorldId(), 0, 0));
9798 world.e(fi[0] + x, fi[1] + y, fi[2] + z,
9799 GLASS);
9800 }
9801 int tb = world.a(tx + x, ty + y, tz + z);
9802 if (tb == 0 || tb == TALL_GRASS || tb == SNOW) {
9803 addpr_addPositionRune(new rcm(FTP, GLASS,
9804 tx + x, ty + y, tz + z,
9805 world.getWorldId(), 0, 0));
9806 world.e(tx + x, ty + y, tz + z, 20);
9807 }
9808 }
9809 }
9810 }// pl.ab(str); str = "";
9811 player.ab(EnChat.YELLOW
9812 + "The aether suddenly tenses around you!");
9813 RCT_main t = t(world, 115, player, tx, ty, tz, world.getWorldId(),
9814 fi[0], fi[1], fi[2], fi[3], -1, fiid);
9815
9816 t.scheduleSyncRepeating(7, 7);
9817 mfrl.add(fiid);
9818 // wpX wpY wpZ wpW fX fY fZ fR iterator
9819 // rct t =
9820 // t(w,115,pl,ta[2],ta[3],ta[4],ta[5],fi[0],fi[1],fi[2],fi[3],fi[3]);
9821
9822 }
9823 if (r.runePattern == PEGASUS - 1) {
9824 if (r.toolArmorType != ENDER_EGG && r.toolArmorType != 7) {
9825 player.rfhs(r.toolArmorType, 1);
9826 }
9827 } else {
9828
9829 c(world, new rcm(r.x - 1, r.y, r.z), 1, 1);
9830 c(world, new rcm(r.x + 1, r.y, r.z), 1, 1);
9831 c(world, new rcm(r.x, r.y - 1, r.z), 1, 1);
9832 c(world, new rcm(r.x, r.y + 1, r.z), 1, 1);
9833 c(world, new rcm(r.x, r.y, r.z - 1), 1, 1);
9834 c(world, new rcm(r.x, r.y, r.z + 1), 1, 1);
9835 }
9836 return true;
9837 // */
9838 }
9839 case BUTTERCURSE:// TODO do all the curses and hexes later
9840 {
9841 if (c(runeIdToRuneNameTable.get(r.runePattern), player, r.inkBlock,
9842 WardType.Void))
9843 return true;
9844 /*
9845 * int ch = 0; switch (gt_getTierByMetaValue(r.inkBlock,r.metaData))
9846 * { default: ch = 4; break; case 1: ch = 5; break; case 2: ch = 10;
9847 * break; case 3: ch = 15; break; case 4: ch = 25; break; case 5: ch
9848 * = 40; break; case 6: ch = 65; break; case 7: ch = 90; break; }
9849 *
9850 * r_removeEnchantmentFromToolType(TP_SWING,0,player,r.runePattern);
9851 * //remove all existing Buttercurses
9852 *
9853 * f_addMagicToPlayer(player, Chat.YELLOW +
9854 * "Your hands no longer grip your items securely"
9855 * ,r.runePattern,1,0,ch,getUses(r.runePattern, r.inkBlock,
9856 * r.metaData)); //install new buttercurse
9857 */
9858 player.ab(EnChat.PINK + "To use this curse, bind it with a hex rune.");
9859 player.ab(EnChat.PINK
9860 + "Those afflicted will sometimes drop what they're holding, when using it!");
9861 player.ab(EnChat.PINK
9862 + "The stronger the rune, the more frequently this will occur.");
9863 player.ab(EnChat.PINK + "A counter curse is available.");
9864 break;
9865 }
9866 case BUTTERCURSE + 1: {
9867 if (c("Butterfingers Counter Curse", player, r.inkBlock))
9868 return true;
9869 List<int[]> l = sl.get(player.aw_getName());
9870 if (l == null) {
9871 l = createLList();
9872 sl.put(player.aw_getName(), l);
9873 }
9874
9875 for (int[] iaa : l) {
9876 if (iaa[0] == BUTTERCURSE) {
9877 int reducto = getUses(BUTTERCURSE, r.inkBlock, r.metaData);
9878 DBG("Buttercurse reduction: " + iaa[4] + ":" + reducto);
9879 if (reducto >= iaa[4]) {
9880 l.remove(iaa);
9881 player.ab(EnChat.GREEN + "You are free from that curse!");
9882 c(world, r, 1, 1);
9883 return true;
9884 } else {
9885 player.ab(EnChat.GREEN + "You have removed " + reducto
9886 + " charges of the curse");
9887 iaa[4] -= reducto;
9888 c(world, r, 1, 1);
9889 return true;
9890 }
9891
9892 }
9893 }
9894
9895 player.ab(EnChat.RED + "You are not cursed with Butterfingers");
9896 return false;
9897
9898 }
9899
9900 case TOUCHHEX: {// \u00A7K
9901 if (c(runeIdToRuneNameTable.get(r.runePattern), player, r.inkBlock,
9902 WardType.Void))
9903 return true;
9904 r_removeEnchantmentFromToolType(TP_RIGHTCLICK, 264, player); // remove
9905 // all
9906 // existing
9907 // ench's
9908 c(world, r, 5, 5);
9909 f_addMagicToPlayer(player,
9910 EnChat.PINK + "Bind a curse to this tool!", r.runePattern,
9911 -2, 264, getUses(r.runePattern, r.inkBlock, r.metaData), 0,
9912 0, 1, 0); // install new hex
9913 return true;
9914
9915 }/**/
9916 case DAMAGEHEX: {// \u00A7K
9917 if (c(runeIdToRuneNameTable.get(r.runePattern), player, r.inkBlock,
9918 WardType.Void))
9919 return true;
9920 r_removeEnchantmentFromToolType(TP_RIGHTCLICK, 264, player); // remove
9921 // all
9922 // existing
9923 // ench's
9924 c(world, r, 5, 5); // curseID, curseTier,hextier
9925 f_addMagicToPlayer(player,
9926 EnChat.PINK + "Bind a curse to this tool!", r.runePattern,
9927 -2, 264, getUses(r.runePattern, r.inkBlock, r.metaData), 0,
9928 0, 1, 0); // install new hex
9929 return true;
9930 }
9931
9932 case PORTALHEX: {// \u00A7K
9933 if (c(runeIdToRuneNameTable.get(r.runePattern), player, r.inkBlock,
9934 WardType.Void))
9935 return true;
9936 r_removeEnchantmentFromToolType(TP_RIGHTCLICK, 264, player); // remove
9937 // all
9938 // existing
9939 // ench's
9940 c(world, r, 5, 5); // curseID, curseTier,hextier
9941 f_addMagicToPlayer(player,
9942 EnChat.PINK + "Bind a curse to this tool!", r.runePattern,
9943 -2, 264, getUses(r.runePattern, r.inkBlock, r.metaData), 0,
9944 0, 1, 0); // install new hex
9945 return true;
9946 }
9947 case WHISPERCURSE: {
9948 // get the north sign
9949 // pl.ab(w.a(r.x, r.y, r.z-2)+"");
9950 if (c("Whisper", player, r.inkBlock, WardType.Void))
9951 return true;
9952 player.ab(EnChat.PINK + "Bind this rune to a hex crystal to use");
9953 player.ab(EnChat.PINK
9954 + "Those who activate the hex, will see the words you have defined");
9955 player.ab(EnChat.PINK + "in the colors you have selected.");
9956
9957 // if (strs.size() > 0) {strl.add(strs);s();}
9958 break;
9959 }
9960
9961 case SPAWNER: {
9962 // trying to use the chest hacking code to acess mob spawner tile
9963 // data
9964
9965 DBG("Mob spawner's value = " + world.getMobSpawnerID(r.x, r.y, r.z));
9966 DBG("Item value of thing = " + player.Pc_dmg());
9967 world.setMobSpawnerID(r.x, r.y, r.z, player.Pc_dmg());
9968
9969 r.x -= 2;
9970 c(world, r, 1, 5);
9971 r.x += 1;
9972 c(world, r, 1, 5);
9973 r.x += 2;
9974 c(world, r, 1, 5);
9975 r.x += 1;
9976 c(world, r, 1, 5);
9977
9978 r.z -= 2;
9979 r.x -= 2;
9980 c(world, r, 5, 1);
9981 r.z += 1;
9982 c(world, r, 5, 1);
9983 r.z += 2;
9984 c(world, r, 5, 1);
9985 r.z += 1;
9986 c(world, r, 5, 1);
9987
9988 player.rfhs(383, 1);
9989 return true;
9990 }
9991 // */
9992 case FAITHOUT: {
9993 if (!rlc("salvation"))
9994 return false;
9995 if (c("Salvation" + EnChat.GREEN, player, r.inkBlock))
9996 return true;
9997 int i = 0;
9998 int fiid = -1;
9999 int ft;
10000 int fi[] = calcFi();
10001 for (; i < faithRuneList.size(); i++) {
10002 int[] fa = faithRuneList.get(i);
10003 if (fa[4] == r.w || fa[4] == -1)
10004 if ((fa[0] - r.x) * (fa[0] - r.x) + (fa[1] - r.y)
10005 * (fa[1] - r.y) + (fa[2] - r.z) * (fa[2] - r.z) < (fa[3] + 0.5)
10006 * (fa[3] + 0.5)) {
10007 // DBG("fa[3] ia "+fa[3] +" and FI[3] is " + fi[3],pl);
10008 if (fa[3] < fi[3]) {
10009 fiid = i;
10010 fi = fa;
10011 DBG("connected island is [" + fi[0] + "," + fi[1]
10012 + "," + fi[2] + "], radius [" + fi[3] + "]",
10013 player);
10014 }
10015 }
10016 }
10017 if (fiid < 0) {
10018 player.ab(EnChat.RED
10019 + "The land around you is not stable enough to be saved");
10020 return true;
10021 }
10022 if (mfrl.contains("" + fiid)) {
10023 player.ab(EnChat.RED + "This land is moving!");
10024 return true;
10025 }
10026
10027 g = gg(world, r.x, r.y, r.z, r.runePattern, false);
10028 gd = gg(world, r.x, r.y, r.z, r.runePattern, true);
10029 boolean exists = (new File(main_world.getWorldFolder(), g + "-"
10030 + gd + ".faith")).exists();
10031 DBG(g + "-" + gd + ".faith", player);
10032 if (exists) {
10033 player.ab(EnChat.RED
10034 + "This signature has been used. Try another!");
10035 return true;
10036 }
10037
10038 if (!fout(fiid, g, gd, player.getWorld().getWorldId())) {
10039 player.ab(EnChat.RED + "Your faith could not be saved.");
10040 } else {
10041 player.ab(EnChat.GREEN + "Your faith has been saved!");
10042 }
10043 return true;
10044 }
10045 case FAITHIN: {
10046 if (!rlc("redemption"))
10047 return false;
10048
10049 if (c("Redemption" + EnChat.GREEN, player, r.inkBlock))
10050 return true;
10051 g = gg(world, r.x, r.y, r.z, r.runePattern, false);
10052 gd = gg(world, r.x, r.y, r.z, r.runePattern, true);
10053 DBG(g + "-" + gd + ".faith");
10054 boolean exists = (new File(main_world.getWorldFolder(), g + "-"
10055 + gd + ".faith")).exists();
10056
10057 if (!exists) {
10058 player.ab(EnChat.RED
10059 + "There is no faith here. Try another signature!");
10060 return true;
10061 }
10062 fin(g, gd, r, player);
10063 return true;
10064 }
10065
10066 case WARDLIGHT:
10067 case WARDDARK:
10068 case WARDTP:
10069 case WARDTOOL:
10070 case WARDNGR:
10071 case WARDTRUNAME:
10072 case WARDFLIGHT: {
10073 final String runename = runeIdToRuneNameTable.get(r.runePattern);
10074 final String affectedString;
10075 WardType fieldtype = null;
10076 switch (r.runePattern) {
10077 case WARDLIGHT:
10078 fieldtype = WardType.Aether;
10079 affectedString = EnChat.GREEN
10080 + "The aether around the emerald stills. It will not hear those who are near.";
10081 break;
10082 case WARDDARK:
10083 fieldtype = WardType.Void;
10084 affectedString = EnChat.PURPLE
10085 + "The void around the emerald stills. It will not hear those who are near.";
10086 break;
10087 case WARDTOOL:
10088 fieldtype = WardType.Tool;
10089 affectedString = EnChat.YELLOW
10090 + "Enchanted tools near the emerald grow quiet. They will not function whilst nearby.";
10091 break;
10092 case WARDTP:
10093 fieldtype = WardType.Teleport;
10094 affectedString = EnChat.GREEN
10095 + "The aether near the emerald closes itself. Teleportation to and from the area is now impossible";
10096 break;
10097 case WARDNGR:
10098 fieldtype = WardType.Dangerous;
10099 affectedString = EnChat.GREEN
10100 + "The aether will suppress dangerous runes nearby.";
10101 break;
10102 case WARDTRUNAME:
10103 fieldtype = WardType.Target;
10104 affectedString = EnChat.GREEN
10105 + "The aether will shield your Name from view.";
10106 break;
10107 case WARDFLIGHT:
10108 fieldtype = WardType.Flight;
10109 affectedString = EnChat.GREEN
10110 + "The aether ground those who would escape gravity.";
10111 break;
10112 default:
10113 DBG("Missing ward case");
10114 return false;
10115 }
10116
10117 if (rlc(runename))
10118 return false;
10119 final WardType activationType = r.runePattern == WARDDARK ? WardType.Void
10120 : WardType.Aether;
10121 if (c(runename, player, r.inkBlock, activationType))
10122 return true;
10123
10124 // This single pattern is used for the positional rune
10125 r.runePattern = WARDLIGHT;
10126
10127 synchronized (positionRune) {
10128 rcm we;
10129
10130 we = getpr(r.x, r.y + 1, r.z, r.w);
10131 if (we != null && we.runePattern != WARDLIGHT) {
10132 DBG("Ward interference at [" + r.x + "," + (r.y + 1) + ","
10133 + r.z + "]", player);
10134 player.ab(EnChat.YELLOW + "Something interferes.");
10135 return true;
10136 }
10137
10138 for (int x = -1; x <= 1; x++)
10139 for (int z = -1; z <= 1; z++) {
10140 we = getpr(r.x + x, r.y, r.z + z, r.w);
10141 if (we != null) {
10142 DBG("Ward interference at [" + (r.x + x) + ","
10143 + r.y + "," + (r.z + z) + "]", player);
10144 player.ab(EnChat.YELLOW + "Something interferes.");
10145 return true;
10146 }
10147 // all 11 spots are clear. Deploy glass and RCMs.
10148 }
10149
10150 addpr_addPositionRune(new rcm(r.runePattern, r.inkBlock, r.x,
10151 r.y - 1, r.z, r.w, 1, r.toolArmorType));
10152 addpr_addPositionRune(new rcm(r.runePattern, r.inkBlock, r.x,
10153 r.y + 1, r.z, r.w, 1, r.toolArmorType));
10154
10155 for (int x = -1; x <= 1; x++)
10156 for (int z = -1; z <= 1; z++) {
10157 addpr_addPositionRune(new rcm(r.runePattern,
10158 r.inkBlock, r.x + x, r.y, r.z + z, r.w, 1,
10159 r.toolArmorType));
10160 if (world.a(r.x + x, r.y, r.z + z) == 0)
10161 world.e(r.x + x, r.y, r.z + z, 102);
10162 }
10163
10164 int[] tiers = { 4, 8, 16, 32, 64, 128 };
10165 int tier = gt_getTierByMetaValue(r.inkBlock, r.metaData);
10166
10167 if (tier < 1)
10168 tier = 1;
10169 else if (tier > tiers.length)
10170 tier = tiers.length;
10171 final int radius;
10172 radius = tiers[tier - 1];
10173
10174 final int[] wd = { r.x, r.y, r.z, r.w, radius, 1,
10175 fieldtype.code };
10176 wardRuneList.add(wd);
10177 }
10178 player.ab(affectedString);
10179 return true;
10180 }
10181
10182 case TRUENAME:
10183 case TRUENAME + 1:
10184 case TRUENAME + 2:
10185 case TRUENAME + 3: {
10186 // first! Check for a valid RCM.
10187 // If present, exit silently (return false)
10188 // If not present, continue.
10189 rcm e = getpr(r.x, r.y, r.z, r.w);
10190 if (e != null) {// DBG("Found an RCM, it's an "+e.runePattern);
10191 if (e.runePattern == TRUENAME) {
10192 return false;
10193 }
10194 } // Valid Namer block found. Defer to its functionality
10195 if (c(runeIdToRuneNameTable.get(TRUENAME), player, r.inkBlock))
10196 return true;
10197
10198 if (gt_getTierByMetaValue(r.inkBlock, r.metaData) > 4)// this is a
10199 // high
10200 // enough
10201 // tier to
10202 // be
10203 // permanent
10204 {
10205 DBG("Namer Rune: uses > 1", player);
10206 e = new rcm(TRUENAME, 0, r.x, r.y, r.z, r.w, getUses(TRUENAME,
10207 r.inkBlock, r.metaData), 0);
10208 if (!addpr_addPositionRune(e)) {
10209 player.ab(EnChat.YELLOW + "Something interferes.");
10210 c(world, e.x, e.y, e.z + 1, 1);
10211 c(world, e.x, e.y, e.z - 1, 1);
10212 c(world, e.x + 1, e.y, e.z, 1);
10213 c(world, e.x - 1, e.y, e.z, 1);
10214 return true;
10215 } else {
10216 for (int x = -2; x <= 2; x++)
10217 for (int z = -2; z <= 2; z++) {
10218 int fb = world.a(r.x + x, r.y, r.z + z);
10219 // DBG((r.x+x)+","+r.y+","+(r.z+z));
10220 if (fb != FIRE && gt_getTier(fb) != 0) {
10221 world.e(r.x + x, r.y, r.z + z, STONE);
10222
10223 } else
10224
10225 {
10226
10227 }
10228 }
10229 player.ab(EnChat.YELLOW
10230 + "You have set up your True Namer with "
10231 + getUses(TRUENAME, r.inkBlock, r.metaData)
10232 + " use" + ((e.length != 1) ? "s" : "") + ".");
10233 player.ab(EnChat.YELLOW
10234 + "Use the centre again to get a copy of your True Name!");
10235 player.ab(EnChat.YELLOW
10236 + "Feed high level tier blocks into the centre to increase the number of uses.");
10237 }
10238 } else// one-shot rune
10239 {
10240 DBG("Namer Rune: uses <= 1", player);
10241 player.dropSkull(r.x, r.y, r.z);
10242 c(world, r, 5, 5);
10243 }
10244 // else//this case may no longer be used
10245 // {
10246 // player.ab(Chat.YELLOW+"Place a tier block in the centre to feed the Namer.");
10247 //
10248 // }
10249 c(world, r, 1, 1);
10250 return true;
10251 }
10252 case BABELCURSE: {
10253
10254 /*
10255 * int ch = 0; switch (gt_getTier(r.inkBlock)) { //percentage
10256 * chances of occurring default: ch = 5;break; case 1: ch = 5;
10257 * break; case 2: ch = 10; break; case 3: ch = 15; break; case 4: ch
10258 * = 25; break; case 5: ch = 40; break; case 6: ch = 65; break; case
10259 * 7: ch = 90; break;
10260 *
10261 * }
10262 */
10263 if (c(runeIdToRuneNameTable.get(BABELCURSE), player, r.inkBlock,
10264 WardType.Void))
10265 return true;
10266 player.ab(EnChat.PINK + "To use this curse, bind it with a hex rune.");
10267 player.ab(EnChat.PINK
10268 + "Those afflicted will sometimes speak in gibberish!");
10269 player.ab(EnChat.PINK
10270 + "The stronger the rune, the more frequently this will occur.");
10271 player.ab(EnChat.PINK + "A counter curse is available.");
10272
10273 break;
10274 }
10275 case BABELCURSE + 1:
10276 if (c(runeIdToRuneNameTable.get(BABELCURSE + 1), player, r.inkBlock))
10277 return true;
10278 boolean functioned = false;
10279 final List<int[]> en = sl.get(player.aw_getName());
10280 if (en != null) {
10281 // DBG("Entry");
10282 for (final int[] ta : en) {
10283 // DBG("Babel counter curse found ["+ta[0]+"] "+runeIdToRuneNameTable.get(ta[0]));
10284 if (ta[0] == BABELCURSE) { // hand speak enchants only
10285
10286 DBG("Found a babel curse to reduct");
10287 final int reducto = getUses(BABELCURSE, r.inkBlock,
10288 r.metaData);
10289 ta[4] -= reducto;
10290 if (ta[4] <= 0) {
10291 player.ab(EnChat.GREEN
10292 + "You have cleansed yourself of the babel curse");
10293 r_removeEnchantmentFromToolType(TP_SPEAK, 0,
10294 player, BABELCURSE);
10295 } else {
10296 player.ab(EnChat.GREEN + "You have removed "
10297 + reducto + " charges of the babel curse");
10298 }
10299 c(world, r, 1, 1);
10300 return true;
10301 }
10302
10303 }
10304 }
10305 player.ab(EnChat.RED + "You aren't cursed with Babel");
10306 break;
10307 case SMITETRAP: {
10308 if (c(runeIdToRuneNameTable.get(SMITETRAP), player, r.inkBlock,
10309 WardType.Void))
10310 return true;
10311 player.ab(EnChat.PINK + "To use this curse, bind it with a hex rune.");
10312 player.ab(EnChat.PINK
10313 + "Those who trigger the hex will be at the centre of a lightning storm");
10314 player.ab(EnChat.PINK
10315 + "The stronger the rune, the longer the storm will last.");
10316 /*
10317 *
10318 * rct t = t(world, SMITETRAP, player, (int)player.x(),
10319 * (int)player.y(), (int)player.z(), getUses(SMITETRAP, r.inkBlock,
10320 * r.metaData),//*10 for regular seconds 0); //no idea what this
10321 * last one does t.setXyz((int)player.x(), (int)player.y(),
10322 * (int)player.z()); if (getUses(SMITETRAP, r.inkBlock, r.metaData)
10323 * > 10) world.setWeather(2); t.scheduleSyncRepeating(10, 20);
10324 */
10325 break;
10326 }
10327 case COMMPEARL: {
10328 if (c("Runic radio", player, r.inkBlock))
10329 return true;
10330 int sb = world.a(r.x, r.y + 1, r.z);
10331 sb = sb << 8 | world.b(r.x, r.y + 1, r.z);
10332 DBG(sb + " Signature of runic radio");
10333 int color = 0;
10334 if (world.a(r.x, r.y - 1, r.z) == 35)
10335 color = world.b(r.x, r.y - 1, r.z);
10336 int ta[] = { r.runePattern, TP_CATCHALL.getCode(), r.toolArmorType,
10337 sb, sb, color };
10338 r_removeEnchantmentFromToolType(TP_CATCHALL, r.toolArmorType,
10339 player, r.runePattern);
10340 f_addMagicToPlayer(
10341 player,
10342 ta,
10343 EnChat.GREEN
10344 + "Whilst holding this pearl, your words will reach only those with compatible pearls.");
10345 player.ab(EnChat.GREEN
10346 + "To speak, hold the pearl. To hear, merely keep the pearl with you.");
10347 c(world, r, 5, 5);
10348 c(world, new rcm(r.x, r.y + 1, r.z), 1, 1);
10349 if (color != 0)
10350 c(world, new rcm(r.x, r.y - 1, r.z), 1, 1);
10351 return true;
10352 }
10353 case REALITYANCHOR: {
10354 DBG("Reality anchor activated");
10355
10356 if (c(runeIdToRuneNameTable.get(r.runePattern), player, r.inkBlock)) {
10357 return true;
10358 }
10359
10360 // Upright variants? Don't think this is necessary, given the setup.
10361 // Dear lords, I'm going to need a massive pattern lab
10362
10363 // Get tier / sig
10364
10365 // Turn emeralds in rune to smoothstone
10366
10367 /*
10368 * Create bounding emeralds : new position magic 1) Move emeralds to
10369 * default positions (say, the bounding the largest cube a T1 can
10370 * use) a) Error if this space isn't clear, or replace block in
10371 * default position? Probably replace the block. 2) Create magic for
10372 * emeralds :: use -REALITYANCHOR as the ID Behavior: when right
10373 * clicked, moves one in the direction clicked, if clicked on a side
10374 * in the right axis Blocked from moving by non-air blocks? refuse
10375 * to move further than the tier of the anchor allows 3) Link magic
10376 * in emeralds to the reality anchor. Probably pass them an int to
10377 * update, store the same int in the anchor.
10378 *
10379 * So, total things to store in the emerald PRs : an int linked back
10380 * to the anchor, and the direction the block can move in, tier of
10381 * anchor
10382 */
10383
10384 // Let's do this first.
10385 // I'm going to assume this rune is going to be 7 x 2 x 7
10386
10387 rcm e = getpr(r.x, r.y, r.z, r.w);
10388 if (e == null) {
10389 g = gg(world, r.x, r.y, r.z, r.runePattern, false);
10390 gd = gg(world, r.x, r.y, r.z, r.runePattern, true);
10391
10392 if (getAnchor(g, gd) != null) {
10393 player.ab(EnChat.YELLOW
10394 + "This signature has been used. Try another.");
10395 return true;
10396 }
10397
10398 int[] tta = { g, gd, r.x, r.y, r.z, r.w, r.inkBlock };
10399 realityAnchorList.add(tta);
10400 e = new rcm(REALITYANCHOR, r.inkBlock, r.x, r.y, r.z, r.w,
10401 getUses(REALITYMASTER, r.inkBlock, r.metaData), 0);
10402 addpr_addPositionRune(e);
10403 } else if (positionRune.get(e).runePattern != REALITYANCHOR) { // If
10404 // there
10405 // is
10406 // another
10407 // RCM
10408 // here,
10409 // interferes
10410 player.ab(EnChat.YELLOW + "Something interferes.");
10411 return true;
10412 } else { // If there is another reality anchor here, things were
10413 // handled already
10414 return true;
10415 }
10416
10417 // pdir = rct.dir(dir);
10418 int offset = 3;
10419
10420 int y = r.y + 2;
10421 int i;
10422 for (i = 0; i < 6; i++) {
10423 if (i == 1) {
10424 continue;
10425 }
10426
10427 int[] pdir = RCT_main.dir(i);
10428
10429 if (world.a(r.x + offset * pdir[0], y + offset * pdir[1], r.z
10430 + offset * pdir[2]) != 0) {
10431 player.ab(EnChat.YELLOW
10432 + "A random block is in the way of the "
10433 + dirs(i, true) + " anchor");
10434 continue;
10435 }
10436
10437 e = new rcm(-REALITYANCHOR, r.inkBlock, r.x + offset * pdir[0],
10438 y + offset * pdir[1], r.z + offset * pdir[2], r.w,
10439 offset, i);
10440
10441 if (!addpr_addPositionRune(e)) {
10442 player.ab(EnChat.YELLOW
10443 + "Some form of magic block prevents the formation of the "
10444 + dirs(i, true) + " anchor");
10445 continue;
10446 // RCM in the way of this rcm. force place, cancel, or try
10447 // again?
10448 // I'm going to go with 'force' for now.
10449 // rcm destr = getpr(r.x + offset * pdir[0],y + offset *
10450 // pdir[1],r.z + offset * pdir[2],r.w);
10451 // DBG(Chat.RED + "blocking RCM : " +
10452 // runeIdToRuneNameTable.get(destr.runePattern) +
10453 // " : destroying");
10454 // need to add something to properly destroy stuff later
10455 // rempr_removePositionRune(e);
10456 // addpr_addPositionRune(e);
10457 }
10458
10459 world.e(r.x + offset * pdir[0], y + offset * pdir[1], r.z
10460 + offset * pdir[2], 133);
10461 world.e(r.x + pdir[0], r.y, r.z + pdir[2], 1);
10462
10463 }
10464
10465 r.x -= 2;
10466 cStone(world, r, 1, 3);
10467 r.x += 4;
10468 cStone(world, r, 1, 3);
10469
10470 r.z -= 2;
10471 r.x -= 2;
10472 cStone(world, r, 3, 1);
10473 r.z += 4;
10474 cStone(world, r, 3, 1);
10475
10476 // Create anchor PR, add it to list of reality anchors
10477
10478 return true;
10479 }
10480 case REALITYMASTER: {
10481 // DBG(Chat.GREEN + "Reality master activated");
10482
10483 if (c(runeIdToRuneNameTable.get(r.runePattern), player, r.inkBlock))
10484 return true;
10485
10486 // Want this to be able to select direction. At minimum, up and
10487 // down, but might want to make upright variants?
10488 // Ooo... what if I make it a sort of mashup of the master runes and
10489 // mineshaft...
10490 // hm... okay... Need to try and encode direction into the rune.
10491 // maybe a little shape above the rune proper?
10492
10493 // Need a new flag in the pattern encoder, 'container'?
10494 // maybe I'll just use key, and 'check for container'?
10495 // yeah, the 'special case of key' meshes with our idea for adding
10496 // an item TP by checking for containers as the key block
10497
10498 // Check if this realitymaster is in use
10499
10500 rcm e = new rcm(r.x, r.y, r.z, r.w);
10501
10502 if (mrml.contains(e)) {
10503 player.ab(EnChat.RED + "This reality master is already active!");
10504 return false;
10505 }
10506
10507 // Get tier? / sig
10508
10509 g = gg(world, r.x, r.y, r.z, r.runePattern, false);
10510 gd = gg(world, r.x, r.y, r.z, r.runePattern, true);
10511
10512 // Get associated reality anchor from sig
10513
10514 int[] anch = getAnchor(g, gd);
10515
10516 if (anch == null) {
10517 player.ab(EnChat.RED + "Such an anchor does not exist.");
10518 return false;
10519 }
10520
10521 e = getpr(anch[2], anch[3], anch[4], anch[5]);
10522
10523 // Check tiers (may skip this step, only use the tier of the
10524 // anchor?)
10525
10526 // Get border coordinates from emeralds, check area against tier
10527
10528 int y = e.y + 2;
10529
10530 rcm lowerBound = new rcm(e.x, y, e.z, e.w);
10531 rcm upperBound = new rcm(e.x, y, e.z, e.w);
10532
10533 rcm lowerOffset = new rcm(0, 0, 0);
10534 rcm upperOffset = new rcm(0, 0, 0);
10535
10536 for (int d = 0; d < 6; d++) {
10537 int rd = getUses(REALITYANCHOR, e.inkBlock, e.metaData);
10538
10539 if (d == 0) {
10540 rd *= 2;
10541 rd -= 1;
10542 }
10543
10544 if (d == 1) {
10545 continue;
10546 // ignore downward
10547 }
10548 int[] pdir = RCT_main.dir(d);
10549 boolean found = false;
10550 for (int i = 1; i <= rd; i++) {
10551 rcm bound = getpr(e.x + i * pdir[0], y + i * pdir[1], e.z
10552 + i * pdir[2], e.w);
10553 if (bound != null && bound.runePattern == -REALITYANCHOR) {
10554 // bounds.add(bound);
10555 if (pdir[0] + pdir[1] + pdir[2] < 0) {
10556 lowerBound.setXyz(lowerBound.x + i * pdir[0],
10557 lowerBound.y + i * pdir[1], lowerBound.z
10558 + i * pdir[2]);
10559 lowerOffset.setXyz(lowerOffset.x + i * pdir[0],
10560 lowerOffset.y + i * pdir[1], lowerOffset.z
10561 + i * pdir[2]);
10562
10563 } else {
10564 upperBound.setXyz(upperBound.x + i * pdir[0],
10565 upperBound.y + i * pdir[1], upperBound.z
10566 + i * pdir[2]);
10567 upperOffset.setXyz(upperOffset.x + i * pdir[0],
10568 upperOffset.y + i * pdir[1], upperOffset.z
10569 + i * pdir[2]);
10570 }
10571 found = true;
10572 break;
10573 }
10574 }
10575 if (!found) {
10576 player.ab(EnChat.YELLOW + "The aether cannot find the "
10577 + dirs(d, true) + " anchor!");
10578 // Destroy anchor and all attached bounds? Or wait to see if
10579 // an anchor will be moved back?
10580 // possibly add another rune to create new anchors?
10581 return false;
10582 }
10583 }
10584
10585 // Adjust bounds off of the emerald blocks
10586 lowerBound.setXyz(lowerBound.x + 1, lowerBound.y, lowerBound.z + 1);
10587 lowerOffset.setXyz(lowerOffset.x + 1, lowerOffset.y + 1,
10588 lowerOffset.z + 1);
10589
10590 upperBound.setXyz(upperBound.x - 1, upperBound.y - 1,
10591 upperBound.z - 1);
10592 upperOffset.setXyz(upperOffset.x - 1, upperOffset.y - 1,
10593 upperOffset.z - 1);
10594
10595 int volume = (upperBound.x - lowerBound.x + 1)
10596 * (upperBound.y - lowerBound.y + 1)
10597 * (upperBound.z - lowerBound.z + 1);
10598
10599 DBG(EnChat.RED + "volume = " + volume);
10600 DBG(EnChat.GREEN + "upperBound = :x:" + EnChat.RED + upperBound.x
10601 + EnChat.GREEN + " :y:" + EnChat.RED + upperBound.y
10602 + EnChat.GREEN + " :z:" + EnChat.RED + upperBound.z);
10603 DBG(EnChat.GREEN + "lowerBound = :x:" + EnChat.RED + lowerBound.x
10604 + EnChat.GREEN + " :y:" + EnChat.RED + lowerBound.y
10605 + EnChat.GREEN + " :z:" + EnChat.RED + lowerBound.z);
10606
10607 if (volume > getUses(REALITYMASTER, e.inkBlock, e.metaData)) {
10608 player.ab(EnChat.YELLOW
10609 + "The anchor is not powerful enough to hold this much space!");
10610 return false;
10611 } else {
10612
10613 player.ab(EnChat.GREEN
10614 + "The aether tenses, preparing to convert the area.");
10615
10616 // Get direction, start task!
10617
10618 // Let's assume we're going up initially, just so I can get the
10619 // code setup on the other end
10620 // then we'll work on getting the directions moving correctly
10621
10622 // Upper/lower bound: bounding box, source
10623
10624 // Dest. corner: depends on direction. go with easy calc for
10625 // corner, have the direction determine where to start?
10626
10627 RuneBlock b = world.getBlock(r.x, r.y, r.z);
10628 int d = 0;
10629 int[] pdir = RCT_main.dir(d);
10630
10631 if (b.getType() == 33 || b.getType() == 29) {
10632 // Found piston!
10633 d = b.getData();
10634 pdir = RCT_main.pistonDir(d);
10635 }
10636
10637 int xD = r.x + 4 * pdir[0];
10638 int yD = r.y + 2 * pdir[1];
10639 if (pdir[1] < 0) {
10640 yD += 1;
10641 }
10642 int zD = r.z + 4 * pdir[2];
10643
10644 int xO = upperBound.x - lowerBound.x + 1;
10645 int yO = upperBound.y - lowerBound.y + 1;
10646 int zO = upperBound.z - lowerBound.z + 1;
10647
10648 if (pdir[0] + pdir[1] + pdir[2] < 0) {
10649
10650 // start at upper bound, go to lower bound
10651
10652 pdir[0] += 1;
10653 pdir[1] += 1;
10654 pdir[2] += 1;
10655
10656 xD += pdir[0] * upperOffset.x;
10657 yD += pdir[1] * (upperOffset.y * 0.5);
10658 zD += pdir[2] * upperOffset.z;
10659
10660 /*
10661 * // CHECK DONE IN RCT if(yD - yO < 0){ player.ab(
10662 * "This spell cannot remove materials from the mortal plane!"
10663 * ); return false; }
10664 */
10665
10666 mrml.add(new rcm(r.x, r.y, r.z, r.w));
10667
10668 RCT_main t = t(world, REALITYMASTER, player, upperBound.x,
10669 upperBound.y, upperBound.z, e.w, xO, yO, zO, -1, 0,
10670 r.x, r.y, r.z);
10671 t.setXyz(xD, yD, zD);
10672 t.scheduleSyncRepeating(2, 2);
10673 } else {
10674 // start at lower bound, go to upper bound
10675
10676 pdir[0] -= 1;
10677 pdir[1] -= 1;
10678 pdir[2] -= 1;
10679
10680 xD -= pdir[0] * lowerOffset.x;
10681 yD += pdir[1] * (upperOffset.y * 0.5);
10682 zD -= pdir[2] * lowerOffset.z;
10683
10684 /*
10685 * CHECK DONE IN RCT if(yD + yO > world.getMaxY()){
10686 * player.ab
10687 * ("This spell cannot remove materials from the mortal plane!"
10688 * ); return false; }
10689 */
10690
10691 mrml.add(new rcm(r.x, r.y, r.z, r.w));
10692
10693 RCT_main t = t(world, REALITYMASTER, player, lowerBound.x,
10694 lowerBound.y, lowerBound.z, e.w, xO, yO, zO, 1, 0,
10695 r.x, r.y, r.z);
10696 t.setXyz(xD, yD, zD);
10697 t.scheduleSyncRepeating(2, 2);
10698 }
10699
10700 DBG(EnChat.GREEN + "dest = :x:" + EnChat.RED + xD + EnChat.GREEN
10701 + " :y:" + EnChat.RED + yD + EnChat.GREEN + " :z:"
10702 + EnChat.RED + zD);
10703
10704 // Need to think of another message for these...
10705
10706 // t.scheduleSyncRepeating(2, 2);
10707
10708 }
10709
10710 // Get direction of activation! Use the opposite face of the
10711 // activated one or pattern? (allows for drills!)
10712
10713 // start task in one corner (how about the negative corner in all
10714 // dimensions?)
10715 // Send to task: coord to start copy, coord to start read,
10716 // dimensions of box
10717
10718 // As I said, WANT TO ALLOW FOR DRILLING
10719 // hmm...... how powerful is it if we *literally* allow for
10720 // drilling?
10721 // Like, how expensive / how many restrictions do we have to place
10722 // on the rune if we allow for something like a mashup between the
10723 // buildraft Quarry and Architect?
10724
10725 return true;
10726 }
10727 case FREIGHTPOINT: {
10728 dir = 1;
10729
10730 g = gg(world, r.x, r.y, r.z, r.runePattern, false);
10731 if (g == 0)
10732 return false;
10733 if (c(runeIdToRuneNameTable.get(r.runePattern), player,
10734 "set up a freightpoint", r.inkBlock))
10735 return true;
10736 if (!wsigc(player, g)) {
10737 player.ab(EnChat.RED
10738 + "The aether denies you this signature. Try another!");
10739 return true;
10740 }
10741
10742 gd = gg(world, r.x, r.y, r.z, r.runePattern, true);
10743
10744 if (rlc("enable travel ink"))
10745 if (!rlc("ink " + r.inkBlock)) {
10746 player.ab(EnChat.RED
10747 + "The aether demands that this rune be made with a");
10748 player.ab(EnChat.RED + "different material!");
10749 return true;
10750 }
10751
10752 ia = gacwp_getWaypointCoordinatesBySignature(g, gd); // get waypoint
10753 // desc
10754 if (ia != null) {
10755 if (ia[2] == r.x && ia[3] == r.y && ia[4] == r.z
10756 && ia[5] == r.w) {
10757 player.ab(EnChat.RED
10758 + "This freightpoint is already established.");
10759 return false;
10760 } // specifically false to allow users to open the chest
10761 else
10762 player.ab(EnChat.RED
10763 + "This signature has been used. Try another.");
10764 return true;
10765 }
10766
10767 for (int i = 0; i < waypointRuneList.size(); i++) {
10768 int[] ta = waypointRuneList.get(i);
10769 if (ta[2] == r.x && ta[3] == r.y && ta[4] == r.z
10770 && ta[5] == r.w) {
10771 ta[6] = r.inkBlock;
10772 if (g == ta[0] && gd == ta[1]) {
10773 player.ab(EnChat.RED
10774 + "This freightpoint is already established.");
10775 DBG("WP already established " + g + "," + gd);
10776 } else {
10777 ta[0] = g;
10778 ta[1] = gd;
10779 s_saveToMagicDat();
10780
10781 player.ab(EnChat.GREEN
10782 + "You have changed the signature of this freightpoint");
10783 player.ab(EnChat.YELLOW
10784 + "The waypoint signature is no longer needed here.");
10785 }
10786 return true;
10787 }
10788 }
10789
10790 int[] newfrp = { g, gd, r.x, r.y, r.z, r.w, r.inkBlock, dir };
10791
10792 waypointRuneList.add(newfrp);
10793 s_saveToMagicDat();
10794 // addpr_addPositionRune(new rcm(WAYPOINT,g, r.x,r.y,r.z,r.w, 1,1));
10795 player.ab(EnChat.GREEN
10796 + "A new opening has been created in the fabric of the aether");
10797 player.ab(EnChat.YELLOW
10798 + "The waypoint signature is no longer needed here.");
10799 return true;
10800
10801 }
10802 case FREIGHTTP: {
10803
10804 g = gg(world, r.x, r.y - 1, r.z, r.runePattern, false);
10805 gd = gg(world, r.x, r.y - 1, r.z, r.runePattern, true);
10806 if (g == 0) {
10807 if (!player.c("teleport", null)) {
10808 player.ab(EnChat.RED + "You cannot teleport.");
10809 return true;
10810 }
10811 player.ab(EnChat.GREEN + "Freight teleporter used.");
10812
10813 /*
10814 * DBG(wpl.size()+" waypoints"); for (int i = 0; i < wpl.size();
10815 * i++) {int[] ta =
10816 * wpl.get(i);DBG("Waypoint ["+Chat.YELLOW+ta[2]
10817 * +","+ta[3]+","+ta
10818 * [4]+","+ta[5]+Chat.GREEN+"] "+ta[0]+","+ta[1]);} //
10819 */
10820
10821 // condition to prevent mob spawners spamming the logs.
10822 for (int i = 0; i < teleportRuneList.size(); i++) {
10823 int[] ta = teleportRuneList.get(i);
10824 if (ta[0] == r.x && ta[1] == r.y && ta[2] == r.z
10825 && ta[3] == r.w) {
10826 g = ta[4];
10827 gd = ta[5];
10828 break;
10829 }
10830 }
10831
10832 if (g == 0) {
10833 if (!ie || ip.contains(player.aw_getName()))
10834 player.ab(EnChat.RED
10835 + "You have not specified a destination.");
10836 return true;
10837 }
10838
10839 RuneInventory source = world.getBlock(r.x, r.y - 1, r.z)
10840 .getInventory();
10841 if (!source.isIntact()) {
10842 player.ab(EnChat.RED
10843 + "The aether could not find anything to send!");
10844 return true;
10845 }
10846
10847 int[] ta = gacwp_getWaypointCoordinatesBySignature(g, gd); // get
10848 // waypoint
10849 // desc
10850 // assume (ta == null || g == ta[0])
10851
10852 if (ta == null) {
10853 player.ab(EnChat.RED
10854 + "Your way has been barred from the other side.");
10855 DBG("broken TP to " + g + "," + gd);
10856 return false;
10857 }
10858
10859 if ((!rlc("enable multiworld travel") && r.w != ta[5])
10860 || wgc(r.w, ta[5], r.inkBlock,
10861 runeIdToRuneNameTable.get(r.runePattern)) == false) {
10862 player.ab(EnChat.RED
10863 + "The distance to the destination is too large.");
10864 DBG("Failure to travel between worlds, source "+r.w+ " destination "+ta[5]);
10865 return false;
10866 }
10867 if (gt_getTierByMetaValue(r.inkBlock, r.metaData) < bt_blockTier[ta[6]]) {
10868 player.ab(EnChat.RED
10869 + "Your way will not open, this rune is not powerful enough.");
10870 return false;
10871 }
10872
10873 RuneWorld ww2 = getWorldById(ta[5]);
10874 if (RunecraftParser.a_runeDetection(
10875 wr_runeTemplateArray[FREIGHTPOINT - 1], ww2, ta[2],
10876 ta[3], ta[4]) == 0) {
10877 player.ab(EnChat.RED
10878 + "Your destination is not able to receive items!");
10879 return false;
10880 }
10881
10882 RuneInventory target = ww2.getBlock(ta[2], ta[3] + 1, ta[4])
10883 .getInventory();
10884 if (!target.isIntact()) {
10885 player.ab(EnChat.RED
10886 + "Your destination is not able to receive items!");
10887 return false;
10888 }
10889
10890 int by = ta[3];
10891
10892 by = b(ww2, ta[2], ta[3], ta[4], 1).y; // up
10893 boolean moved = false;
10894 for (RuneItem src : source.getInventory()) {
10895
10896 if (src != null && src.getType() != 0) {
10897
10898 RuneItem ex = target.addItem(src);
10899
10900 if (ex == null) {
10901 moved = true;
10902 source.removeItem(src);
10903 } else if (ex.getAmount() != src.getAmount()) {
10904 moved = true;
10905 source.removeItem(src);
10906 source.addItem(ex);
10907 }
10908 }
10909
10910 }
10911 DBG("Moved :" + moved + " sizes src|tgt ["
10912 + source.getInventory().size() + "|"
10913 + target.getInventory().size() + "]");
10914
10915 if (moved) {
10916 player.ab(EnChat.GREEN + "The aether swallows some items.");
10917 return true;
10918 }
10919
10920 else {
10921 player.ab(EnChat.RED + "The aether couldn't send any items!");
10922 return false;
10923 }
10924
10925 // if (wdc(player,4)){ return true; }
10926 // if(wdc(new rcm
10927 // ((int)(ta[2]+0.5D),by,(int)(ta[4]+0.5D),ww2.getWorldId()),4))
10928 // {DBG("Blocked teleporter",player);player.ab(Chat.RED+"There is a ward at your destination preventing teleportation");
10929 // return false;}
10930 // aa(player,ww2,ta[2]+0.5D,by,ta[4]+0.5D,player.v(),player.w());
10931 // aa(plww2, ta[2]+0.5D,bb,ta[4]+0.5D, pl.v(),pl.w());
10932 // oa(player);
10933
10934 } else { // there are sig blocks.
10935 if (!player.isEntity())
10936 return false;
10937 if (ie && !ip.contains(player.aw_getName()))
10938 return false;
10939
10940 if (c(runeIdToRuneNameTable.get(r.runePattern), player,
10941 "set up a freight teleporter", r.inkBlock))
10942 return true;
10943
10944 int[] wpp = gacwp_getWaypointCoordinatesBySignature(g, gd); // get
10945 // waypoint
10946 // desc
10947 if (wpp == null) {
10948 player.ab(EnChat.RED
10949 + "Such a destination has not been opened.");
10950 DBG("Failed to establish TP to " + g + "," + gd, player);
10951 return true;
10952 }
10953 if ((!rlc("enable multiworld travel") && r.w != wpp[5])
10954 || wgc(r.w, wpp[5], r.inkBlock,
10955 runeIdToRuneNameTable.get(r.runePattern)) == false) {
10956 player.ab(EnChat.RED
10957 + "The distance to the destination is too large.");
10958 return true;
10959 }
10960
10961 c(world, r.x, r.y - 1, r.z - 2, 0);
10962 c(world, r.x, r.y - 1, r.z + 2, 0);
10963 c(world, r.x - 2, r.y - 1, r.z, 0);
10964 c(world, r.x + 2, r.y - 1, r.z, 0);
10965
10966 for (int i = 0; i < teleportRuneList.size(); i++) {
10967 int[] ta = teleportRuneList.get(i);
10968 if (ta[0] == r.x && ta[1] == r.y && ta[2] == r.z
10969 && ta[3] == r.w) {
10970 ta[4] = g;
10971 ta[5] = gd;
10972 s_saveToMagicDat(); // replace active teleporter
10973 player.ab(EnChat.GREEN
10974 + "A new tunnel through the aether has been established.");
10975 teleportRuneList.set(i, ta);
10976 return true;
10977 }
10978 }
10979 int[] ta = { r.x, r.y, r.z, r.w, g, gd }; // create new
10980 // teleporter
10981 // DBG("Standard TP created @ ["+r.x+","+ r.y +","+ r.z +","+
10982 // r.w +"] to ["+ g+","+ gd+"]",pl);
10983 teleportRuneList.add(ta);
10984 s_saveToMagicDat();
10985 player.ab(EnChat.GREEN
10986 + "A tunnel through the aether has been established.");
10987
10988 }
10989 break;
10990 }
10991 case MEMENTO: {
10992
10993 rcm e = getpr(r.x, r.y + 1, r.z, world.getWorldId());
10994 if (e != null && e.runePattern != r.runePattern) {
10995 if (c(runeIdToRuneNameTable.get(r.runePattern), player,
10996 r.inkBlock))
10997 return true;
10998 player.ab(EnChat.YELLOW
10999 + "Something interferes the creation of your memento.");
11000 } else if (e != null && e.runePattern == r.runePattern) {
11001 if (e.inkBlock != r.inkBlock) {
11002 if (c(runeIdToRuneNameTable.get(r.runePattern), player,
11003 r.inkBlock))
11004 return true;
11005 e.inkBlock = r.inkBlock;
11006 player.ab(EnChat.GREEN
11007 + "You have altered the range of this memento.");
11008 } else {
11009 return false;
11010 }
11011 } else {
11012 if (c(runeIdToRuneNameTable.get(r.runePattern), player,
11013 r.inkBlock))
11014 return true;
11015 e = new rcm(r.runePattern, r.inkBlock, r.x, r.y + 1, r.z, r.w,
11016 0, 0, 0);
11017 addpr_addPositionRune(e);
11018 player.ab(EnChat.GREEN + "You have created a memento!");
11019 player.ab(EnChat.YELLOW
11020 + "Feed blocks into the centre to charge it. When active the memento will remember the area around it.");
11021 // create
11022 }
11023 // first set up t
11024 }
11025 case HELLMAW:
11026 case HELLMAW + 1: {
11027 if (!player.isPlayer())
11028 return false;
11029 if (c("Hell Maw", player, r.inkBlock))
11030 return true;
11031 r_removeEnchantmentFromToolType(TP_ARROWLAUNCH, r.toolArmorType,
11032 player);
11033
11034 f_addMagicToPlayer(player, EnChat.RED
11035 + "Use this bow to tear open the ground.", HELLMAW,
11036 TP_ARROWLAUNCH.getCode(), r.toolArmorType,
11037 (r.runePattern == HELLMAW) ? 7 : 1);
11038
11039 c(world, r, 5, 5);
11040 return true;
11041
11042 }
11043 case TRUENAMEALTAR:
11044 case TRUENAMEALTAR +1:
11045 {
11046
11047 DBG("Entered true name tower activater",player);
11048 if (!player.isPlayer())
11049 return false;
11050 if (c(runeIdToRuneNameTable.get(TRUENAMEALTAR), player, r.inkBlock))
11051 return true;
11052
11053 //step 1, create RCM
11054 //step 2, create RCT
11055 //step 3, create TNpoint
11056 for (RunePoint tnp : waypointList)
11057 {
11058 if (tnp instanceof WP_TrueName)
11059 {
11060 WP_TrueName trueName = (WP_TrueName)tnp;
11061 if( trueName.playerName.equals(player.aw_getName()) && trueName.exists());
11062 {
11063
11064 rcm ALoc= trueName.getAltarLocation();
11065 if (ALoc.w == r.w && ALoc.x == r.x && ALoc.y == r.y && ALoc.z == r.z)
11066 {
11067 int tns = trueName.getSig();
11068 int tnsd = trueName.getSigData();
11069 int newsig = gg(world, r.x, r.y-1, r.z, WAYPOINT, false);
11070 int newsigd = gg(world, r.x, r.y-1, r.z, WAYPOINT, true);
11071
11072 if ((newsig == 0 && newsigd == 0) ||(newsig == tns & newsigd == tnsd))
11073 {
11074 player.ab(EnChat.YELLOW + "You feel a gentle wave of energy roll from the altar in greeting");
11075 DBG("The signature for this TNA is "+tns+","+tnsd);
11076 }
11077 else
11078 {
11079 trueName.setSig(newsig,newsigd);
11080 player.ab(EnChat.GREEN + "You have changed the signature for your True Name");
11081 player.ab(EnChat.YELLOW + "The signature is no longer needed here.");
11082
11083 }
11084 return true;
11085 }
11086 else
11087 {
11088 player.ab(EnChat.RED + "The Aether cannot grant someone a second Truename Altar");
11089 return false;
11090 }
11091
11092 }
11093 }
11094
11095
11096 }
11097 //player doesn't have existing true name altar, verify head match.
11098 String skullName = world.getUserNameFromSkullBlock(r.x, r.y+2, r.z);
11099 if(skullName != null && !skullName.equals(player.aw_getName()))
11100 {
11101 player.ab(EnChat.RED + "You do not understand others' Truenames deeply enough for such subtle rune craft");
11102 return false;
11103 }
11104 g = gg(world, r.x, r.y-1, r.z,r.runePattern, false);
11105 gd = gg(world, r.x, r.y-1, r.z,r.runePattern, true);
11106
11107 //clear to create a NEW true name point huzzah
11108 WP_TrueName newTNP = new WP_TrueName(r,gt_getTierByMetaValue(r.inkBlock,r.metaData),g,gd,player,this);
11109 waypointList.add(newTNP);
11110 player.ab(EnChat.GREEN + "A new opening has been created in the fabric of the aether, centred on you!");
11111 player.ab(EnChat.GREEN + "A smaller opening leads back to this altar also opens");
11112
11113 player.ab(EnChat.YELLOW
11114 + "The signature is no longer needed here.");
11115 s_saveToMagicDat();
11116 return false;
11117 }
11118 case GENESIS:
11119 {
11120 //cannot use genesis within another's world
11121
11122 if (c(runeIdToRuneNameTable.get(GENESIS), player, r.inkBlock))
11123 return true;
11124 DBG(" Entered genesis");
11125
11126 RuneWorld gWorld = world;
11127 boolean match = false;
11128 for (RuneWorld rw : worlds.values())
11129 {
11130 //DBG(rw.getWorldFolder().getPath());
11131 if (rw.getWorldFolder().getPath().equals("." + File.separator + "RunecraftGenesis_"+player.aw_getName()))
11132 {
11133 gWorld = rw;
11134 match = true;
11135 }
11136 }
11137
11138 if (match)
11139 {
11140 //check if inside that world, if not: error
11141 //if inisde their demiplane, expand.
11142
11143 if (gWorld != null && gWorld.getWorldId() == r.w)
11144 {
11145 //expansion
11146 //
11147 for (RunePoint runepoint : waypointList)
11148 {
11149 //filters: If the runepoint's target world is the same world as the world the rune is in AND it's an anchor point
11150 if (runepoint.getCords().w == r.w && runepoint instanceof WP_AnchorPoint)
11151 {
11152
11153 WP_AnchorPoint dimP = (WP_AnchorPoint)runepoint;
11154 if (dimP.expanding) {player.ab(EnChat.RED+"Your world is already expanding"); return false;}
11155 rcm source = dimP.getCreationPoint();
11156 if ((dimP.getExpansionRadius()) < 48)
11157 {
11158 RCT_genesisExpansion animation = new RCT_genesisExpansion(player, dimP, this, getWorldById(source.w), gWorld);
11159 animation.loadWorldToBeCopied();
11160 //animation.dump();
11161 animation.scheduleSyncRepeating(ANIMATION_TICK_RATE, ANIMATION_TICK_RATE);
11162 //RCT_genesisExpansion animationTask = //new rct(this, gWorld,player,GENESIS,EnAction.TP_RIGHTCLICK);
11163 //animationTask.scheduleSyncRepeating(8, 8);
11164 }
11165 else
11166 {
11167 player.ab(EnChat.RED+"Your world is already at its full size!");
11168 }
11169 }
11170 }
11171
11172 }
11173 else
11174 {
11175
11176 player.ab(EnChat.RED+"The aether will not grant you a second world.");
11177 player.ab(EnChat.YELLOW+"You may use this rune to expand it from within");
11178 return false;
11179 }
11180
11181
11182 }
11183 else
11184 {
11185 //not inside. Create.
11186 DBG("No genesis found, creating.");
11187 String worldName = "RunecraftGenesis_"+player.aw_getName();
11188 EmptyWorldBuilder newWorld = new EmptyWorldBuilder(this,worldName);
11189 RuneWorld newRW = newWorld.getWorld();
11190 registerWorld(newRW);
11191 g = gg(world, r.x, r.y, r.z, WAYPOINT, false);
11192 gd = gg(world, r.x, r.y, r.z, WAYPOINT, true);
11193 DBG("Success? ["+newRW.getWorldId()+"]");
11194 newRW.e(0, 64, 0, BEDROCK);
11195
11196 WP_AnchorPoint newWorldPoint = new WP_AnchorPoint(r,g,gd,0,1,this,player);
11197 waypointList.add(newWorldPoint);
11198
11199 for (int y = 0; y <= 4; y++)
11200 for (int x = -y; x <= y; x++)
11201 for (int z = -y; z <= y; z++)
11202 {
11203 int b = world.a(r.x+x, r.y-y, r.z+z);
11204 int bd = world.b(r.x+x, r.y-y, r.z+z);
11205 //world.e(r.x+x,r.y-y,r.z+z,0);
11206 newRW.eSilently(0+x,69-y,0+z,b,bd);
11207 //DBG("Found ["+b+":"+bd+"] at ["+(r.x+x)+","+ (r.y-y)+","+ (r.z-z)+"] for reference XYZ = ("+x+","+y+","+z+")");
11208 }
11209
11210 aa(player,newRW, 0.5D, b_NextEmptySpace(newRW,0,65,0).y, 0.5D,player.v(), player.w());
11211 }
11212
11213
11214
11215 return true;
11216 }
11217 default: {
11218 DBG(EnChat.RED+"Found an untyped rune, ID " +r.runePattern + " at "+r.x+","+r.y+","+r.z+","+r.w,player);
11219 player.ab(EnChat.YELLOW+"You have no idea what this rune does. Neither does the aether.");
11220
11221 }
11222 }
11223
11224 return false;
11225 }
11226
11227 // get and check waypoint
11228
11229 private boolean blockIsManMade(int id) {
11230 boolean manMade = gt_getTier(id) > 1;// natural materials are low tier
11231 int[] naturalMaterials = { GOLD_ORE, IRON_ORE, COAL_ORE, LAPIS_ORE,
11232 SANDSTONE, SOULSAND, GLOWSTONE, DIAMOND_ORE, EMERALD_ORE };// high
11233 // tier
11234 // ores
11235 int[] manMadeMaterials = { COBBLESTONE, PLANK, GLASS, LAPIS_BLOCK,
11236 STONEBRICK, WOOL, BRICK_BLOCK };// low tier man made
11237 for (int block : naturalMaterials)
11238 if (id == block)
11239 return false;
11240 for (int block : manMadeMaterials)
11241 if (id == block)
11242 return true;
11243
11244 return manMade;
11245 }
11246
11247 private RunePlayer checkForHeadInSignature(RuneWorld world, int x, int y,
11248 int z, int activatingRune) {
11249 final int[][] coords = new int[][] { { 0, -1 }, { 1, 0 }, { 0, 1 },
11250 { -1, 0 } };
11251 for (final int[] delta : coords) {
11252 final int skullX = x + delta[0];
11253 final int skullY = y;
11254 final int skullZ = z + delta[1];
11255
11256 if (world.a(skullX, skullY, skullZ) == SKULLBLOCK) {
11257 final String skullName = world.getUserNameFromSkullBlock(
11258 skullX, skullY, skullZ);
11259 if (skullName != null && !skullName.isEmpty()) {
11260 return world.getPlayerByDisplayName(skullName);
11261 }
11262 }
11263 }
11264 return null;// if we get through all the blocks with no name match,
11265 // return null
11266 }
11267
11268 /**
11269 * This method checks the table of Rune uses that are generated from the
11270 * game balance spreadsheet. It takes a runeID and a tier block.
11271 *
11272 * @return Number of Uses
11273 * */
11274 int getUses(int runeID, int blockID, int metaData) {
11275 int tier = gt_getTierByMetaValue(blockID, metaData);
11276 String name = runeIdToRuneNameTable.get(runeID);
11277 int uses = runeUsesTable.get(name).get(tier);
11278
11279 return uses;
11280 }
11281
11282 /** Returns null if the waypoint signature cannot be found */
11283 int[] gacwp_getWaypointCoordinatesBySignature(int g, int gd) {
11284 return gacwp_getWaypointCoordinatesBySignature(g,gd,new RuneDummy(main_world, "INTERNAL_waypoint"));
11285 }
11286 int[] gacwp_getWaypointCoordinatesBySignature(int g, int gd, RunePlayer asker) {
11287 int fi;
11288 //int[] wp = null;
11289 RunePoint rp = null;
11290 // find waypoint with signature g
11291 //DBG("Seeking "+Chat.YELLOW+g+Chat.GREEN+":"+Chat.YELLOW+gd);
11292 for (fi = 0; fi < waypointList.size(); ++fi) {
11293 rp = waypointList.get(fi);
11294 if (g == rp.getSig() && gd == rp.getSigData())
11295 break;
11296 //DBG(Chat.YELLOW+""+rp.getSig()+Chat.GREEN+":"+Chat.YELLOW+rp.getSigData());
11297 }
11298
11299 // signature not found
11300 if (fi == waypointList.size()) {
11301 DBG(EnChat.YELLOW+"=Signature not found=");
11302 return null;
11303 }
11304
11305 // Check that referenced world exists
11306 final RuneWorld w = getWorldById(rp.getCords().w);
11307 if (w == null) {
11308 logInfo("A waypoint (" + rp.getCords().x + "," + rp.getCords().y + "," + rp.getCords().z
11309 + ") is broken because its world (id " + rp.getCords().w
11310 + ") is not loaded.");
11311 waypointRuneList.remove(fi); // world is not loaded; remove WP from
11312 // list
11313 s_saveToMagicDat();
11314 return null;
11315 }
11316
11317 if (!rp.exists()){
11318 DBG("Not intact removing");
11319 waypointList.remove(rp);
11320 s_saveToMagicDat();
11321 return null;
11322 }
11323
11324 rcm returnCords = rp.getCords(asker);
11325 int returnvals[] = {rp.getSig(),rp.getSigData(),returnCords.x,returnCords.y,returnCords.z,returnCords.w,rp.getTier(),rp.getFacing()};
11326 return returnvals;
11327 //waypointRuneList.remove(fi); // not intact: remove from list
11328
11329
11330 }
11331
11332 // update proximity list for rune pads
11333 void oa(RunePlayer p) {
11334 RuneWorld w = p.getWorld();
11335 int wid = getWorldId(w);
11336 synchronized (rplp) {
11337 if (rplp.get(p.aw_getName()) == null)
11338 rplp.put(p.aw_getName(), new Vector<Integer>());
11339 Vector<Integer> li = rplp.get(p.aw_getName());
11340 li.clear();
11341 synchronized (runePadList) {
11342 for (int i = 0; i < runePadList.size(); i++) {
11343 int[] ta = runePadList.get(i);
11344 if (ta == null)
11345 continue;
11346 if (wid != ta[4])
11347 continue;
11348 if ((p.x() - ta[1]) * (p.x() - ta[1]) + (p.y() - ta[2])
11349 * (p.y() - ta[2]) + (p.z() - ta[3])
11350 * (p.z() - ta[3]) < 4000)
11351 li.add(i);
11352 }
11353 }
11354 }
11355 }
11356
11357 // update proximity list for rune pads using mobs
11358 void oam(RuneWorld w) {
11359 int wid = getWorldId(w);
11360 synchronized (runePadList) {
11361 for (int i = 0; i < runePadList.size(); i++) {
11362 int[] ta = runePadList.get(i);
11363 if (ta == null)
11364 continue;
11365 if (wid != ta[4])
11366 continue;
11367 rplm.put(new rcm(ta[1], ta[2], ta[3], wid),
11368 w.getMobs(ta[1], ta[2], ta[3], 32, 32, 32, false));
11369 }
11370 }
11371 }
11372
11373 // remove rune pad @x,y,z,w from list
11374 void drpl(RuneWorld w, int x, int y, int z) {
11375 int wid = getWorldId(w);
11376 synchronized (runePadList) {
11377 final Iterator<int[]> iter = runePadList.iterator();
11378 while (iter.hasNext()) {
11379 final int[] ta = iter.next();
11380 if (ta[1] == x && ta[2] == y && ta[3] == z && ta[4] == wid)
11381 iter.remove();
11382 }
11383
11384 for (RunePlayer p : w.getPlayers())
11385 oa(p);
11386 }
11387 synchronized (rplm) {
11388 rplm.remove(new rcm(x, y, z, wid));
11389 }
11390 }
11391
11392 void r(RunePlayer pl, int t) {
11393 long[] lol = { t, System.currentTimeMillis() };
11394 RCT_main.ld.put(pl.aw_getName(), lol);
11395 }
11396
11397 RCT_main t(RuneWorld w, int tsk, int[] ar, RunePlayer pl, EnAction tp) {
11398 RCT_main ts = new RCT_main(this, w, pl, tsk, tp);
11399 ts.ia = ar;
11400 return ts;
11401
11402 }
11403
11404 RCT_main t(RuneWorld w, int tsk, int[] ar, RunePlayer pl) {
11405 RCT_main ts = new RCT_main(this, w, pl, tsk);
11406 ts.ia = ar;
11407 return ts;
11408 }
11409
11410 RCT_main t(RuneWorld world, int task, RunePlayer player, int... arguments) {
11411 return t(world, task, arguments, player);
11412 }
11413
11414 void f_addMagicToPlayer(RunePlayer player, int[] ar, String msg) {
11415 List<int[]> l = sl.get(player.aw_getName());
11416 if (l == null) {
11417 l = createLList();
11418 sl.put(player.aw_getName(), l);
11419 }
11420 // DBG("Added enchant to a player."+ar[0]+","+ar[1]+","+ar[2]+","+ar[3]+","+ar[4],player);
11421 l.add(ar);
11422 if (!msg.isEmpty())
11423 player.ab(msg);
11424 s_saveToMagicDat();
11425 }
11426
11427 /**
11428 * Silently increases the nubmer of uses in ia[usesID] by IncreaseAmmount
11429 *
11430 * @param player
11431 * @param tp
11432 * - trigger activator
11433 * @param tool
11434 * - tool ID
11435 * @param runeID
11436 * - rune ID
11437 * @param usesID
11438 * - the Integer Array index for uses
11439 * @param increaseAmmount
11440 * - this is the number to be added,
11441 * @param en
11442 * - if engraved item
11443 */
11444 void f_addMoreUsesToEnch(RunePlayer player, int tp, int tool, int runeID,
11445 int usesID, int increaseAmmount, boolean en) {
11446 /*
11447 * List<int[]> l = sl.get(player.aw_getName()); if (l == null) { l =
11448 * createLList(); sl.put(player.aw_getName(), l); }
11449 * DBG("Added enchant to a player."
11450 * +ar[0]+","+ar[1]+","+ar[2]+","+ar[3]+","+ar[4],player);
11451 *
11452 * if (!msg.isEmpty()) player.ab(msg); s_saveToMagicDat();
11453 */
11454
11455 }
11456
11457 boolean g(int tl) // checks if tool is golden tool/armor
11458 {
11459 return golden.contains(tl);
11460 }
11461
11462 void f_addMagicToPlayer(RunePlayer pl, String msg, int... ar) {
11463 f_addMagicToPlayer(pl, ar, msg);
11464 }
11465
11466 void s(RuneWorld w, int x, int y, int z, int v, int c, short d) {
11467 v = b(v);
11468 if (v != 0)
11469 w.s(x, y, z, v, c, d);
11470 }
11471
11472 void s(RuneWorld w, int x, int y, int z, int v, int c) {
11473 s(w, x, y, z, v, c, (short) 0);
11474 }
11475
11476 void s(RuneWorld w, int x, int y, int z, int v) {
11477 s(w, x, y, z, v, 1);
11478 }
11479
11480 static int af(int a) {
11481 if (liquids.contains(a))
11482 return 0;
11483 return a;
11484 }
11485
11486 static boolean n(int a) {
11487 // no method. illegal blocks here.
11488 // chest furnace furnace diamond sign sign door door
11489 return (a == 54 || a == 61 || a == 62 || a == 57 || a == 63 || a == 68
11490 || a == 64 || a == 71 || a == BEDROCK);
11491 }
11492
11493 static boolean lb(int a) {
11494 // latch method. blocks that attach to other blocks here
11495 // for use in Faith, TT & large movement operations
11496
11497 return latchblocks.contains(a);
11498
11499 }
11500
11501 // checks if an option is set via config file or other means
11502 protected boolean opt_on(String n) {
11503 return opt.contains(n);
11504 }
11505
11506 protected String opt_val(String n) {
11507 return "";
11508 }
11509
11510 // utility: fills map from array. See class rct.
11511 protected static Map<Integer, String> map_is(Object... args) {
11512 Map<Integer, String> map = createMap();
11513 for (int i = 0; i + 1 < args.length; i += 2) {
11514 map.put((Integer) args[i], (String) args[i + 1]);
11515 }
11516 return map;
11517 }
11518
11519 // utility methods
11520 // usage: Set<String> myset = createSet();
11521 protected static <T> Set<T> createSet() {
11522 return new HashSet<T>();
11523 }
11524
11525 protected static <T> Set<T> createLinkedSet() {
11526 return new LinkedHashSet<T>();
11527 }
11528
11529 protected static <K, V> Map<K, V> createMap() {
11530 return new HashMap<K, V>();
11531 }
11532
11533 protected static <T> List<T> createLList() {
11534 return new LinkedList<T>();
11535 }
11536
11537 protected static <T> List<T> createAList() {
11538 return new ArrayList<T>();
11539 }
11540
11541 boolean FTP(rcm r, RunePlayer pl, RuneWorld w) {
11542 // FTP: Detect Faith island
11543 /*
11544 * STEP 1: global validation - initiation - find a local faith island
11545 * STEP 2:
11546 */
11547 boolean ie = rlc("initiation");
11548 int i = 0;
11549
11550 final int find = findFaithIsland(r.x, r.y, r.z, r.w);
11551
11552 if (find < 0) {
11553 pl.ab(EnChat.GREEN + "Faith Transfer Portal used.");
11554 pl.ab(EnChat.RED
11555 + "The land around you is not stable enough to travel");
11556 return true;
11557 }
11558
11559 if (mfrl.contains(find)) {
11560 pl.ab(EnChat.RED + "This land is already moving!");
11561 return true;
11562 }
11563
11564 final int fi[] = faithRuneList.get(find);
11565
11566 if (checkForOverlappingMovingIsland(fi)) {
11567 pl.ab(EnChat.RED + "The aether nearby is too tense!");
11568 return true;
11569 }
11570
11571 int rd = fi[3];
11572 int g = gg(w, r.x, r.y, r.z, r.runePattern, false);
11573 int gd = gg(w, r.x, r.y, r.z, r.runePattern, true);
11574 if (g == 0) // being used without sig blocks
11575 {
11576 // DBG("sig blocks missing: attempting TP",pl);
11577 if (!pl.c("teleport", null)) {
11578 pl.ab(EnChat.RED + "You cannot invoke teleportation.");
11579 return true;
11580 }
11581
11582 pl.ab(EnChat.GREEN + "Faith Transfer Portal used.");
11583
11584 for (i = 0; i < teleportRuneList.size(); i++) {
11585 int[] ta = teleportRuneList.get(i);
11586 if (ta[0] == r.x && ta[1] == r.y && ta[2] == r.z
11587 && ta[3] == r.w) {
11588 g = ta[4];
11589 gd = ta[5];
11590 break;
11591 }
11592 }
11593
11594 if (g == 0) {
11595 if (!ie || ip.contains(pl.aw_getName()))
11596 pl.ab(EnChat.RED + "You have not specified a destination.");
11597 return true;
11598 }
11599 int[] ta = gacwp_getWaypointCoordinatesBySignature(g, gd); // get
11600 // waypoint
11601 // desc
11602 if (ta == null) {
11603 pl.ab(EnChat.RED
11604 + "Your way has been barred from the other side.");
11605 return false;
11606 }
11607 if ((!rlc("enable multiworld travel") && r.w != ta[5])
11608 || wgc(r.w, ta[5], r.inkBlock,
11609 runeIdToRuneNameTable.get(r.runePattern)) == false) {
11610 pl.ab(EnChat.RED
11611 + "The distance to the destination is too large.");
11612 return false;
11613 }
11614
11615 if (wdc(r, WardType.Teleport)) {
11616 pl.ab(EnChat.RED
11617 + "There is a ward enveloping this rune. It cannot move the Faith Island");
11618 return true;
11619 }
11620
11621 final RuneWorld ww1 = getWorldById(r.w);
11622 final RuneWorld ww2 = getWorldById(ta[5]);
11623
11624 if (ww1 == null || ww2 == null) {
11625 // DBG(Chat.RED + "target world ["+ta[5]+"] is null. ",pl);
11626 return false;
11627 }
11628
11629 if (!ResidenceChecker.residenceCheck(pl.aw_getName(), fi[0], fi[1],
11630 fi[2], fi[3], ww1, ResFlags.FaithFlags)) {
11631 pl.ab(EnChat.RED + "The aether refuses to aid in this theft.");
11632 return false;
11633 }
11634
11635 if (!ResidenceChecker.residenceCheck(pl.aw_getName(), ta[2], ta[3],
11636 ta[4], fi[3], ww2, ResFlags.FaithFlags)) {
11637 pl.ab(EnChat.RED + "The aether refuses to invade this territory.");
11638 return false;
11639 }
11640
11641 logInfo(pl.aw_getName()
11642 + " took an island through a teleporter to " + g + gd + ".");
11643
11644 ww2.eAd(ta[2] - (rd), ta[4] - (rd)); // force chunk loading
11645 ww2.eAd(ta[2] + (rd), ta[4] + (rd));
11646 ww2.eAd(ta[2] + (rd), ta[4] - (rd));
11647 ww2.eAd(ta[2] - (rd), ta[4] + (rd));
11648
11649 if (RunecraftParser.a_runeDetection(
11650 wr_runeTemplateArray[FAITHPOINT - 1], ww2, ta[2], ta[3],
11651 ta[4]) == 0
11652 && RunecraftParser.a_runeDetection(
11653 wr_runeTemplateArray[WALLFPOINT - 1], ww2, ta[2],
11654 ta[3], ta[4]) == 0
11655 && RunecraftParser.a_runeDetection(
11656 wr_runeTemplateArray[WALLFPOINT], ww2, ta[2],
11657 ta[3], ta[4]) == 0) {
11658
11659 pl.ab(EnChat.RED
11660 + "The destination must be anchored more securely.");
11661 DBG("unanchored destination is at [" + EnChat.YELLOW + ta[2]
11662 + "," + ta[3] + "," + ta[4] + EnChat.GREEN + "]");
11663 return false;
11664 }
11665 // assume (ta == null || g == ta[0])
11666
11667 if ((!rlc("enable multiworld travel") && r.w != ta[5])
11668 || wgc(r.w, ta[5], r.inkBlock,
11669 runeIdToRuneNameTable.get(r.runePattern)) == false) {
11670 pl.ab(EnChat.RED
11671 + "The distance to the destination is too large.");
11672 return false;
11673 }
11674
11675 // DBG("loaded chunks at the following world ["+ww2.getWorldFolder()+"]",
11676 // pl);
11677
11678 // 0(down) 1(up) 2(east) 3(west) 4(north) 5(south)
11679 // y-1 y+1 x+1 x-1 z-1 z+1
11680 int bx = ta[2];
11681 int by = ta[3];
11682 int bz = ta[4];
11683 switch (ta[7]) {
11684 case 0:
11685 by = b(ww2, ta[2], ta[3], ta[4], ta[7]).y - rd;
11686 break; // down
11687 default:
11688 case 1:
11689 by = b(ww2, ta[2], ta[3], ta[4], 1).y + rd;
11690 break; // up
11691 case 4:
11692 bz = b(ww2, ta[2], ta[3], ta[4], ta[7]).z - rd;
11693 break; // north
11694 case 5:
11695 bz = b(ww2, ta[2], ta[3], ta[4], ta[7]).z + rd;
11696 break; // south
11697 case 3:
11698 bx = b(ww2, ta[2], ta[3], ta[4], ta[7]).x - rd;
11699 break; // west
11700 case 2:
11701 bx = b(ww2, ta[2], ta[3], ta[4], ta[7]).x + rd;
11702 break; // east
11703 }
11704 DBG("the originals are [" + EnChat.YELLOW + ta[2] + "," + ta[3] + ","
11705 + ta[4] + EnChat.GREEN + "] updated to [" + EnChat.YELLOW + bx
11706 + "," + by + "," + bz + EnChat.GREEN + "]");
11707 // set arrival point of island
11708 if (by + fi[3] > 256 || by - fi[3] < 0) {
11709 pl.ab(EnChat.RED
11710 + "This spell may not remove materials from the mortal plane...");
11711 return false;
11712 }
11713
11714 // FTP: BEGIN CHECKING DESTINATION AREA FOR BLOCKS
11715
11716 // DBG("destination = ["+ta[2]+","+bb+","+ta[4]+"] world ["+ta[5]+"]",pl);
11717
11718 if (wdc(new rcm(bx, by, bx, ww2.getWorldId()), WardType.Teleport)) {
11719 DBG("Blocked teleporter", pl);
11720 pl.ab(EnChat.RED
11721 + "There is a ward at your destination preventing teleportation");
11722 return false;
11723 }
11724
11725 i = 0;
11726
11727 // wpl
11728 // rpl
11729 // ldl
11730 // fwpl
11731
11732 // DBG("saught radius = " + ((rd+0.5)*(rd+0.5)),pl);
11733 for (int x = -rd; x < rd + 1; x++)
11734 for (int z = -rd; z < rd + 1; z++)
11735 for (int y = -rd; y < rd + 1; y++) {
11736 i++;
11737 // if (radiuscheck(x, y, z, rd) &&
11738 // !radiuscheck(x,y,z,rd-1.1))
11739 // {
11740 // w.e(fi[0]+x,fi[1]+y,fi[2]+z,OBSIDIAN);
11741 // }
11742 if ((x * x) + (y * y) + (z * z) < (rd + 0.5)
11743 * (rd + 0.5)) {
11744
11745 // check source block
11746 int sb = w.a(fi[0] + x, fi[1] + y, fi[2] + z);
11747 // override allowing Chests, Furnaces, Dispensers
11748 // and Bedrock to move.
11749 if (n(sb) && sb != CHEST && sb != 23 && sb != 61
11750 && sb != 62 && sb != SIGN_POST
11751 && sb != WALL_SIGN && sb != BEDROCK) {
11752 pl.ab(EnChat.RED
11753 + "The aether has rejected your greedy request...");
11754 DBG("banned item [" + sb + "] is at ["
11755 + (fi[0] + x) + "," + (fi[1] + y) + ","
11756 + (fi[2] + z) + "]", pl);
11757 return true;
11758 }
11759
11760 // check destination block
11761 if (ww2.a(bx + x, by + y, bz + z) != 0) {
11762
11763 pl.ab(EnChat.RED
11764 + "There are obstacles at your destination.");
11765
11766 DBG("obstacle ["
11767 + ww2.a(bx + x, by + y, bz + z)
11768 + "] is at [" + (bx + x) + ","
11769 + (by + y) + "," + (bz + z)
11770 + "], distance: "
11771 + ((x * x) + (y * y) + (z * z)), pl);
11772 DBG("Destination's central point is ["
11773 + EnChat.YELLOW + (bx) + "," + (by) + ","
11774 + (bz) + EnChat.GREEN + "]");
11775 return true;
11776
11777 }
11778 /*
11779 * if (getpr(ta[2]+x, bb+y, ta[4]+ z,ta[5]) !=
11780 * null){ pl.ab(Chat.RED+
11781 * "There is interfering residual magic at the destination."
11782 * ); DBG(Chat.RED +"at " +(ta[2]+x) +","+ (bb+y) +
11783 * ","+ (ta[4]+ z) +","+ta[5] +
11784 * " of type "+getpr(ta[2]+x, bb+y, ta[4]+
11785 * z,ta[5]).a,pl); return true; }
11786 */// magic collisions are currently to difficult to
11787 // find. a way of highlighting collisions needs
11788 // to be found, whilst not being immersive
11789 }
11790 }
11791
11792 // RuneWorld w, int tsk, int[] ar, RunePlayer pl)
11793 // DBG("Entering the glass sphere",pl);
11794 int grd = rd + 1;
11795
11796 for (int x = -grd; x < grd + 1; x++)
11797 for (int z = -grd; z < grd + 1; z++) {
11798 for (int y = -grd; y < grd + 1; y++) {
11799
11800 double pos = (Math.sqrt((x * x) + (y * y) + (z * z)));
11801
11802 i++;
11803 if (pos >= grd - 0.5 && pos <= grd + 0.5) {
11804
11805 if (w.a(fi[0] + x, fi[1] + y, fi[2] + z) == 0) {
11806 if (addpr_addPositionRune(new rcm(FTP, GLASS,
11807 fi[0] + x, fi[1] + y, fi[2] + z,
11808 w.getWorldId(), 0, 0)))
11809 w.e(fi[0] + x, fi[1] + y, fi[2] + z, GLASS);
11810 // w.e(fi[0]+x,fi[1]+y,fi[2]+z,35);
11811 }
11812 // ww2.e(ta[2]+x,bb+y,ta[4]+z,20,rd);
11813 if (ww2.a(bx + x, by + y, bz + z) == 0) {
11814 if (addpr_addPositionRune(new rcm(FTP, GLASS,
11815 bx + x, by + y, bz + z,
11816 ww2.getWorldId(), 0, 0)))
11817 ww2.e(bx + x, by + y, bz + z, GLASS);
11818 }
11819 }
11820 }
11821 }// pl.ab(str); str = "";
11822
11823 // DBG("Glass sphere complete");
11824 // pl.ab(Chat.YELLOW + w.getWorldId());
11825 pl.ab(EnChat.YELLOW + "The aether suddenly tenses around you!");
11826 // rct t =
11827 // t(w,115,pl,bx,by,bz,ta[5],fi[0],fi[1],fi[2],fi[3],fi[3],find);
11828 RCT_main t = t(w, 115, pl, bx, by, bz, ta[5], fi[0], fi[1], fi[2],
11829 fi[3], -1, find);
11830
11831 t.scheduleSyncRepeating(7, 7);
11832 mfrl.add(find);
11833 // latch blocks removed and stored. Begin
11834
11835 return true;
11836
11837 }
11838
11839 else { // there are sig blocks.
11840 // DBG("Sig blocks detected",pl);
11841 if (!pl.isEntity())
11842 return false;
11843 if (ie && !ip.contains(pl.aw_getName()))
11844 return false;
11845 if (rlc("enable travel ink"))
11846 if (!rlc("ink " + r.inkBlock)) {
11847 pl.ab(EnChat.RED
11848 + "The aether demands that this rune be made with a");
11849 pl.ab(EnChat.RED + "different material!");
11850 return true;
11851 }
11852 if (c("faith transfer portal", pl, "set up an FTP", r.inkBlock))
11853 return true;
11854
11855 int[] wpp = gacwp_getWaypointCoordinatesBySignature(g, gd); // get
11856 // faith
11857 // desc
11858
11859 if (wpp == null) {
11860 pl.ab(EnChat.RED + "Such a destination has not been opened.");
11861 return true;
11862 }
11863
11864 final RuneWorld remoteWorld = getWorldById(wpp[5]);
11865
11866 if (RunecraftParser.a_runeDetection(
11867 wr_runeTemplateArray[FAITHPOINT - 1], remoteWorld, wpp[2],
11868 wpp[3], wpp[4]) == 0
11869 && RunecraftParser.a_runeDetection(
11870 wr_runeTemplateArray[WALLFPOINT - 1], remoteWorld,
11871 wpp[2], wpp[3], wpp[4]) == 0
11872 && RunecraftParser.a_runeDetection(
11873 wr_runeTemplateArray[WALLFPOINT], remoteWorld,
11874 wpp[2], wpp[3], wpp[4]) == 0) {
11875 pl.ab(EnChat.RED + "The destination is too weak to support this.");
11876 return true;
11877 }
11878
11879 if ((!rlc("enable multiworld travel") && r.w != wpp[5])
11880 || wgc(r.w, wpp[5], r.inkBlock,
11881 runeIdToRuneNameTable.get(r.runePattern)) == false) {
11882 pl.ab(EnChat.RED
11883 + "The distance to the destination is too large.");
11884 return true;
11885 }
11886
11887 eraseFTPsignature(r);
11888
11889 for (i = 0; i < teleportRuneList.size(); i++) {
11890 int[] ta = teleportRuneList.get(i);
11891 if (ta[0] == r.x && ta[1] == r.y && ta[2] == r.z
11892 && ta[3] == r.w) {
11893 ta[4] = g;
11894 ta[5] = gd;
11895 s_saveToMagicDat(); // replace active teleporter
11896 pl.ab(EnChat.GREEN
11897 + "A new course through the aether has been established.");
11898 teleportRuneList.set(i, ta);
11899 return true;
11900
11901 }
11902 }
11903 int[] ta = { r.x, r.y, r.z, r.w, g, gd }; // create new teleporter
11904 // DBG("Standard TP created @ ["+r.x+","+ r.y +","+ r.z +","+ r.w
11905 // +"] to ["+ g+","+ gd+"]",pl);
11906 teleportRuneList.add(ta);
11907 s_saveToMagicDat();
11908 pl.ab(EnChat.GREEN
11909 + "A tunnel through the aether has been established.");
11910 }
11911 return true;
11912
11913 }
11914
11915 /**
11916 * Consume the signature blocks of an FTP rune
11917 *
11918 * @param r
11919 * rcm pointing at the rune with the signature to erase
11920 */
11921 private void eraseFTPsignature(rcm r) {
11922
11923 final RuneWorld w = getWorldById(r.w);
11924
11925 if (r.runePattern == FTP || r.runePattern == WALLFTP + 1) {
11926 c(w, r.x, r.y, r.z - 3, 0);
11927 c(w, r.x, r.y, r.z + 3, 0);
11928 }
11929
11930 if (r.runePattern == FTP || r.runePattern == WALLFTP) {
11931 c(w, r.x - 3, r.y, r.z, 0);
11932 c(w, r.x + 3, r.y, r.z, 0);
11933 }
11934
11935 if (r.runePattern == WALLFTP || r.runePattern == WALLFTP + 1) {
11936 c(w, r.x, r.y + 3, r.z, 0);
11937 c(w, r.x, r.y - 3, r.z, 0);
11938 }
11939 }
11940
11941 /**
11942 * @param pl
11943 * @param fi
11944 */
11945 private boolean checkForOverlappingMovingIsland(final int[] fi) {
11946 for (final int j : mfrl) {
11947 final int[] fa = faithRuneList.get(j);
11948
11949 // Blocking check, planning to improve to a non-blocking method
11950 // non-blocking check: find potentially blocking islands. Instead of
11951 // saving data from these blocks, replace with air in saved data.
11952 // try to use this to
11953 if ((fa[4] == -1 || fi[4] == -1 || fa[4] == fi[4])
11954 && radiuscheck(fi[0], fi[1], fi[2], fa[0], fa[1], fa[2],
11955 fa[3] + fi[3] + 1)) {
11956 return true;
11957 }
11958 }
11959 return false;
11960 }
11961
11962 /**
11963 * Find the index of the smallest faith island that contains the given
11964 * coordinates. On failure, return a number less than 0
11965 *
11966 * @return either the index of a faith island or a negative number
11967 */
11968 private int findFaithIsland(int x, int y, int z, int w) {
11969 int i;
11970 int fiid = -1;
11971 int[] smallest = null;
11972
11973 for (i = 0; i < faithRuneList.size(); i++) {
11974 final int[] fa = faithRuneList.get(i);
11975
11976 if ((fa[4] == -1 || fa[4] == w)
11977 && radiuscheck(fa[0], fa[1], fa[2], x, y, z, fa[3] + 0.5)) {
11978 if (smallest == null || fa[3] < smallest[3]) {
11979 fiid = i;
11980 smallest = fa;
11981 }
11982 }
11983 }
11984
11985 if (smallest != null) {
11986 DBG("connected island " + fiid + "is [" + smallest[0] + ","
11987 + smallest[1] + "," + smallest[2] + "], radius ["
11988 + smallest[3] + "]");
11989 }
11990
11991 return fiid;
11992 }
11993
11994 private int[] calcFi() {
11995 List<Integer> radii = runeUsesTable.get(runeIdToRuneNameTable
11996 .get(FAITH));
11997 int caprd = radii.get(radii.size() - 1) + 1; // rds[rds.length-1]+1;
11998 int fi[] = { 0, 0, 0, caprd, 0 };
11999 return fi;
12000 }
12001
12002 public void DBG(String m, RuneWorld w) {
12003 DBG(m);
12004 }
12005
12006 public void DBG(String m, RunePlayer pl) {
12007 if (!pl.aw_getName().equals("Zombie Pigman")) {
12008 m = EnChat.RED + pl.aw_getName() + ", " + EnChat.GREEN + m;
12009 DBG(m);
12010 }
12011 }
12012
12013 public void DBG(String m) {
12014 for (RunePlayer pl : main_world.getPlayers()) {
12015 if (dbgl.contains(pl.aw_getName())) {
12016 pl.ab(EnChat.PURPLE + "DBG: " + EnChat.GREEN + m);
12017 } else {
12018 // pl.ab("not authorised");
12019 }
12020 }
12021
12022 }
12023
12024 public void aa(RunePlayer pl, RuneWorld wo, double x, double y, double z,
12025 float v, float w) {
12026 // Check the player
12027 if (wdc(pl, WardType.Teleport)) {
12028 return;
12029 }
12030
12031 // Check the rune
12032 if (wdc(new rcm((int) x, (int) y, (int) z, wo.getWorldId()),
12033 WardType.Teleport)) {
12034 pl.ab(EnChat.RED
12035 + "There is a ward at your destination blocking your teleportation");
12036 return;
12037 }
12038
12039 rcm c = getcr((int) Math.floor(x), (int) Math.floor(y) - 1,
12040 (int) Math.floor(z), wo.getWorldId());
12041 DBG("searching for CR at " + (int) Math.floor(x) + ","
12042 + ((int) Math.floor(y) - 1) + "," + (int) Math.floor(z) + ","
12043 + wo.getWorldId(), pl);
12044
12045 // wo.smite((int)x,(int)y,(int)z);
12046 pl.aa(wo, x, y, z, v, w);
12047 if (c != null) {
12048 DBG("teleport trap triggered [" + c.runePattern + "]", pl);
12049 pr_doPositionRune(pl, TP_TELEPORT, 0, c, null, 0);
12050 }
12051 }
12052
12053 public void aa(RunePlayer pl, double x, double y, double z) {
12054
12055 aa(pl, x, y, z, 0, pl.getWorld().getWorldId());
12056 }
12057
12058 public void aa(RunePlayer pl, double x, double y, double z, float v, float w) {
12059
12060 aa(pl, pl.getWorld(), x, y, z, v, w);
12061 }
12062
12063 public void mtps(rcm s, rcm t, int rd) {
12064 // helper function to move teleports from S.x,s.y,s.z,s.w to t.x,
12065 // t.y,t.z,t.w
12066 // whilst within radius rd of s
12067
12068 for (final int[] tp : teleportRuneList) {
12069 if (tp[3] == s.w) {
12070 int rx = s.x - tp[0];
12071 int ry = s.y - tp[1];
12072 int rz = s.z - tp[2];
12073
12074 if ((rx * rx + ry * ry + rz * rz) < ((rd + 0.5) * (rd + 0.5))) {
12075 tp[0] = t.x - rx;
12076 tp[1] = t.y - ry;
12077 tp[2] = t.z - rz;
12078 tp[3] = t.w;
12079 }
12080 }
12081 }
12082
12083 }
12084
12085 public void mfrs(rcm s, rcm t, int rd) {
12086 for (int i = 0; i < faithRuneList.size(); i++) {
12087 int[] fi;
12088 int[] fa = faithRuneList.get(i);
12089 if (fa.length < 5) // code to handle Faith Islands created before
12090 // they had world IDs
12091 {
12092
12093 int fix = fa[0];
12094 int fiy = fa[1];
12095 int fiz = fa[2];
12096 int fird = fa[3];
12097 fi = new int[5];
12098 fi[0] = fix;
12099 fi[1] = fiy;
12100 fi[2] = fiz;
12101 fi[3] = fird;
12102 fi[4] = s.w;
12103 faithRuneList.set(i, fi);
12104 } else {
12105 fi = fa;
12106 }
12107
12108 if (fi[4] == s.w || fi[4] < 0) {
12109 int rx = s.x - fi[0];
12110 int ry = s.y - fi[1];
12111 int rz = s.z - fi[2];
12112
12113 if ((rx * rx + ry * ry + rz * rz) < ((rd + 0.5) * (rd + 0.5))) {
12114
12115 /*
12116 * DBG("Island found at ["+Chat.YELLOW+fi[0]+","+fi[1]+","+fi
12117 * [2]+","+fi[4]+Chat.GREEN+"]" +
12118 * " moved to ["+Chat.YELLOW+(t.x- rx)+","+(t.y-
12119 * ry)+","+(t.z-
12120 * rz)+","+t.w+Chat.GREEN+"]",getWorldById(t.w));
12121 */
12122 fi[0] = t.x - rx;
12123 fi[1] = t.y - ry;
12124 fi[2] = t.z - rz;
12125 fi[4] = t.w;
12126 // tpl.set(i,tp);
12127
12128 }
12129 }
12130 }
12131
12132 }
12133
12134 public void mwps(rcm s, rcm t, int rd) {
12135 for (final int[] ta : waypointRuneList) {
12136 if (ta[5] == s.w) {
12137 int rx = s.x - ta[2];
12138 int ry = s.y - ta[3];
12139 int rz = s.z - ta[4];
12140
12141 if ((rx * rx + ry * ry + rz * rz) < ((rd + 0.5) * (rd + 0.5))) {
12142 // rmm.DBG("found a TP in range ["+rmm.Chat.YELLOW+ta[0]+","+ta[1]+","+ta[2]+rmm.Chat.GREEN+"] <"+ta[3]+">",pl);
12143 ta[2] = t.x - rx;
12144 ta[3] = t.y - ry;
12145 ta[4] = t.z - rz;
12146 ta[5] = t.w;
12147 // m.wpl.set(i,tp);
12148 }
12149 }
12150 }
12151
12152 for (int i = 0; i < waypointList.size(); i++) {
12153 RunePoint ta = waypointList.get(i);
12154 final rcm coords = ta.getCords();
12155 if (coords.w == s.w) {
12156 int rx = s.x - coords.x;
12157 int ry = s.y - coords.y;
12158 int rz = s.z - coords.z;
12159
12160 if (radiuscheck(rx, ry, rz, rd + 0.5)) {
12161 // rmm.DBG("found a TP in range ["+rmm.Chat.YELLOW+ta[0]+","+ta[1]+","+ta[2]+rmm.Chat.GREEN+"] <"+ta[3]+">",pl);
12162 ta.setCords(t.x - rx, t.y - ry, t.z - rz, t.w);
12163 // m.wpl.set(i,tp);
12164 }
12165 }
12166 }
12167 }
12168
12169 public void mrps(rcm s, rcm t, int rd) {
12170 // DBG("Moving runepads "+rpl.size() +
12171 // " from source "+s.x+","+s.y+","+s.z+" to "+t.x+","+t.y+","+t.z);
12172 for (final int[] rp : runePadList) {
12173 if (rp[4] == s.w) {
12174 int rx = s.x - rp[1];
12175 int ry = s.y - rp[2];
12176 int rz = s.z - rp[3];
12177
12178 if ((rx * rx + ry * ry + rz * rz) < ((rd + 0.5) * (rd + 0.5))) {
12179 rp[1] = t.x - rx;
12180 rp[2] = t.y - ry;
12181 rp[3] = t.z - rz;
12182 rp[4] = t.w;
12183 }
12184
12185 // 0 1 2 3 4
12186 // r.a, r.x,r.y,r.z,r.w,
12187 }
12188 }
12189
12190 }
12191
12192 public void mwds(rcm s, rcm t, int rd) {
12193 // DBG("Moving wards "+wdl.size() +
12194 // " from source "+s.x+","+s.y+","+s.z+" to "+t.x+","+t.y+","+t.z);
12195 for (final int[] wd : wardRuneList) {
12196 if (wd[3] == s.w) {
12197 int rx = s.x - wd[0];
12198 int ry = s.y - wd[1];
12199 int rz = s.z - wd[2];
12200
12201 if ((rx * rx + ry * ry + rz * rz) < ((rd + 0.5) * (rd + 0.5))) {
12202 wd[0] = t.x - rx;
12203 wd[1] = t.y - ry;
12204 wd[2] = t.z - rz;
12205 wd[3] = t.w;
12206 }
12207 }
12208 }
12209 // [x,y,z,w,radius,state,type]
12210
12211 }
12212
12213 public void mlps(rcm s, rcm t, int rd) {
12214 // rmm.DBG("Automation target size: "+m.rpl.size(), pl);
12215 for (final int[] ld : logicDestinationRuneList) {
12216 if (ld[3] == s.w) {
12217 int rx = s.x - ld[0];
12218 int ry = s.y - ld[1];
12219 int rz = s.z - ld[2];
12220
12221 if ((rx * rx + ry * ry + rz * rz) < ((rd + 0.5) * (rd + 0.5))) {
12222 // rmm.DBG("found a TP in range ["+rmm.Chat.YELLOW+ld[0]+","+ld[1]+","+ld[2]+rmm.Chat.GREEN+"] <"+ld[3]+">",pl);
12223 ld[0] = t.x - rx;
12224 ld[1] = t.y - ry;
12225 ld[2] = t.z - rz;
12226 ld[3] = t.w;
12227 // m.wpl.set(i,tp);
12228 }
12229 }
12230 }
12231
12232 }
12233
12234 public void mras(rcm s, rcm t, int rd) {
12235 // DBG("==Reality Anchor Size: "+realityAnchorList.size()+"==");
12236 for (final int[] ld : realityAnchorList) {
12237 if (ld[5] == s.w) {
12238 int rx = s.x - ld[2];
12239 int ry = s.y - ld[3];
12240 int rz = s.z - ld[4];
12241
12242 if ((rx * rx + ry * ry + rz * rz) < ((rd + 0.5) * (rd + 0.5))) {
12243 // DBG("found a RAS in range ["+rmm.Chat.YELLOW+ld[2]+","+ld[3]+","+ld[4]+rmm.Chat.GREEN+"] <"+ld[5]+">");
12244 ld[2] = t.x - rx;
12245 ld[3] = t.y - ry;
12246 ld[4] = t.z - rz;
12247 ld[5] = t.w;
12248 // m.wpl.set(i,tp);
12249 }
12250 }
12251 }
12252 }
12253
12254 public boolean fout(int fiid, int g, int gd, int rw) {
12255 int[] fi = faithRuneList.get(fiid);
12256
12257 int x = fi[0];
12258 int y = fi[1];
12259 int z = fi[2];
12260 int rd = fi[3];
12261 // DBG("["+Chat.YELLOW+x+","+y+","+z+Chat.GREEN+"]");
12262
12263 RuneWorld w = getWorldById(rw);
12264 Map<String, Object[]> ca = createMap();
12265 Map<int[], int[]> opr = createMap();
12266 Map<int[], int[]> ocr = createMap();
12267
12268 int[][][] hbaa = new int[(rd + 1) * 2][(rd + 1) * 2][(rd + 1) * 2];
12269 int[][][] lbaa = new int[(rd + 1) * 2][(rd + 1) * 2][(rd + 1) * 2];
12270 for (int lx = -rd; lx <= rd; lx++)
12271 for (int lz = -rd; lz <= rd; lz++)
12272 for (int ly = -rd; ly <= rd; ly++) {
12273 if ((lx * lx) + (ly * ly) + (lz * lz) < (rd + 0.5)
12274 * (rd + 0.5)) {
12275 int rx = lx;
12276 int ry = ly;
12277 int rz = lz;
12278
12279 rcm re = new rcm(x + lx, y + ly, z + lz, rw);
12280
12281 synchronized (positionRune) {
12282 rcm npr = positionRune.get(re);
12283 if (npr != null) {
12284 npr.x = rx;
12285 npr.y = ry;
12286 npr.z = rz;
12287 opr.put(re.toArray(), npr.toArray());
12288 positionRune.remove(npr);
12289 }
12290 }
12291 synchronized (hexRune) {
12292 rcm ncr = hexRune.get(re);
12293 if (ncr != null) {
12294 ncr.x = rx;
12295 ncr.y = ry;
12296 ncr.z = rz;
12297 ocr.put(re.toArray(), ncr.toArray());
12298 hexRune.remove(ncr);
12299 }
12300 }
12301
12302 int b = w.a(x + lx, y + ly, z + lz);
12303
12304 if (lb(b)) {
12305 b <<= 16;
12306 b |= w.b(lx + x, ly + y, lz + z);
12307 lbaa[lx + rd][ly + rd][lz + rd] = b;
12308 // w.e(lx+x,ly+y,lz+z,0);
12309 // m.DBG("Latch block ["+b+"]stored at ["+x+","+y+","+z+"]",pl);
12310 }
12311
12312 else if (boxes.contains((b))) {
12313
12314 try {
12315
12316 Object[] items = w.mgc(lx + x, ly + y, lz + z); // get
12317 // the
12318 // from
12319 // world
12320 // contents
12321 Object[] blank = new Object[items.length];
12322 w.msc(lx + x, ly + y, lz + z, blank);
12323 String xyz = x + "," + y + "," + z;
12324 ca.put(xyz, items); // store chest
12325 // m.DBG("saving key = "+Chat.YELLOW+xyz.toString()+Chat.GREEN+"]",pl);
12326 b <<= 16;
12327 b |= w.b(lx + x, ly + y, lz + z);
12328 hbaa[lx + rd][ly + rd][lz + rd] = b;
12329 } catch (Exception e) {
12330 log.log(Level.WARNING,
12331 "[Runecraft] Exception while storing a Chest",
12332 e);
12333 break;
12334 }
12335 }
12336
12337 else {
12338 if (b != 0) {
12339 b <<= 16;
12340 b |= w.b(lx + x, ly + y, lz + z);
12341 hbaa[lx + rd][ly + rd][lz + rd] = b;
12342 }
12343 }
12344 }
12345 }
12346 // DBG("escaped the l00ping");
12347 List<List<int[]>> omdat = createLList();
12348
12349 { // export waypoints
12350 final List<int[]> owpl = createLList(); // save internalised
12351 // waypoints
12352 final Iterator<int[]> iter = waypointRuneList.iterator();
12353 while (iter.hasNext()) {
12354 int[] ta = iter.next();
12355 if (ta[5] == rw) {
12356 int rx = ta[2] - x;
12357 int ry = ta[3] - y;
12358 int rz = ta[4] - z;
12359 if ((rx * rx + ry * ry + rz * rz) < ((rd + 0.5) * (rd + 0.5))) {
12360 iter.remove();
12361 ta[2] = rx;
12362 ta[3] = ry;
12363 ta[4] = rz;
12364 owpl.add(ta);
12365 }
12366 }
12367 }
12368 omdat.add(owpl);
12369 }
12370
12371 {
12372 final List<int[]> otpl = createLList(); // teleporter list
12373 final Iterator<int[]> iter = teleportRuneList.iterator();
12374 while (iter.hasNext()) {
12375 final int[] tp = iter.next();
12376 if (tp[3] == rw) {
12377 int rx = tp[0] - x;
12378 int ry = tp[1] - y;
12379 int rz = tp[2] - z;
12380 if ((rx * rx + ry * ry + rz * rz) < ((rd + 0.5) * (rd + 0.5))) {
12381 tp[0] = rx;
12382 tp[1] = ry;
12383 tp[2] = rz;
12384 otpl.add(tp);
12385 iter.remove();
12386 }
12387 }
12388 }
12389 omdat.add(otpl);
12390 }
12391
12392 {
12393 final List<int[]> orpl = createLList(); // rune pad list
12394 final Iterator<int[]> iter = runePadList.iterator();
12395 while (iter.hasNext()) {
12396 final int[] rp = iter.next();
12397 if (rp[4] == rw) {
12398 int rx = rp[1] - x;
12399 int ry = rp[2] - y;
12400 int rz = rp[3] - z;
12401 if ((rx * rx + ry * ry + rz * rz) < ((rd + 0.5) * (rd + 0.5))) {
12402 rp[1] = rx;
12403 rp[2] = ry;
12404 rp[3] = rz;
12405 orpl.add(rp);
12406 iter.remove();
12407 }
12408 }
12409 }
12410 omdat.add(orpl);
12411 }
12412
12413 {
12414 final List<int[]> oldl = createLList(); // logic destination list
12415 final Iterator<int[]> iter = logicDestinationRuneList.iterator();
12416 while (iter.hasNext()) {
12417 final int[] ld = iter.next();
12418 if (ld[3] == rw) {
12419 int rx = ld[0] - x;
12420 int ry = ld[1] - y;
12421 int rz = ld[2] - z;
12422 if ((rx * rx + ry * ry + rz * rz) < ((rd + 0.5) * (rd + 0.5))) {
12423 DBG("Found an LD [" + rx + "," + ry + "," + rz + ","
12424 + ld[3] + "] " + ld[4] + "," + ld[5]);
12425 ld[0] = rx;
12426 ld[1] = ry;
12427 ld[2] = rz;
12428 oldl.add(ld);
12429 iter.remove();
12430 }
12431 }
12432 }
12433 omdat.add(oldl);
12434 }
12435
12436 faithRuneList.remove(fi);
12437 try {
12438 File Faith_out = new File(main_world.getWorldFolder(), g + "-" + gd
12439 + ".faith");
12440
12441 FileOutputStream fos = new FileOutputStream(Faith_out);
12442 ObjectOutputStream oos = new ObjectOutputStream(fos);
12443 oos.writeObject(1);
12444 oos.writeObject(fi);
12445 oos.writeObject(hbaa);
12446 oos.writeObject(lbaa);
12447 // oos.writeObject(ca);
12448 oos.writeObject(opr);
12449 oos.writeObject(ocr);
12450 oos.writeObject(omdat);
12451
12452 oos.close();
12453 fos.close();
12454
12455 } catch (IOException i) {
12456 i.printStackTrace();
12457 return false;
12458 }
12459 for (int ly = rd; ly >= -rd; ly--)
12460 for (int lx = -rd; lx <= rd; lx++)
12461 for (int lz = -rd; lz <= rd; lz++) {
12462 if ((lx * lx + ly * ly + lz * lz) < ((rd + 0.5) * (rd + 0.5)))
12463 w.e(x + lx, y + ly, z + lz, 0);
12464 }
12465 return true;
12466 }
12467
12468 public boolean fin(int g, int gd, rcm r, RunePlayer pl) {
12469 File Faith_in = new File(main_world.getWorldFolder(), g + "-" + gd
12470 + ".faith");
12471 try {
12472 FileInputStream fis = new FileInputStream(Faith_in);
12473 ObjectInputStream ois = new ObjectInputStream(fis);
12474 int vr = ((Number) ois.readObject()).intValue();
12475 int fi[] = (int[]) ois.readObject();
12476 fi[0] = r.x;
12477 fi[1] = r.y + fi[3] + 1;
12478 fi[2] = r.z;
12479 fi[4] = r.w;
12480 RuneWorld w = getWorldById(r.w);
12481
12482 int rd = fi[3];
12483 int[][][] hbaa = new int[(rd + 1) * 2][(rd + 1) * 2][(rd + 1) * 2];
12484 int[][][] lbaa = new int[(rd + 1) * 2][(rd + 1) * 2][(rd + 1) * 2];
12485 hbaa = (int[][][]) ois.readObject();
12486 lbaa = (int[][][]) ois.readObject();
12487
12488 Map<String, Object[]> ca = (Map<String, Object[]>) ois.readObject();
12489 Map<int[], int[]> opr = (Map<int[], int[]>) ois.readObject();
12490 Map<int[], int[]> ocr = (Map<int[], int[]>) ois.readObject();
12491 List<List<int[]>> omdat = (List<List<int[]>>) ois.readObject();
12492
12493 ois.close();
12494 fis.close();
12495 for (int lx = -rd; lx <= rd; lx++)
12496 for (int lz = -rd; lz <= rd; lz++)
12497 for (int ly = -rd; ly <= rd; ly++) {
12498 if ((lx * lx + ly * ly + lz * lz) < ((rd + 0.5) * (rd + 0.5))) {
12499 if (w.a(fi[0] + lx, fi[1] + ly, fi[2] + lz) != 0) {
12500 pl.ab(EnChat.RED + "There are things in the way!");
12501 DBG("Obstacle "
12502 + w.a(fi[0] + lx, fi[1] + ly, fi[2]
12503 + lz) + " is at ["
12504 + EnChat.YELLOW + (fi[0] + lx) + ","
12505 + (fi[1] + ly) + "," + (fi[2] + lz)
12506 + EnChat.GREEN + "]", pl);
12507 return false;
12508 }
12509 }
12510 }
12511 for (int lx = -rd; lx <= rd; lx++)
12512 for (int lz = -rd; lz <= rd; lz++)
12513 for (int ly = -rd; ly <= rd; ly++) {
12514
12515 // first! deploy the hard blocks
12516 {
12517 int fb = hbaa[lx + rd][ly + rd][lz + rd] >> 16;
12518 int fd = hbaa[lx + rd][ly + rd][lz + rd] & 15;
12519 if (fb != 0)
12520 w.e(fi[0] + lx, fi[1] + ly, fi[2] + lz, fb, fd);
12521 }
12522
12523 }
12524
12525 for (int[] pri : opr.values()) {
12526 synchronized (positionRune) {
12527 rcm e = new rcm(pri);
12528 DBG("put a pr in [" + EnChat.YELLOW + e.x + "," + e.y + ","
12529 + e.z + EnChat.GREEN + "]");
12530 e.x = e.x + fi[0];
12531 e.y = e.y + fi[1];
12532 e.z = e.z + fi[2];
12533 e.w = r.w;
12534 rcm key = new rcm(e.x, e.y, e.z, e.w);
12535 DBG("Absolute position is [" + EnChat.YELLOW + e.x + ","
12536 + e.y + "," + e.z + EnChat.GREEN + "]");
12537 positionRune.put(key, e);
12538 }
12539 }
12540 for (int[] cri : ocr.values()) {
12541 synchronized (hexRune) {
12542 rcm e = new rcm(cri);
12543 e.x += fi[0];
12544 e.y += fi[1];
12545 e.z += fi[2];
12546 rcm key = new rcm(e.x, e.y, e.z, e.w);
12547 hexRune.put(key, e);
12548 DBG("put a cr in [" + EnChat.YELLOW + e.x + "," + e.y + ","
12549 + e.z + EnChat.GREEN + "]");
12550 }
12551 }
12552
12553 for (int lx = -rd; lx <= rd; lx++)
12554 for (int lz = -rd; lz <= rd; lz++)
12555 for (int ly = -rd; ly <= rd; ly++) {
12556
12557 // second, deploy the softblocks and PRs CRs
12558 {
12559 int fb = lbaa[lx + rd][ly + rd][lz + rd] >> 16;
12560 int fd = lbaa[lx + rd][ly + rd][lz + rd] & 15;
12561 if (fb != 0)
12562 w.e(fi[0] + lx, fi[1] + ly, fi[2] + lz, fb, fd);
12563 }
12564
12565 //
12566 }
12567 faithRuneList.add(fi); // faith is now saved
12568
12569 for (int[] wp : omdat.get(0)) // waypoints
12570 {
12571 // DBG("Waypoint found, relative ["+Chat.YELLOW+wp[2]+","+wp[3]+","+wp[4]+","+wp[5]+Chat.GREEN+"] "+wp[0]+","+wp[1]);
12572 // DBG("Faith centre is ["+Chat.YELLOW+fi[0]+","+fi[1]+","+fi[2]+","+fi[4]+Chat.GREEN+"]");
12573 wp[2] += fi[0];
12574 wp[3] += fi[1];
12575 wp[4] += fi[2];
12576 wp[5] = w.getWorldId();
12577 DBG(EnChat.RED + "Waypoint set, absolute [" + EnChat.YELLOW + wp[2]
12578 + "," + wp[3] + "," + wp[4] + "," + wp[5] + EnChat.GREEN
12579 + "] " + wp[0] + "," + wp[1]);
12580
12581 if (gacwp_getWaypointCoordinatesBySignature(wp[0], wp[1]) == null)// prevents
12582 // multiple
12583 // waypoints
12584 // with
12585 // the
12586 // same
12587 // sig
12588 {
12589 waypointRuneList.add(wp);
12590
12591 } else {
12592 DBG("Waypoint discarded");
12593 }
12594
12595 }
12596
12597 for (int[] tp : omdat.get(1)) {
12598 // DBG("Found a TP ["+tp[0]+","+tp[1]+","+tp[2]+","+tp[3]+"] "+tp[4]+","+tp[5]);
12599 tp[0] += fi[0];
12600 tp[1] += fi[1];
12601 tp[2] += fi[2];
12602 tp[3] = w.getWorldId();
12603 teleportRuneList.add(tp); // no need to check for collisions :D
12604 }
12605 for (int[] rp : omdat.get(2)) {
12606 rp[1] += fi[0];
12607 rp[2] += fi[1];
12608 rp[3] += fi[2];
12609 rp[4] = w.getWorldId();
12610 runePadList.add(rp);
12611 }
12612 for (int[] ld : omdat.get(3)) {
12613 DBG("Found an LD [" + ld[0] + "," + ld[1] + "," + ld[2] + ","
12614 + ld[3] + "] " + ld[4] + "," + ld[5]);
12615 ld[0] += fi[0];
12616 ld[1] += fi[1];
12617 ld[2] += fi[2];
12618 ld[3] = w.getWorldId();
12619 DBG("Found an ABSOLUTE [" + ld[0] + "," + ld[1] + "," + ld[2]
12620 + "," + ld[3] + "] " + ld[4] + "," + ld[5]);
12621 logicDestinationRuneList.add(ld);
12622 }
12623
12624 // deploy magic (remember faith)
12625 File Faithed = new File(main_world.getWorldFolder(), g + "-" + gd
12626 + ".faithed");
12627 if (Faithed.exists())
12628 Faithed.delete();
12629 Faith_in.renameTo(Faithed); // erases the faith file from access,
12630 // but keeps it
12631
12632 }
12633
12634 catch (IOException i) {
12635 i.printStackTrace();
12636 return false;
12637 } catch (ClassNotFoundException e) {
12638
12639 e.printStackTrace();
12640 return false;
12641 }
12642 /*
12643 * ois.readObject(fi); ois.readObject(hbaa); ois.readObject(lbaa);
12644 * ois.readObject(ca); ois.readObject(opr); ois.readObject(ocr);
12645 * ois.readObject(omdat);
12646 */
12647 return true;
12648 }
12649
12650 /**
12651 *
12652 * @param input
12653 * from a player chat, or /me event, or other.
12654 * @return any babeled text
12655 */
12656 String processtext(String input, RunePlayer pl) {
12657
12658 List<int[]> en = sl.get(pl.aw_getName());
12659 if (en == null)
12660 en = createAList();
12661 int[] ench = null;
12662
12663 for (int[] ta : en) {
12664 if (ta != null && ta[1] == -3 && ta[2] == 0) // hand speak enchants
12665 // only
12666 {
12667 ench = ta;
12668 // instance.DBG("Found a TP = -3, hand enchant");
12669 }
12670 }
12671
12672 if (ench != null)
12673 switch (ench[0]) {
12674
12675 case 157: // BABELCURSE:
12676 {
12677 // rmm.self.DBG("babel curse detected");
12678 int chance = (int) (Math.random() * 100);
12679 if (ench[4] < 0) {
12680 Runecraft_MAIN.self.r_removeEnchantmentFromToolType(TP_SPEAK, 0, pl,
12681 157);
12682 pl.ab(EnChat.YELLOW + "You feel the babel curse expire");
12683 DBG("babel curse removed");
12684 }
12685 if (chance < ench[3]) {
12686 // rmm.self.DBG("babel curse procced. Chance = "+chance+
12687 // " and threshold = "+ ench[3]);
12688 ench[4]--;
12689
12690 DBG("Babelfish says: " + EnChat.WHITE + input, pl);
12691 return ("" + EnChat.PURPLE + EnChat.SCRAMBLED + input + EnChat.WHITE);
12692 }
12693 }
12694 }
12695 return input;
12696 }
12697
12698 static String wooltohex(int i) {
12699 String hex = "" + i;
12700 switch (i) {
12701 case 15:
12702 return "0";
12703 case 11:
12704 return "1";
12705 case 13:
12706 return "2";
12707 case 9:
12708 return "3";
12709 case 12:
12710 return "b";
12711 case 14:
12712 return "4";
12713 case 10:
12714 return "5";
12715 case 1:
12716 return "6";
12717 case 8:
12718 return "7";
12719 case 7:
12720 return "8";
12721 case 3:
12722 return "9";
12723 case 5:
12724 return "a";
12725 case 6:
12726 return "c";
12727 case 2:
12728 return "d";
12729 case 4:
12730 return "e";
12731 case 0:
12732 return "f";
12733 }
12734 return hex;
12735 }
12736
12737 /**
12738 * Permission check for inter-world travel using multiworld groups and
12739 * multiworld ink.
12740 *
12741 * @param source
12742 * - the world ID of the source world
12743 * @param dest
12744 * - the world ID of the target world
12745 * @param inkblock
12746 * - the block ID of the tier being used. 0 if no tier involved.
12747 * @param runeName
12748 * - the name of the rune of exception checking
12749 * @return true when such a movement is allowed.
12750 */
12751 boolean wgc(int source, int dest, int inkblock, String runeName) {
12752 // Allow intra-world travel
12753 if (source == dest) {
12754 return true;
12755 }
12756
12757 // Allow when multi-world ink used
12758 if (wgo.contains(inkblock)) {
12759 return true;
12760 }
12761
12762 // Allow some runes to always cross
12763 if (rlc("multigrouprune " + runeName)) {
12764 return true;
12765 }
12766
12767 // Check if either world is in a group and if both are in the same
12768 // Note that one world might exist in multiple world groups (for example
12769 // a hub world)
12770 boolean eitherInGroup = false;
12771 synchronized (wgl) {
12772 for (final List<Integer> aWorldGroup : wgl) {
12773 final boolean sourceInGroup = aWorldGroup.contains(source);
12774 final boolean destInGroup = aWorldGroup.contains(dest);
12775
12776 if (sourceInGroup && destInGroup)
12777 return true;
12778
12779 eitherInGroup |= sourceInGroup || destInGroup;
12780 }
12781 }
12782
12783 // Allow travel between ungrouped worlds
12784 return !eitherInGroup;
12785 }
12786
12787 boolean wdc(long x, long y, long z, WardType cu) {
12788 rcm r = new rcm((int) x, (int) y, (int) z);
12789 return wdc(r, cu);
12790
12791 }
12792
12793 enum WardType {
12794 Aether(1), Void(2), Tool(3), Teleport(4), Dangerous(5), Target(6), Flight(
12795 7);
12796
12797 final int code;
12798
12799 private WardType(int i) {
12800 code = i;
12801 }
12802 }
12803
12804 boolean wdc(RunePlayer pl, WardType cu) // invoked for most ward types:
12805 // handles messages
12806 {
12807 // DBG("Entered int based ward check "+ cu);
12808 boolean rv = wdc(new rcm((int) pl.x(), (int) pl.y(), (int) pl.z(), pl
12809 .getWorld().getWorldId()), cu);
12810
12811 if (rv) {
12812 final String msg;
12813
12814 switch (cu) {
12815 case Aether:
12816 msg = EnChat.RED + "The aether is suppressed here by a ward.";
12817 break;
12818 case Void:
12819 msg = EnChat.PINK + "The void is suppressed here by a ward.";
12820 break;
12821 case Tool:
12822 msg = EnChat.RED
12823 + "The enchantment on this tool is suppressed by a ward.";
12824 break;
12825 case Teleport:
12826 msg = EnChat.RED
12827 + "Teleporting in this area is made impossible by a ward.";
12828 break;
12829 case Dangerous:
12830 msg = EnChat.RED
12831 + "A ward prevents this dangerous rune from being used.";
12832 break;
12833 case Target:
12834 msg = EnChat.RED
12835 + "The aether cannot find your target because of a ward.";
12836 break;
12837 case Flight:
12838 msg = EnChat.RED + "Gravity is stronger here because of a ward.";
12839 break;
12840 default:
12841 msg = EnChat.RED + "An unknown ward has prevented your action";
12842 break;
12843 }
12844
12845 pl.ab(msg);
12846 }
12847
12848 return rv;
12849 }
12850
12851 boolean wdc(rcm r, WardType cu) // the actual ward checker, no messages
12852 {
12853 synchronized (wardRuneList) {
12854 final Iterator<int[]> iter = wardRuneList.iterator();
12855 while (iter.hasNext()) {
12856 final int[] ia = iter.next();
12857 // 0 1 2 3 4 5 6
12858 // ward list [x,y,z,w,radius,state,type]
12859
12860 // Remove invalid wards
12861 if (ia.length != 7) {
12862 DBG("Invalid entry in ward list");
12863 iter.remove();
12864 continue;
12865 }
12866
12867 if (ia[5] == 0)
12868 continue; // skip disabled wards
12869 if (ia[3] != r.w)
12870 continue; // skip wards on different worlds
12871 if (ia[6] != cu.code)
12872 continue; // skip wards that aren't what we're looking for
12873
12874 // skip distant wards
12875 final int rx = ia[0] - r.x;
12876 final int ry = ia[1] - r.y;
12877 final int rz = ia[2] - r.z;
12878 if (!radiuscheck(rx, ry, rz, ia[4]))
12879 continue;
12880
12881 // Remove wards without a corresponding ward rune
12882 final rcm rb = getpr(ia[0], ia[1], ia[2], ia[3]);
12883 if (rb == null) {
12884 iter.remove();
12885 DBG("Ward field without RCM! Dispel witchery. tidied.");
12886 continue;
12887 }
12888
12889 DBG("Ward type " + ia[6] + " blocked action [" + EnChat.YELLOW
12890 + ia[0] + "," + ia[1] + "," + ia[2] + "," + ia[3] + "]");
12891 return true;
12892 }
12893 }
12894 return false;
12895 }
12896
12897 /**
12898 * Permission check for signature assignments (when enabled)
12899 *
12900 * @param pl
12901 * Player allocating the signature
12902 * @param g
12903 * Encoded signature being allocated.
12904 * @return true when signature assignment is allowed
12905 */
12906 boolean wsigc(final RunePlayer pl, int g) {
12907 if (!rlc("signature assignments")) {
12908 return true;
12909 }
12910
12911 final String sig1 = "" + (g & 255);
12912 g >>= 8; // IMPURRTANT NOTE: WEST
12913 final String sig2 = "" + (g & 255);
12914 g >>= 8; // SOUTH
12915 final String sig3 = "" + (g & 255);
12916 g >>= 8; // EAST
12917 final String sig4 = "" + (g & 255); // NORTH
12918
12919 // DBG(Integer.toString(g,
12920 // 2)+Chat.YELLOW+","+Chat.GREEN+Integer.toString(sig1,
12921 // 2)+Chat.YELLOW+","+Chat.GREEN+Integer.toString(gs, 2));
12922
12923 for (final String[] wsigc : wpassgnl) {
12924 if (wsigc.length == 4) {
12925 // this is a default allocation
12926 // [0] north [1] east [2] south [3] west
12927 // s4 north s3 east s2 south s1 west
12928
12929 if ((wsigc[0].equals("*") || wsigc[0].equals(sig4))
12930 && (wsigc[1].equals("*") || wsigc[1].equals(sig3))
12931 && (wsigc[2].equals("*") || wsigc[2].equals(sig2))
12932 && (wsigc[3].startsWith("*") || wsigc[3]
12933 .startsWith(sig1))) {
12934 return true;
12935 }
12936 } else if (wsigc.length == 5) {
12937 // [1] north [2] east [3] south [4] west
12938 // s4 north s3 east s2 south s1 west
12939 if (wsigc[0].equalsIgnoreCase((pl.aw_getName()))
12940 && (wsigc[1].equals("*") || wsigc[1].equals(sig4))
12941 && (wsigc[2].equals("*") || wsigc[2].equals(sig3))
12942 && (wsigc[3].equals("*") || wsigc[3].equals(sig2))
12943 && (wsigc[4].startsWith("*") || wsigc[4]
12944 .startsWith(sig1))) {
12945 return true;
12946 }
12947 }
12948 }
12949 // DBG(allow+":"+pl.aw().toLowerCase()+","+sig1+","+sig2+","+sig3+","+sig4+"<<"+Integer.toString(gs,2));
12950 return false;
12951 }
12952
12953 /**
12954 * Return a string describing the blockface.
12955 */
12956 public static String dirs(int dir) {
12957 return dirs(dir, false);
12958 }
12959
12960 /**
12961 * Return a string returning the blockface or player face.
12962 *
12963 * @param dir
12964 * number representing block face
12965 * @param playerface
12966 * true to get player face string (invert the direction)
12967 * @return string representation of face
12968 */
12969 public static String dirs(int dir, boolean playerface) {
12970 switch (dir) {
12971 // 0(down) 1(up) 2(east) 3(west) 4(north) 5(south)
12972 // y-1 y+1 x+1 x-1 z-1 z+1
12973 // player dir , block face
12974 case 0:
12975 return playerface ? "upward" : "downward";
12976 case 1:
12977 return playerface ? "downward" : "upward";
12978 case 4:
12979 return playerface ? "south" : "north";
12980 case 5:
12981 return playerface ? "north" : "south";
12982 case 3:
12983 return playerface ? "east" : "west";
12984 case 2:
12985 return playerface ? "west" : "east";
12986 default:
12987 return "in an unknown direction";
12988 }
12989 }
12990
12991 /**
12992 * Helper function for chkfaithpoint for checking a single section.
12993 *
12994 * Given a center point, a vector pointing from the center to the section,
12995 * and a vector pointing in the search direction. The vectors should be
12996 * perpendicular and have a magnitude of 1.
12997 *
12998 * @param w
12999 * World the section is in
13000 * @param x
13001 * rune's center x coordinate
13002 * @param y
13003 * rune's center y coordinate
13004 * @param z
13005 * rune's center z coordinate
13006 * @param dx1
13007 * x component of section vector
13008 * @param dy1
13009 * y component of section vector
13010 * @param dz1
13011 * z component of section vector
13012 * @param dx2
13013 * x component of search vector
13014 * @param dy2
13015 * y component of search vector
13016 * @param dz2
13017 * z component of search vector
13018 * @return
13019 */
13020 private boolean chkFaithSection(final RuneWorld w, final int x,
13021 final int y, final int z, final int dx1, final int dy1,
13022 final int dz1, final int dx2, final int dy2, final int dz2) {
13023
13024 final int block = w.a(x + dx1, y + dy1, z + dz1);
13025 final int metadata = w.b(x + dx1, y + dy1, z + dz1);
13026 final boolean onlyCheckTier = gt_getTierByMetaValue(block, metadata) == 0;
13027
13028 for (int i = -1; i <= 1; i++) {
13029 final int xi = x + 2 * dx1 + i * dx2;
13030 final int yi = y + 2 * dy1 + i * dy2;
13031 final int zi = z + 2 * dz1 + i * dz2;
13032
13033 final int block1 = w.a(xi, yi, zi);
13034 final int metadata1 = w.b(xi, yi, zi);
13035
13036 if (onlyCheckTier) {
13037 if (gt_getTierByMetaValue(block1, metadata1) != 0) {
13038 return false;
13039 }
13040 } else {
13041 if (block != block1 || metadata != metadata1) {
13042 return false;
13043 }
13044 }
13045 }
13046 return true;
13047 }
13048
13049 /**
13050 * Check that a faith point rune has a correctly constructed signature
13051 *
13052 * @param r
13053 * The rune to check
13054 * @return true if the rune is correct
13055 */
13056 boolean chkfaithpoint(rcm r) {
13057 RuneWorld w = getWorldById(r.w);
13058 switch (r.runePattern) {
13059 case FAITHPOINT:
13060 return chkFaithSection(w, r.x, r.y, r.z, 1, 0, 0, 0, 0, 1)
13061 && chkFaithSection(w, r.x, r.y, r.z, -1, 0, 0, 0, 0, 1)
13062 && chkFaithSection(w, r.x, r.y, r.z, 0, 0, 1, 1, 0, 0)
13063 && chkFaithSection(w, r.x, r.y, r.z, 0, 0, -1, 1, 0, 0);
13064 case WALLFPOINT: // N/S wall faith point
13065 return chkFaithSection(w, r.x, r.y, r.z, 1, 0, 0, 0, 1, 0)
13066 && chkFaithSection(w, r.x, r.y, r.z, -1, 0, 0, 0, 1, 0)
13067 && chkFaithSection(w, r.x, r.y, r.z, 0, 1, 0, 1, 0, 0)
13068 && chkFaithSection(w, r.x, r.y, r.z, 0, -1, 0, 1, 0, 0);
13069 case WALLFPOINT + 1: // E/W wall faith point
13070 return chkFaithSection(w, r.x, r.y, r.z, 0, 1, 0, 0, 0, 1)
13071 && chkFaithSection(w, r.x, r.y, r.z, 0, -1, 0, 0, 0, 1)
13072 && chkFaithSection(w, r.x, r.y, r.z, 0, 0, 1, 0, 1, 0)
13073 && chkFaithSection(w, r.x, r.y, r.z, 0, 0, -1, 0, 1, 0);
13074
13075 default:
13076 DBG("chkfaithpoint called on non faithpoint rune: " + EnChat.YELLOW
13077 + r.runePattern);
13078 return true;
13079 }
13080 }
13081
13082 public RunePlayer getPlayerByName(String name) {
13083 for (final RuneWorld world : worlds.values()) {
13084 final RunePlayer player = world.getPlayerByDisplayName(name);
13085 if (player != null)
13086 return player;
13087 }
13088
13089 return null;
13090 }
13091
13092 public boolean radiuscheck(int lx, int ly, int lz, double rd) {
13093 long res = (lx * lx) + (ly * ly) + (lz * lz);
13094 double radius = rd * rd;
13095 // DBG("distance is "+Math.floor(Math.sqrt(res)) + " from radius "+rd);
13096 return res < radius && res >= 0;
13097 }
13098
13099 public boolean radiuscheck(int lx, int ly, int lz, int centx, int centy,
13100 int centz, double radius) {
13101 return radiuscheck(centx - lx, centy - ly, centz - lz, radius);
13102 }
13103
13104 public int addWhisperCurse(int x, int y, int z, int w, int tier) {
13105
13106 int freespot = whisperSourceList.size();
13107 for (int i = 0; i < whisperSourceList.size(); i++) {
13108 int[] ta = whisperSourceList.get(i);
13109 if (x == ta[0] && y == ta[1] && z == ta[2] && w == ta[3]) {
13110 freespot = i;
13111 return freespot;
13112 }
13113 }
13114 DBG("Adding whisper curse link to [" + x + "," + y + "," + z + "," + w
13115 + "]");
13116 int newcurse[] = { x, y, z, w, tier };
13117 whisperSourceList.add(newcurse);
13118
13119 return freespot;
13120
13121 }
13122
13123 public void engagePassives(RunePlayer pl) {
13124 logInfo("[DBG] engaging passives");
13125 DBG("engaging passives", pl);
13126 List<int[]> l = sl.get(pl.aw_getName());
13127 if (l == null) {
13128 l = new ArrayList<int[]>();
13129 sl.put(pl.aw_getName(), l);
13130 }
13131 for (int i = 0; i < l.size(); i++) {
13132 int[] ta = l.get(i);
13133 switch (ta[0]) {
13134 case LEVITATE: {
13135 // logInfo("[DBG] engaging levitate passive");
13136 DBG("engaging levitate passive" + ta[3]);
13137 RCT_main t = t(pl.getWorld(), 2, pl, (int) pl.x(), (int) pl.y(),
13138 (int) pl.z(), ta[3], // *10 for regular seconds
13139 0);
13140 t.scheduleSyncRepeating(3, 3);
13141 pl.addPassiveBuff(t);
13142 s_saveToMagicDat();
13143 break;
13144 }
13145 case ENDURANCE:
13146
13147 {
13148 String dbgstring = EnChat.RED + "engaging endurance "
13149 + EnChat.GREEN;
13150 for (i = 0; i < ta.length; i++) {
13151 dbgstring += "[" + EnChat.YELLOW + ta[i] + EnChat.GREEN + "], ";
13152 }
13153
13154 DBG(dbgstring);
13155 int[] args = { (int) pl.x(), (int) pl.y(), (int) pl.z(), ta[3],
13156 ta[4] };
13157
13158 RCT_main t = t(pl.getWorld(), -ta[0], args, pl, TP_PASSIVE);
13159 pl.addPassiveBuff(t);
13160 t.scheduleSyncRepeating(10, 10);
13161 break;
13162 }
13163 }
13164 }
13165
13166 }
13167
13168 public String[] getWhisperCurseText(int x, int y, int z, int w) {
13169 String[] rv = { "", "", "", "" };
13170 for (int i = 0; i < whisperSourceList.size(); i++) {
13171 int[] ta = whisperSourceList.get(i);
13172 if (ta[0] == x && ta[1] == y && ta[2] == z && ta[3] == w) {
13173 // DBG(Chat.YELLOW+"Found whisper curse link match, index "+i);
13174 // DBG(Chat.YELLOW+
13175 // "coords for link are "+ta[0]+","+ta[1]+","+ta[2]+","+ta[3]);
13176 // DBG(Chat.YELLOW+ "Searching for "+x+","+y+","+z+","+w);
13177 rv = getWhisperCurseText(i);
13178 break;
13179 }
13180
13181 // DBG(Chat.BLUE+"whisper curse ["+Chat.YELLOW+ta[0]+","+ta[1]+","+ta[2]+","+ta[3]+Chat.BLUE+"]");
13182
13183 }
13184 return rv;
13185 }
13186
13187 public String[] getWhisperCurseText(int index) {
13188 String[] rv = { "", "", "", "" };
13189 int ta[] = whisperSourceList.get(index);
13190 if (ta == null)
13191 return rv;
13192
13193 RuneWorld world = getWorldById(ta[3]);
13194 // check 4 wool blocks and get colour values
13195 DBG("Searching for whisper curse rune parts at " + ta[0] + "," + ta[1]
13196 + "," + ta[2] + "," + ta[3]);
13197 if (world.eAa(ta[0] + 2, ta[2]))
13198 world.eAd(ta[0] + 2, ta[2]);
13199 if (world.eAa(ta[0] - 2, ta[2]))
13200 world.eAd(ta[0] - 2, ta[2]);
13201 if (world.eAa(ta[0], ta[2] + 2))
13202 world.eAd(ta[0], ta[2] + 2);
13203 if (world.eAa(ta[0], ta[2] - 2))
13204 world.eAd(ta[0], ta[2] - 2);
13205
13206 if (world.a(ta[0], ta[1], ta[2]) != OBSIDIAN) {
13207 rv[0] = "";
13208 rv[1] = "";
13209 rv[2] = "";
13210 rv[3] = "";
13211 DBG("whps brk 0");
13212 return rv;
13213 }
13214
13215 if (world.a(ta[0], ta[1], ta[2] - 1) == WOOL) {
13216 rv[0] = "\u00A7" + wooltohex(world.b(ta[0], ta[1], ta[2] - 1));
13217 } else {
13218 rv[0] = "";
13219 rv[1] = "";
13220 rv[2] = "";
13221 rv[3] = "";
13222 DBG("whps brk 1");
13223 return rv;
13224 }
13225 String[] signtext = world.readSign(ta[0], ta[1], ta[2] - 2);
13226 for (String cct : signtext) {
13227 rv[0] += cct;
13228 }
13229
13230 if (world.a(ta[0] + 1, ta[1], ta[2]) == WOOL) {
13231 rv[1] = "\u00A7" + wooltohex(world.b(ta[0] + 1, ta[1], ta[2]));
13232 } else {
13233 rv[0] = "";
13234 rv[1] = "";
13235 rv[2] = "";
13236 rv[3] = "";
13237 DBG("whps brk 2");
13238 return rv;
13239 }
13240 signtext = world.readSign(ta[0] + 2, ta[1], ta[2]);
13241 for (String cct : signtext) {
13242 rv[1] += cct;
13243 }
13244
13245 if (world.a(ta[0], ta[1], ta[2] + 1) == WOOL) {
13246 rv[2] = "\u00A7" + wooltohex(world.b(ta[0], ta[1], ta[2] + 1));
13247 } else {
13248 rv[0] = "";
13249 rv[1] = "";
13250 rv[2] = "";
13251 rv[3] = "";
13252 DBG("whps brk 3");
13253 return rv;
13254 }
13255 signtext = world.readSign(ta[0], ta[1], ta[2] + 2);
13256 for (String cct : signtext) {
13257 rv[2] += cct;
13258 }
13259
13260 if (world.a(ta[0] - 1, ta[1], ta[2]) == WOOL) {
13261 rv[3] = "\u00A7" + wooltohex(world.b(ta[0] - 1, ta[1], ta[2]));
13262 } else {
13263 rv[0] = "";
13264 rv[1] = "";
13265 rv[2] = "";
13266 rv[3] = "";
13267 DBG("whps brk 4");
13268 return rv;
13269 }
13270 signtext = world.readSign(ta[0] - 2, ta[1], ta[2]);
13271 for (String cct : signtext) {
13272 rv[3] += cct;
13273 }
13274 // check 4 signs and get text values
13275 //
13276 return rv;
13277 }
13278
13279 public void mwcs(rcm s, rcm t, int rd) {
13280 for (int i = 0; i < whisperSourceList.size(); i++) {
13281 int[] ld = whisperSourceList.get(i);
13282 if (ld[3] == s.w) {
13283 int rx = s.x - ld[0];
13284 int ry = s.y - ld[1];
13285 int rz = s.z - ld[2];
13286
13287 if (radiuscheck(rx, ry, rz, rd + 0.5)) {
13288 // rmm.DBG("found a TP in range ["+rmm.Chat.YELLOW+ld[0]+","+ld[1]+","+ld[2]+rmm.Chat.GREEN+"] <"+ld[3]+">",pl);
13289 ld[0] = t.x - rx;
13290 ld[1] = t.y - ry;
13291 ld[2] = t.z - rz;
13292 ld[3] = t.w;
13293 // m.wpl.set(i,tp);
13294 }
13295 }
13296 }
13297 }
13298
13299 public boolean dropSmeltedBlock(RuneWorld w, int x, int y, int z) {
13300 int result = 0;
13301 short metaResult = 0;
13302 if (getpr(w.getWorldId(), x, y, z) != null)
13303 return false; // don't uncraft magic blocks
13304
13305 switch (w.a(x, y, z)) {
13306 case Runecraft_MAIN.STONE:
13307 case Runecraft_MAIN.COBBLESTONE:
13308 result = STONE;
13309 break;
13310 case Runecraft_MAIN.SAND:
13311 result = GLASS;
13312 break;
13313 case GRAVEL:
13314 result = FLINT;
13315 break;
13316 case GOLD_ORE:
13317 result = GOLD;
13318 break;
13319 case IRON_ORE:
13320 result = IRON;
13321 break;
13322 case Runecraft_MAIN.WOOD:
13323 result = COAL;
13324 metaResult = 1;// should be charcoal but we don't handle damage
13325 // values
13326 break;
13327 case Runecraft_MAIN.CACTUS:
13328 result = DYE;
13329 metaResult = 2; // 351
13330 case CLAY_BLOCK: // clay block -> brick
13331 result = BRICK_BLOCK;
13332 break;
13333 case JUKEBOX:
13334 result = 264 /* diamond */;
13335 break;
13336 case BEDROCK:
13337 return true;// don't do anything and tell the calling function to
13338 // not do anything either
13339 default:
13340 result = 0;
13341 }
13342 if (result != 0) {
13343 w.e(x, y, z, Runecraft_MAIN.AIR);
13344 s(w, x, y, z, result, metaResult);
13345 return true;
13346 }
13347
13348 return false;
13349 }
13350
13351 /**
13352 * Look up signature anchor by signature. Returns null if the anchor
13353 * signature cannot be found
13354 *
13355 * @param g
13356 * Block signature
13357 * @param gd
13358 * Metadata signature
13359 * @return Anchor array if signature is found, null otherwise
13360 */
13361 private int[] getAnchor(int g, int gd) {
13362
13363 int fi = 0;
13364 int[] wp = null;
13365
13366 // find waypoint with signature g/gd
13367 for (fi = 0; fi < realityAnchorList.size(); ++fi) {
13368 wp = realityAnchorList.get(fi);
13369 // DBG(Chat.RED+"["+g+","+gd+"]"+Chat.YELLOW+"["+wp[0]+","+wp[1]+"]");
13370 if (g == wp[0] && gd == wp[1])
13371 break;
13372 }
13373
13374 // logInfo("WP Sweep complete ["+fi+"],["+ffi+"]");
13375 if (fi == realityAnchorList.size()) { // signature not found
13376 // DBG("Signature not found");
13377 // logInfo("signature not found");
13378 return null;
13379 }
13380
13381 final RuneWorld w = getWorldById(wp[5]);
13382 if (w == null) {
13383 // DBG("World not in memory. erasing");
13384 logInfo("An anchor (" + wp[2] + "," + wp[3] + "," + wp[4]
13385 + ") is broken because its world (id " + wp[5]
13386 + ") is not loaded.");
13387 realityAnchorList.remove(fi); // world is not loaded; remove WP from
13388 // list
13389 s_saveToMagicDat();
13390 return null;
13391 }
13392
13393 // force chunk loading
13394 w.eAd(wp[2] - 4, wp[4] - 4);
13395 w.eAd(wp[2] + 4, wp[4] + 4);
13396 w.eAd(wp[2] + 4, wp[4] - 4);
13397 w.eAd(wp[2] - 4, wp[4] + 4);
13398
13399 if (getpr(wp[2], wp[3], wp[4], wp[5]) == null) {
13400 realityAnchorList.remove(fi); // world is not loaded; remove WP from
13401 // list
13402 s_saveToMagicDat();
13403 return null;
13404 // self destruct for dispelled RCMs
13405 }
13406
13407 return wp;
13408
13409 // check if waypoint / faithpoint is intact
13410 // logInfo("FP check: "+ rcn.a(wr[FAITHPOINT-1],w, wp[2], wp[3],
13411 // wp[4],7, 7));
13412 // logInfo("WP check: "+ rcn.a(wr[WAYPOINT-1],w, wp[2], wp[3], wp[4],7,
13413 // 7));
13414 /*
13415 * if ((rcn.a(wr_runeTemplateArray[WAYPOINT-1], w, wp[2], wp[3], wp[4],
13416 * 5, 5) == 0 ) && rcn.a(wr_runeTemplateArray[FAITHPOINT-1],w, wp[2],
13417 * wp[3], wp[4],7, 7) == 0 && rcn.a(wr_runeTemplateArray[WALLWPOINT-1],
13418 * w, wp[2], wp[3], wp[4], 5,1) == 0 &&
13419 * rcn.a(wr_runeTemplateArray[WALLWPOINT], w, wp[2], wp[3], wp[4], 1,5)
13420 * == 0 && rcn.a(wr_runeTemplateArray[WALLFPOINT-1], w, wp[2], wp[3],
13421 * wp[4], 7,1) == 0 && rcn.a(wr_runeTemplateArray[WALLFPOINT], w, wp[2],
13422 * wp[3], wp[4], 1,7) == 0) {
13423 *
13424 *
13425 * //ia, world, wpx,y,z, width&height
13426 * //logInfo("gacwp: target not intact"); DBG("Not intact removing");
13427 * realityAnchorList.remove(fi); // not intact: remove from list
13428 *
13429 * s_saveToMagicDat(); return null; }
13430 */
13431 }
13432
13433 private static <T> Set<T> mkSet(T... args) {
13434 final Set<T> set = new HashSet<T>(args.length);
13435 for (T t : args)
13436 set.add(t);
13437 return set;
13438 }
13439
13440 /**
13441 * Find the y value of the block which is just outside the sphere centered
13442 * at 0,0,0 with radius r
13443 *
13444 * @param x
13445 * x coordinate of column
13446 * @param z
13447 * z coordinate of column
13448 * @param r
13449 * radius of sphere centered at 0,0,0
13450 * @return y coordinate of block in x,z column which is above the sphere, -1
13451 * if x,z are outside the radius
13452 */
13453 private static int yAboveSphere(final int x, final int z, final int r) {
13454 final double a = (r + 0.5) * (r + 0.5) - x * x - z * z;
13455 if (a < 0)
13456 return -1;
13457 return (int) Math.ceil(Math.sqrt(a));
13458 }
13459 /**
13460 * Method for activating tasks/events that are world dependant, after the server has finished booting up.
13461 */
13462 public void postLoadLoad()
13463 {
13464
13465 for (RunePoint rp : waypointList)
13466
13467 {
13468 if (rp instanceof WP_TrueName)
13469 {
13470 ((WP_TrueName) rp).setupRCT();
13471 }
13472 }
13473 }
13474
13475 static public boolean isLog(int b) {
13476 return b == WOOD || b == WOOD2;
13477 }
13478 static public boolean isLeaves(int b) {
13479 return b == LEAVES || b == LEAVES2;
13480 }
13481}