001/* 002 * Trident - A Multithreaded Server Alternative 003 * Copyright 2014 The TridentSDK Team 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018package net.tridentsdk.server.entity.block; 019 020import net.tridentsdk.base.Block; 021import net.tridentsdk.base.Position; 022import net.tridentsdk.base.Substance; 023import net.tridentsdk.effect.sound.SoundEffectType; 024import net.tridentsdk.entity.block.PrimeTNT; 025import net.tridentsdk.entity.types.EntityType; 026import net.tridentsdk.event.entity.EntityExplodeEvent; 027import net.tridentsdk.server.data.RecordBuilder; 028import net.tridentsdk.server.event.EventProcessor; 029import net.tridentsdk.server.packets.play.out.PacketPlayOutExplosion; 030import net.tridentsdk.server.packets.play.out.PacketPlayOutSoundEffect; 031import net.tridentsdk.server.player.TridentPlayer; 032import net.tridentsdk.server.world.TridentChunk; 033import net.tridentsdk.util.Vector; 034 035import java.util.UUID; 036import java.util.concurrent.atomic.AtomicInteger; 037 038public class TridentPrimeTNT extends TridentFallingBlock implements PrimeTNT { 039 private volatile int fuse = 80; // 4 seconds by default 040 private volatile int radius = 4; // Sphere with 4 blocks radius 041 042 private volatile AtomicInteger countDown = new AtomicInteger(fuse); 043 044 public TridentPrimeTNT(UUID id, Position spawnLocation) { 045 super(id, spawnLocation); 046 } 047 048 @Override 049 protected void doTick() { 050 if (countDown.get() == 0) { 051 EntityExplodeEvent event = EventProcessor.fire(new EntityExplodeEvent(this, radius)); 052 if (event.isIgnored()) { 053 return; 054 } 055 056 Position p = position(); 057 int radius = this.radius; // Prevent the value from changing within operation 058 059 int minX = (int) (p.x() - radius); 060 int maxX = (int) (p.x() + radius); 061 int minY = (int) (p.y() - radius); 062 int maxY = (int) (p.y() + radius); 063 int minZ = (int) (p.z() - radius); 064 int maxZ = (int) (p.z() + radius); 065 066 RecordBuilder[] records = new RecordBuilder[(int) Math.pow(radius * 2, 3)]; 067 int recordIdx = 0; 068 069 for (int i = minX; i < maxX; i++) { 070 for (int j = minY; j < maxY; j++) { 071 for (int k = minZ; k < maxZ; k++) { 072 Block block = p.world().blockAt(new Position(p.world(), i, j, k)); 073 ((TridentChunk) p.world().chunkAt(i / 16, k / 16, false)) 074 .setAt(i, j, k, Substance.AIR, (byte) 0, (byte) 0, (byte) 0); 075 records[recordIdx] = new RecordBuilder() 076 .setX((byte) i) 077 .setY((byte) j) 078 .setZ((byte) k) 079 .setData(block.meta()) 080 .setBlockId(block.substance().id()); 081 recordIdx++; 082 } 083 } 084 } 085 086 PacketPlayOutExplosion explosion = new PacketPlayOutExplosion(); 087 explosion.set("loc", p) 088 .set("recordCount", records.length) 089 .set("records", records) 090 .set("velocity", new Vector(radius, radius, radius)); 091 092 PacketPlayOutSoundEffect sound = new PacketPlayOutSoundEffect(); 093 sound.set("sound", SoundEffectType.RANDOM_EXPLODE).set("loc", p).set("volume", 50).set("pitch", 20); 094 095 TridentPlayer.sendFiltered(explosion, player -> player.world().equals(world())); 096 TridentPlayer.sendFiltered(sound, player -> player.world().equals(world())); 097 } 098 099 countDown.decrementAndGet(); 100 } 101 102 @Override 103 public int fuse() { 104 return fuse; 105 } 106 107 @Override 108 public int radius() { 109 return radius; 110 } 111 112 @Override 113 public void setRadius(int radius) { 114 this.radius = radius; 115 } 116 117 @Override 118 public void setFuse(int ticks) { 119 this.fuse = ticks; 120 this.countDown.set(ticks); 121 } 122 123 @Override 124 public EntityType type() { 125 return EntityType.PRIMED_TNT; 126 } 127}