Fork of Poseidon providing Bukkit #1060 to older Beta versions (b1.0-b1.7.3)
1package org.bukkit.craftbukkit;
2
3import net.minecraft.server.Block;
4import net.minecraft.server.WorldServer;
5import org.bukkit.Bukkit;
6import org.bukkit.Location;
7import org.bukkit.TravelAgent;
8import org.bukkit.event.world.PortalCreateEvent;
9
10import java.util.Random;
11
12public class PortalTravelAgent implements TravelAgent {
13
14 private Random random = new Random();
15
16 private int searchRadius = 128;
17 private int creationRadius = 14; // 16 -> 14
18 private boolean canCreatePortal = true;
19
20 public PortalTravelAgent() {
21 }
22
23 public Location findOrCreate(Location location) {
24 WorldServer worldServer = ((CraftWorld) location.getWorld()).getHandle();
25 worldServer.chunkProviderServer.forceChunkLoad = true;
26 // Attempt to find a Portal.
27 Location resultLocation = this.findPortal(location);
28 // If a Portal cannot be found we will attempt to create one.
29 if (resultLocation == null) {
30 // Attempt to create a portal, return if it was successful or not.
31 if (this.canCreatePortal && this.createPortal(location)) {
32 // Now find that portals location.
33 resultLocation = this.findPortal(location);
34 } else {
35 // Fallback onto the original location.
36 resultLocation = location;
37 }
38 }
39 worldServer.chunkProviderServer.forceChunkLoad = false;
40 // Return our resulting portal location.
41 return resultLocation;
42 }
43
44 public Location findPortal(Location location) {
45 net.minecraft.server.World world = ((CraftWorld) location.getWorld()).getHandle();
46 // short short1 = 128;
47 double d0 = -1.0D;
48 int i = 0;
49 int j = 0;
50 int k = 0;
51 int l = location.getBlockX();
52 int i1 = location.getBlockZ();
53
54 double d1;
55
56 for (int j1 = l - this.searchRadius; j1 <= l + this.searchRadius; ++j1) {
57 double d2 = (double) j1 + 0.5D - location.getX();
58
59 for (int k1 = i1 - this.searchRadius; k1 <= i1 + this.searchRadius; ++k1) {
60 double d3 = (double) k1 + 0.5D - location.getZ();
61
62 for (int l1 = 127; l1 >= 0; --l1) {
63 if (world.getTypeId(j1, l1, k1) == Block.PORTAL.id) {
64 while (world.getTypeId(j1, l1 - 1, k1) == Block.PORTAL.id) {
65 --l1;
66 }
67
68 d1 = (double) l1 + 0.5D - location.getY();
69 double d4 = d2 * d2 + d1 * d1 + d3 * d3;
70
71 if (d0 < 0.0D || d4 < d0) {
72 d0 = d4;
73 i = j1;
74 j = l1;
75 k = k1;
76 }
77 }
78 }
79 }
80 }
81
82 if (d0 >= 0.0D) {
83 double d5 = (double) i + 0.5D;
84 double d6 = (double) j + 0.5D;
85
86 d1 = (double) k + 0.5D;
87 if (world.getTypeId(i - 1, j, k) == Block.PORTAL.id) {
88 d5 -= 0.5D;
89 }
90
91 if (world.getTypeId(i + 1, j, k) == Block.PORTAL.id) {
92 d5 += 0.5D;
93 }
94
95 if (world.getTypeId(i, j, k - 1) == Block.PORTAL.id) {
96 d1 -= 0.5D;
97 }
98
99 if (world.getTypeId(i, j, k + 1) == Block.PORTAL.id) {
100 d1 += 0.5D;
101 }
102
103 return new Location(location.getWorld(), d5, d6, d1, location.getYaw(), location.getPitch());
104 } else {
105 return null;
106 }
107 }
108
109 public boolean createPortal(Location location) {
110 net.minecraft.server.World world = ((CraftWorld) location.getWorld()).getHandle();
111 // byte b0 = 16;
112 double d0 = -1.0D;
113 int i = location.getBlockX();
114 int j = location.getBlockY();
115 int k = location.getBlockZ();
116 int l = i;
117 int i1 = j;
118 int j1 = k;
119 int k1 = 0;
120 int l1 = this.random.nextInt(4);
121
122 int i2;
123 double d1;
124 int j2;
125 double d2;
126 int k2;
127 int l2;
128 int i3;
129 int j3;
130 int k3;
131 int l3;
132 int i4;
133 int j4;
134 int k4;
135 double d3;
136 double d4;
137
138 for (i2 = i - this.creationRadius; i2 <= i + this.creationRadius; ++i2) {
139 d1 = (double) i2 + 0.5D - location.getX();
140
141 for (j2 = k - this.creationRadius; j2 <= k + this.creationRadius; ++j2) {
142 d2 = (double) j2 + 0.5D - location.getZ();
143
144 label271:
145 for (l2 = 127; l2 >= 0; --l2) {
146 if (world.isEmpty(i2, l2, j2)) {
147 while (l2 > 0 && world.isEmpty(i2, l2 - 1, j2)) {
148 --l2;
149 }
150
151 for (k2 = l1; k2 < l1 + 4; ++k2) {
152 j3 = k2 % 2;
153 i3 = 1 - j3;
154 if (k2 % 4 >= 2) {
155 j3 = -j3;
156 i3 = -i3;
157 }
158
159 for (l3 = 0; l3 < 3; ++l3) {
160 for (k3 = 0; k3 < 4; ++k3) {
161 for (j4 = -1; j4 < 5; ++j4) {
162 i4 = i2 + (k3 - 1) * j3 + l3 * i3;
163 k4 = l2 + j4;
164 int l4 = j2 + (k3 - 1) * i3 - l3 * j3;
165
166 if (j4 < 0 && !world.getMaterial(i4, k4, l4).isBuildable() || j4 >= 0 && !world.isEmpty(i4, k4, l4)) {
167 continue label271;
168 }
169 }
170 }
171 }
172
173 d3 = (double) l2 + 0.5D - location.getY();
174 d4 = d1 * d1 + d3 * d3 + d2 * d2;
175 if (d0 < 0.0D || d4 < d0) {
176 d0 = d4;
177 l = i2;
178 i1 = l2 + 1;
179 j1 = j2;
180 k1 = k2 % 4;
181 }
182 }
183 }
184 }
185 }
186 }
187
188 if (d0 < 0.0D) {
189 for (i2 = i - this.creationRadius; i2 <= i + this.creationRadius; ++i2) {
190 d1 = (double) i2 + 0.5D - location.getX();
191
192 for (j2 = k - this.creationRadius; j2 <= k + this.creationRadius; ++j2) {
193 d2 = (double) j2 + 0.5D - location.getZ();
194
195 label219:
196 for (l2 = 127; l2 >= 0; --l2) {
197 if (world.isEmpty(i2, l2, j2)) {
198 while (l2 > 0 && world.isEmpty(i2, l2 - 1, j2)) {
199 --l2;
200 }
201
202 for (k2 = l1; k2 < l1 + 2; ++k2) {
203 j3 = k2 % 2;
204 i3 = 1 - j3;
205
206 for (l3 = 0; l3 < 4; ++l3) {
207 for (k3 = -1; k3 < 5; ++k3) {
208 j4 = i2 + (l3 - 1) * j3;
209 i4 = l2 + k3;
210 k4 = j2 + (l3 - 1) * i3;
211 if (k3 < 0 && !world.getMaterial(j4, i4, k4).isBuildable() || k3 >= 0 && !world.isEmpty(j4, i4, k4)) {
212 continue label219;
213 }
214 }
215 }
216
217 d3 = (double) l2 + 0.5D - location.getY();
218 d4 = d1 * d1 + d3 * d3 + d2 * d2;
219 if (d0 < 0.0D || d4 < d0) {
220 d0 = d4;
221 l = i2;
222 i1 = l2 + 1;
223 j1 = j2;
224 k1 = k2 % 2;
225 }
226 }
227 }
228 }
229 }
230 }
231 }
232
233 int i5 = l;
234 int j5 = i1;
235
236 j2 = j1;
237 int k5 = k1 % 2;
238 int l5 = 1 - k5;
239
240 if (k1 % 4 >= 2) {
241 k5 = -k5;
242 l5 = -l5;
243 }
244
245 boolean flag;
246
247 // CraftBukkit start - portal create event
248 java.util.ArrayList<org.bukkit.block.Block> blocks = new java.util.ArrayList<org.bukkit.block.Block>();
249 // Find out what blocks the portal is going to modify, duplicated from below
250 CraftWorld craftWorld = ((WorldServer) world).getWorld();
251
252 if (d0 < 0.0D) {
253 if (i1 < 70) {
254 i1 = 70;
255 }
256
257 if (i1 > 118) {
258 i1 = 118;
259 }
260
261 j5 = i1;
262
263 for (l2 = -1; l2 <= 1; ++l2) {
264 for (k2 = 1; k2 < 3; ++k2) {
265 for (j3 = -1; j3 < 3; ++j3) {
266 i3 = i5 + (k2 - 1) * k5 + l2 * l5;
267 l3 = j5 + j3;
268 k3 = j2 + (k2 - 1) * l5 - l2 * k5;
269 org.bukkit.block.Block b = craftWorld.getBlockAt(i3, l3, k3);
270 if (!blocks.contains(b)) {
271 blocks.add(b);
272 }
273 }
274 }
275 }
276 }
277
278 for (l2 = 0; l2 < 4; ++l2) {
279 for (k2 = 0; k2 < 4; ++k2) {
280 for (j3 = -1; j3 < 4; ++j3) {
281 i3 = i5 + (k2 - 1) * k5;
282 l3 = j5 + j3;
283 k3 = j2 + (k2 - 1) * l5;
284 org.bukkit.block.Block b = craftWorld.getBlockAt(i3, l3, k3);
285 if (!blocks.contains(b)) {
286 blocks.add(b);
287 }
288 }
289 }
290 }
291
292 PortalCreateEvent event = new PortalCreateEvent(blocks, (org.bukkit.World) craftWorld);
293 Bukkit.getServer().getPluginManager().callEvent(event);
294 if (event.isCancelled()) {
295 return false;
296 }
297 // CraftBukkit end
298
299 if (d0 < 0.0D) {
300 if (i1 < 70) {
301 i1 = 70;
302 }
303
304 if (i1 > 118) {
305 i1 = 118;
306 }
307
308 j5 = i1;
309
310 for (l2 = -1; l2 <= 1; ++l2) {
311 for (k2 = 1; k2 < 3; ++k2) {
312 for (j3 = -1; j3 < 3; ++j3) {
313 i3 = i5 + (k2 - 1) * k5 + l2 * l5;
314 l3 = j5 + j3;
315 k3 = j2 + (k2 - 1) * l5 - l2 * k5;
316 flag = j3 < 0;
317 world.setTypeId(i3, l3, k3, flag ? Block.OBSIDIAN.id : 0);
318 }
319 }
320 }
321 }
322
323 for (l2 = 0; l2 < 4; ++l2) {
324 world.suppressPhysics = true;
325
326 for (k2 = 0; k2 < 4; ++k2) {
327 for (j3 = -1; j3 < 4; ++j3) {
328 i3 = i5 + (k2 - 1) * k5;
329 l3 = j5 + j3;
330 k3 = j2 + (k2 - 1) * l5;
331 flag = k2 == 0 || k2 == 3 || j3 == -1 || j3 == 3;
332 world.setTypeId(i3, l3, k3, flag ? Block.OBSIDIAN.id : Block.PORTAL.id);
333 }
334 }
335
336 world.suppressPhysics = false;
337
338 for (k2 = 0; k2 < 4; ++k2) {
339 for (j3 = -1; j3 < 4; ++j3) {
340 i3 = i5 + (k2 - 1) * k5;
341 l3 = j5 + j3;
342 k3 = j2 + (k2 - 1) * l5;
343 world.applyPhysics(i3, l3, k3, world.getTypeId(i3, l3, k3));
344 }
345 }
346 }
347
348 return true;
349 }
350
351
352 public TravelAgent setSearchRadius(int radius) {
353 this.searchRadius = radius;
354 return this;
355 }
356
357 public int getSearchRadius() {
358 return this.searchRadius;
359 }
360
361 public TravelAgent setCreationRadius(int radius) {
362 this.creationRadius = radius < 2 ? 0 : radius - 2;
363 return this;
364 }
365
366 public int getCreationRadius() {
367 return this.creationRadius;
368 }
369
370 public boolean getCanCreatePortal() {
371 return this.canCreatePortal;
372 }
373
374 public void setCanCreatePortal(boolean create) {
375 this.canCreatePortal = create;
376 }
377}