Skip to content

Instantly share code, notes, and snippets.

@effective-light
Last active June 19, 2017 21:19
Show Gist options
  • Select an option

  • Save effective-light/5074526a86866bff978d to your computer and use it in GitHub Desktop.

Select an option

Save effective-light/5074526a86866bff978d to your computer and use it in GitHub Desktop.
Holograms.
/**
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
package packagename;
import com.google.common.base.Preconditions;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import javax.annotation.Nonnull;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
public class Hologram
{
private Player player;
private Location location;
private String[] lines;
private Object[] armorStands;
private static Constructor<?> armorStandConstructor;
private static Constructor<?> spawnEntityConstructor;
private static Constructor<?> destroyEntityConstructor;
private static Method getId;
private static Method setGravity;
private static Method setInvisible;
private static Method setCustomNameVisible;
private static Method setCustomName;
private static Method getPlayerHandle;
private static Method getWorldHandle;
private static Method sendPacket;
private static Field playerConnection;
static
{
String version = Bukkit.getServer().getClass().getPackage().getName().split( "\\." )[ 3 ];
String nms = "net.minecraft.server." + version + ".";
String obc = "org.bukkit.craftbukkit." + version + ".";
try
{
Class<?> entityArmorStand = Class.forName( nms + "EntityArmorStand" );
armorStandConstructor = entityArmorStand.getConstructor( Class.forName( nms + "World" ), double.class, double.class, double.class );
setGravity = entityArmorStand.getMethod( "setGravity", boolean.class );
setInvisible = entityArmorStand.getMethod( "setInvisible", boolean.class );
setCustomNameVisible = entityArmorStand.getMethod( "setCustomNameVisible", boolean.class );
setCustomName = entityArmorStand.getMethod( "setCustomName", String.class );
getId = Class.forName( nms + "Entity" ).getMethod( "getId" );
spawnEntityConstructor = Class.forName( nms + "PacketPlayOutSpawnEntityLiving" ).getConstructor( Class.forName( nms + "EntityLiving" ) );
destroyEntityConstructor = Class.forName( nms + "PacketPlayOutEntityDestroy" ).getConstructor( int[].class );
getPlayerHandle = Class.forName( obc + "entity.CraftPlayer" ).getMethod( "getHandle" );
getWorldHandle = Class.forName( obc + "CraftWorld" ).getMethod( "getHandle" );
playerConnection = Class.forName( nms + "EntityPlayer" ).getField( "playerConnection" );
sendPacket = Class.forName( nms + "PlayerConnection" ).getMethod( "sendPacket", Class.forName( nms + "Packet" ) );
} catch ( ClassNotFoundException | NoSuchMethodException | NoSuchFieldException e )
{
e.printStackTrace();
}
}
public Hologram(@Nonnull Player player, @Nonnull Location location, @Nonnull String... lines)
{
Preconditions.checkArgument( lines.length > 1, "You must have at least one line!" );
this.player = player;
this.location = location;
this.lines = lines;
this.armorStands = new Object[ lines.length ];
}
public void setLine(int line, @Nonnull String text)
{
int index = line - 1;
this.lines[ index ] = text;
try
{
setCustomName.invoke( armorStands[ index ], text );
} catch ( IllegalAccessException | InvocationTargetException e )
{
e.printStackTrace();
}
show( index );
}
public List<String> getLines()
{
return Arrays.asList( lines );
}
public Location getLocation()
{
return location;
}
public Player getPlayer()
{
return player;
}
public void show()
{
for ( int i = 0; i < lines.length; i++ )
{
show( i );
}
}
public void show(int index)
{
try
{
if ( armorStands[ index ] != null )
{
@SuppressWarnings("all")
Object destroyEntity = destroyEntityConstructor.newInstance( new int[]{ ( int ) getId.invoke( armorStands[ index ] ) } );
Object craftPlayer = getPlayerHandle.invoke( player );
Object connection = playerConnection.get( craftPlayer );
sendPacket.invoke( connection, destroyEntity );
}
Object armorStand;
if ( armorStands[ index ] == null )
{
armorStand = armorStandConstructor.newInstance( getWorldHandle.invoke( location.getWorld() ),
location.getX(), location.getY() - ( 0.25D * index ), location.getZ() );
setGravity.invoke( armorStand, false );
setInvisible.invoke( armorStand, true );
setCustomNameVisible.invoke( armorStand, true );
setCustomName.invoke( armorStand, lines[ index ] );
armorStands[ index ] = armorStand;
} else
{
armorStand = armorStands[ index ];
}
Object entity = spawnEntityConstructor.newInstance( armorStand );
Object craftPlayer = getPlayerHandle.invoke( player );
Object connection = playerConnection.get( craftPlayer );
sendPacket.invoke( connection, entity );
} catch ( InvocationTargetException | InstantiationException | IllegalAccessException e )
{
e.printStackTrace();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment