View difference between Paste ID: dAs2hk42 and fG9CgPmQ
SHOW: | | - or go back to the newest paste.
1
/** Represents a dragon mount */
2
public final class Dragon extends EntityEnderDragon {
3
	/** The player that's riding the dragon */
4
	final Player rider;
5
	/** The dragon's current location and orientation around the Z axis */ 
6
	final Location loc;
7
	/** The dragon's speed */
8
	private float speed = .7f;
9
	/** The dragon's health */
10
	private int health;
11
	/** The list of all the dragons */
12
	static final List<Dragon> dragons = new ArrayList<Dragon>();
13
	/** The amount of time until the dragon can be hurt by melee damage again */
14
	private int damageCooldown = 0;
15
	
16
	/** The default constructor
17
	 * @param rider - the player that summoned this dragon 
18
	 * @param maxHealth - the amount of hitpoints this dragon has
19
	 * @param world - the NMS world we're spawning the dragon in
20
	 */
21
	Dragon(Player rider, int maxHealth, WorldServer world) {
22
		super(world);
23
		this.rider = rider;
24
		setHealth(health = maxHealth);
25
		loc = rider.getLocation();
26
		loc.setYaw(yaw = loc.getYaw() - 180);
27
		loc.setPitch(0);
28
		setPosition(loc, false);
29
		getBukkitEntity().setPassenger(rider);
30
		((LivingEntity) getBukkitEntity()).setMaxHealth(maxHealth);
31
		dragons.add(this);
32
    }
33
	
34
	@Override
35
	/** The main thread of this dragon, called every tick */
36
	public void c() {
37
		// Checks if the player dismounted. Kills the dragon and returns if yes
38
		if (bukkitEntity.getPassenger() != rider) {
39
			kill();
40
			return;
41
		}
42
		// Handles the damage cooldown
43
		if (damageCooldown > 0) damageCooldown--;
44
		// Handles the controls
45
		EntityLiving passenger = (EntityLiving) this.passenger;
46
		loc.setYaw(yaw = passenger.yaw - 180); 
47
		boolean left = passenger.be < 0, right = passenger.be > 0, forwards = passenger.bf > 0, backwards = passenger.bf < 0;
48
		double y = rider.getLocation().getDirection().getY();
49
		Vector add = new Vector();
50
		if (left) addTurnedDir(add, 90, .5, 0);
51
		if (right) addTurnedDir(add, -90, .5, 0);
52
		if (forwards) addTurnedDir(add, 0, 1, y);
53
		else if (backwards) addTurnedDir(add, 0, -.5, y);
54
		try {
55
			Field jump = EntityLiving.class.getDeclaredField("bd");
56
			jump.setAccessible(true);
57
			if (jump.getBoolean(passenger)) add.setY(.3f);
58
		} catch (Exception e) {
59
			e.printStackTrace();
60
		}
61
		loc.add(add.multiply(speed));
62
		setPosition(loc, true);
63
	}
64
	
65
	/** Adds an angled version of the dragon's direction to the vector
66
	 * @param add - the vector that we're adding to
67
	 * @param angle - the angle under which we're adding to the vector. If 0, this will also set add a vertical thrust
68
	 * @param mod - how much should we add to the vector
69
	 * @param y - the vertical thrust. Get from the player's direction
70
	 */
71
	void addTurnedDir(Vector add, float angle, double mod, double y) {
72
		Location loc = this.loc.clone();
73
		loc.setYaw(yaw + angle);
74
		Vector dir = loc.getDirection();
75
		if (angle == 0) dir.setY(-y);
76
		add.add(dir.normalize().multiply(-mod));
77
	}
78
	
79
	/** Kills this dragon */
80
	void kill() {
81
		getBukkitEntity().remove();
82
	}
83
84
	/** Sets the dragon's position and does the collision checks
85
	 * @param loc - the location to move the dragon to
86
	 * @param colide - if true, the dragon will collide with the terrain
87
	 */
88
	void setPosition(Location loc, boolean colide) {
89-
		World world = loc.getWorld();
89+
		if (colide) if (loc.getBlock().getType().isSolid()) 
90-
		if (colide) {
90+
			if (!colAndRev(true, false, false) && !colAndRev(false, true, false) && !colAndRev(false, false, true) && !colAndRev(true, true, false) && !colAndRev(false, true, true)) {
91-
			xCol: for (int y = -1; y < 1; y++) for (int z = -1; z < 1; z++) if (world.getBlockAt((int) loc.getX() - 1, (int) loc.getY() + y, (int) loc.getZ() + z).getType().isSolid() || world.getBlockAt((int) loc.getX() + 1,  (int) loc.getY() + y, (int) loc.getZ() + z).getType().isSolid()) {
91+
					loc.setX(locX);
92-
				loc.setX(locX);
92+
					loc.setY(locY);
93-
				break xCol;
93+
					loc.setZ(locZ);
94
				}
95-
			yCol: for (int x = -1; x < 1; x++) for (int z = -1; z < 1; z++) if (world.getBlockAt((int) loc.getX() + x, (int) loc.getY() - 1, (int) loc.getZ() + z).getType().isSolid() || world.getBlockAt((int) loc.getX() + x, (int) loc.getY() + 1, (int) loc.getZ() + z).getType().isSolid()) {
95+
96-
				loc.setY(locY);
96+
97-
				break yCol;
97+
98
	/** Checks if the selected axes are the one the dragon got stuck on. If yes, it rolls them back
99-
			zCol: for (int x = -1; x < 1; x++) for (int y = -1; y < 1; y++) if (world.getBlockAt((int) loc.getX() + x, (int) loc.getY() + y, (int) loc.getZ() - 1).getType().isSolid() || world.getBlockAt((int) loc.getX() + x, (int) loc.getY() + y, (int) loc.getZ() + 1).getType().isSolid()) {
99+
	 * @param revX - if it should check the X axis
100-
				loc.setZ(locZ);
100+
	 * @param revY - if it should check the Y axis
101-
				break zCol;
101+
	 * @param revZ - if it should check the Z axis
102
	 * @return if it succesfuly rolled back. If false, continue looking for the problematic axes
103
	 */
104
	private boolean colAndRev(boolean revX, boolean revY, boolean revZ) {
105
		double x = loc.getX(), y = loc.getY(), z = loc.getZ();
106
		if (revX) x = locX;
107
		if (revY) y = locY;
108
		if (revZ) z = locZ;
109
		if (!loc.getWorld().getBlockAt((int) x, (int) y, (int) z).getType().isSolid()) {
110
			loc.setX(x);
111
			loc.setY(y);
112
			loc.setZ(z);
113
			return true;
114
		}
115
		return false;
116
	}
117
	
118
	/** Deals damage to the dragon. Kills him if his health drops to 0
119
	 * @param damage - the amount of damage to be dealt
120
	 */
121
	void damage(int damage) {
122
		health -= damage;
123
		if (health <= 0) kill();
124
		else setHealth(health);
125
	}
126
	
127
	/** Deals melee damage to the dragon
128
	 * @param material - the item that the dragon was punched with
129
	 */
130
	void damage(Material material) {
131
		if (damageCooldown > 0) return;
132
		damageCooldown = 10;
133
		int damage = 1;
134
		if (material == Material.DIAMOND_SWORD) damage += 7;
135
		else if (material == Material.IRON_SWORD) damage += 6;
136
		else if (material == Material.STONE_SWORD) damage += 5;
137
		else if (material == Material.WOOD_SWORD || material == Material.GOLD_SWORD) damage += 4;
138
		damage(damage);
139
	}
140
}
141
142
/** Used to listen to events */
143
public final class MMListener implements Listener {
144
	/** The list of all the arrows */
145
	private List<Arrow> arrows;
146
	
147
	/** The default constructor */
148
	MMListener() {
149
		arrows = new ArrayList<Arrow>();
150
		MM plugin = MM.getPlugin();
151
		plugin.getServer().getScheduler().scheduleSyncRepeatingTask(plugin, new Runnable() {
152
			public void run() {
153
				for (Arrow arrow : arrows) dragonSearch: for (Dragon dragon : Dragon.dragons) if (arrow.getLocation().distanceSquared(dragon.loc) <= 9) {
154
						dragon.damage(6);
155
						arrow.remove();
156
						arrows.remove(arrow);
157
						break dragonSearch;
158
					}
159
			}
160
		}, 1, 1);
161
	}
162
	
163
	/** Handles mouse clicks done by players */
164
	@EventHandler(priority = EventPriority.HIGH)
165
	public void onPlayerInteract(PlayerInteractEvent event) {
166
		Player player = event.getPlayer();
167
		Action action = event.getAction();
168
		// Checks if the player attacked a dragon. If so, deals melee damage to that dragon
169
		dragonSearch: for (Dragon dragon : Dragon.dragons) if (player != dragon.rider) for (int i = 0; i < 5; i++) 
170
			if (player.getTargetBlock(null, i).getLocation().distanceSquared(dragon.loc) <= 9) {
171
				dragon.damage(player.getItemInHand().getType());
172
				break dragonSearch;
173
			}
174
	}
175
176
	@EventHandler(priority = EventPriority.HIGH)
177
	/** Handles shot projectiles */
178
	public void onProjectileLaunch(ProjectileLaunchEvent event) {
179
		Projectile projectile = event.getEntity();
180
		if (projectile instanceof Arrow) arrows.add((Arrow) projectile);
181
	}
182
	
183
	@EventHandler(priority = EventPriority.HIGH)
184
	/** Handles projectiles landing */
185
	public void onProjectileHit(ProjectileHitEvent event) {
186
		Projectile projectile = event.getEntity();
187
		if (arrows.contains(projectile)) arrows.remove(projectile);
188
	}
189
}