I've been looking all over, to find out how to spawn ropes (leads). I did not find any solutions, so I decided to make my own class, with a cheaty way, since that is the only way I know of right now. You can use this for decoration, ziplines, etcetera. Enough to play around with. Here is the class. Code:java public class Rope { private EntityWitherSkull start;private EntityWitherSkull end; public Rope() {} public Location getEnd() {return this.end.getBukkitEntity().getLocation();} public Location getStart() {return this.start.getBukkitEntity().getLocation();} public void move(Location newStart, Location newEnd) {delete();spawn(newStart, newEnd);} public void delete() {start.getBukkitEntity().getPassenger().remove();start.getBukkitEntity().remove();end.getBukkitEntity().getPassenger().remove();end.getBukkitEntity().remove();this.start = null;this.end = null;} public void spawn(Location start, Location end) {if (start.getWorld().getName().equals(end.getWorld().getName())) { WorldServer world = ((CraftWorld) start.getWorld()).getHandle(); EntityWitherSkull skullStart = new EntityWitherSkull(world);EntityWitherSkull skullEnd = new EntityWitherSkull(world); skullStart.setLocation(start.getX(), start.getY(), start.getZ(), 0, 0);skullEnd.setLocation(end.getX(), end.getY(), end.getZ(), 0, 0); world.addEntity(skullStart);world.addEntity(skullEnd); Bat ropeStart = (Bat) world.getWorld().spawnEntity(start, EntityType.BAT);Bat ropeEnd = (Bat) world.getWorld().spawnEntity(end, EntityType.BAT); skullStart.getBukkitEntity().setPassenger(ropeStart);skullEnd.getBukkitEntity().setPassenger(ropeEnd); ropeStart.addPotionEffect(new PotionEffect(PotionEffectType.INVISIBILITY, 9999999, 1));ropeEnd.addPotionEffect(new PotionEffect(PotionEffectType.INVISIBILITY, 9999999, 1)); ropeStart.setLeashHolder(ropeEnd); this.start = skullStart;this.end = skullEnd;}}} And you could use it by doing something like this; Code:java Rope rope = new Rope();rope.spawn(startLocation, endLocation);rope.delete();rope.move(newStartLocation, newEndLocation);rope.getEnd();rope.getStart(); Note that this is not fully working the way I wanted it to, since you can still damage the mobs that are being attached to eachother. For me, that's not a problem since I don't use mobs, so I can cancel all damage to bats. But maybe for anyone using this, it is, so be aware and mess some with this code to your needs. If packets does the job for you, Goblom improved this by much and made it use packets, which can be found right here.
Desle Awesome resource! Imagine if you could detect if a player is on the lead, then you could make zip lines :3
You could calculate a vector between the start and end point then set that as the player's velocity and it might look like they are zip lining . And only do this when they toggle crouch at the start location.
Windy Day Vectors = for me Just cool to speculate though :3 would be nice for buildings, add a pretty cool touch.
hmm.. I might turn this into using packets, so that the WitherSkulls aren't actually there. There's quite a few things you could do with this.
Agreed. Just like what Ultimate_n00b said. There id quite a few things you could do with this. As for calculating a vector between two locations, with Bukkit its super easy. Just do: Code: Vector vector = end.toVector().subtract(start.toVector());
I converted it to Packets. I have no idea if it works though... https://gist.github.com/Goblom/9354411 Code: Rope rope = new Rope(Location start, Location end); rope.setStart(Location location); rope.setEnd(Location location); rope.getStart(); rope.getEnd(); rope.spawn(); rope.deSpawn();
Goblom I totally forgot about the attach packets and whatnot.. Nice. May I use bits of your code and improve both classes of ours? I'll give you credit and all that
Would it be possible to "connect" a player to the rope, and then make them move along? I suppose vectors would be involved.
You'd have to calculate the curve of the rope then correct the player's velocity every tick. In theory, it could be done.
I did calculate the vector and change the player's velocity to it's "distance". The player went completly right at the first try (going in a line that doesn't make any curve), but when I tried with curves, the player went completly wrong xD I guess your way would work Maybe I can try this tomorrow
I updated source so that it updated every time you set start or end location as well as added a new constructor to make it so that it can automatically spawn at creation.
Very cool. Is it simple to add a vector to the rope (like a throwing animation), or does the entity just teleport to the new location from the starting location? Cheers
I can't seem to get it to work, keep having an error at: WorldServer world = ((CraftWorld) start.getWorld()).getHandle(); in the 'spawn()' method.
Well, it was an error on my part(got wrong locations), but now when I spawn them in, they stay there for a second then disappear!
Again, derp. I got it working. BUT: When they spawn in, the bats just fly around. They arent still. I was using it on my main world, where I did have them disabled, then I went to my survival world, and it worked(sort of) fine. EDIT by Moderator: merged posts, please use the edit button instead of double posting.
Fixed up and changed Goblom 's code to work with packets. This version is more about sticking the ends to entities. Now, you provide it with an entity to glue the start to and can provide it with another entity to glue the end to. Code:java import java.util.ArrayList;import java.util.List; import org.bukkit.Bukkit;import org.bukkit.Location;import org.bukkit.entity.Entity;import org.bukkit.entity.Player; import net.minecraft.server.v1_7_R1.EntityBat;import net.minecraft.server.v1_7_R1.PacketPlayOutAttachEntity;import net.minecraft.server.v1_7_R1.PacketPlayOutEntityDestroy;import net.minecraft.server.v1_7_R1.PacketPlayOutSpawnEntityLiving;import net.minecraft.server.v1_7_R1.WorldServer; import org.bukkit.craftbukkit.v1_7_R1.CraftWorld;import org.bukkit.craftbukkit.v1_7_R1.entity.CraftEntity;import org.bukkit.craftbukkit.v1_7_R1.entity.CraftPlayer; /*** Credits to [USER=90856537]Desle[/USER] for the original resource. (Uses entities, not packets)** @author Goblom* @author Jordan*/public class Rope { private static final List<Rope> ropes = new ArrayList<Rope>(); private Location loc_end; private EntityBat ent_bat_end; private Entity holder; public Rope(Location end, Entity holder) { this.loc_end = end; this.holder = holder; for (Rope r : new ArrayList<Rope>(ropes)) { if (r.holder != null && r.holder.equals(holder)) { r.holder = null; r.despawn(); } } ropes.add(this); spawn(); } public void setEnd(Location end) { this.loc_end = end; spawn(); } public Location getEnd() { return loc_end; } private void makeEnt() { WorldServer world = ((CraftWorld) loc_end.getWorld()).getHandle(); if (ent_bat_end == null) { this.ent_bat_end = new EntityBat(world); ent_bat_end.setInvisible(true); } this.ent_bat_end.setLocation(loc_end.getX(), loc_end.getY(), loc_end.getZ(), 0, 0); ent_bat_end.setLeashHolder(((CraftEntity) holder).getHandle(), true); } public void spawn() { if (holder == null) { despawn(); return; } makeEnt(); PacketPlayOutSpawnEntityLiving bat_end = new PacketPlayOutSpawnEntityLiving(ent_bat_end); PacketPlayOutAttachEntity attach = new PacketPlayOutAttachEntity(1, ent_bat_end, ((CraftPlayer) holder).getHandle()); for (Player player : Bukkit.getOnlinePlayers()) { CraftPlayer cP = (CraftPlayer) player; cP.getHandle().playerConnection.sendPacket(bat_end); cP.getHandle().playerConnection.sendPacket(attach); } } public void despawn() { PacketPlayOutEntityDestroy destroy = new PacketPlayOutEntityDestroy(ent_bat_end.getId()); for (Player player : Bukkit.getOnlinePlayers()) { CraftPlayer cP = (CraftPlayer) player; cP.getHandle().playerConnection.sendPacket(destroy); } ropes.remove(this); } public void glueEndTo(Entity att) { PacketPlayOutAttachEntity attach = new PacketPlayOutAttachEntity(0, ent_bat_end, ((CraftEntity) att).getHandle()); for (Player player : Bukkit.getOnlinePlayers()) { CraftPlayer cP = (CraftPlayer) player; cP.getHandle().playerConnection.sendPacket(attach); } }} A practical use of this might be as follows: To throw a rope, listen for a right-click event and do something like so: Code:java private void throwRope(Player thrower) { Rope rope = new Rope(thrower.getLocation(), thrower); Snowball snowball = thrower.launchProjectile(Snowball.class); rope.glueEndTo(snowball); } To glue the end of the rope to the snowball. Once the snowball lands, it is automatically un-glued from the rope and so the rope sticks where it lands. The other end follows the player.
Updated March 13, 2014 You can now Spawn & Despawn the rope for a Specific Player rope.spawn(Player player); rope.deSpawn(Player player);