Skip to content
Permalink
Browse files
Merge pull request #548 from Pieter12345/master
Add get/set_skull_owner functions
  • Loading branch information
PseudoKnight committed Jan 30, 2020
2 parents 5fdf61e + 701f4a7 commit 0fa2489d666adcb4a750ef8b919a8416dabf47db
Show file tree
Hide file tree
Showing 6 changed files with 234 additions and 23 deletions.
@@ -0,0 +1,24 @@
package com.laytonsmith.abstraction.blocks;

import com.laytonsmith.abstraction.MCOfflinePlayer;

public interface MCSkull extends MCBlockState {

/**
* Gets the player which owns the skull.
* @return The player or {@code null} if the skull does not have an owner.
*/
MCOfflinePlayer getOwningPlayer();

/**
* Gets whether the skull has an owner.
* @return {@code true} if the skull has an owner, {@code false} otherwise.
*/
boolean hasOwner();

/**
* Sets the player which owns the skull.
* @param player - The new skull owner or {@code null} to clear the current owner.
*/
void setOwningPlayer(MCOfflinePlayer player);
}
@@ -40,6 +40,7 @@
import com.laytonsmith.abstraction.bukkit.blocks.BukkitMCFurnace;
import com.laytonsmith.abstraction.bukkit.blocks.BukkitMCLectern;
import com.laytonsmith.abstraction.bukkit.blocks.BukkitMCMaterial;
import com.laytonsmith.abstraction.bukkit.blocks.BukkitMCSkull;
import com.laytonsmith.abstraction.bukkit.entities.BukkitMCAgeable;
import com.laytonsmith.abstraction.bukkit.entities.BukkitMCCommandMinecart;
import com.laytonsmith.abstraction.bukkit.entities.BukkitMCComplexEntityPart;
@@ -106,6 +107,7 @@
import org.bukkit.block.Dropper;
import org.bukkit.block.Furnace;
import org.bukkit.block.Lectern;
import org.bukkit.block.Skull;
import org.bukkit.block.banner.Pattern;
import org.bukkit.command.BlockCommandSender;
import org.bukkit.command.CommandSender;
@@ -494,6 +496,22 @@ public List<MCEntity> GetEntitiesAt(MCLocation location, double radius) {
}

public static MCBlockState BukkitGetCorrectBlockState(BlockState bs) {
if(bs instanceof Container) {
// This code block should only contain checks for blockstates that implement Container.
if(bs instanceof BrewingStand) {
return new BukkitMCBrewingStand((BrewingStand) bs);
}
if(bs instanceof Dispenser) {
return new BukkitMCDispenser((Dispenser) bs);
}
if(bs instanceof Dropper) {
return new BukkitMCDropper((Dropper) bs);
}
if(bs instanceof Furnace) {
return new BukkitMCFurnace((Furnace) bs);
}
return new BukkitMCContainer((Container) bs);
}
if(bs instanceof Banner) {
return new BukkitMCBanner((Banner) bs);
}
@@ -503,20 +521,8 @@ public static MCBlockState BukkitGetCorrectBlockState(BlockState bs) {
if(bs instanceof Beacon) {
return new BukkitMCBeacon((Beacon) bs);
}
if(bs instanceof BrewingStand) {
return new BukkitMCBrewingStand((BrewingStand) bs);
}
if(bs instanceof Dispenser) {
return new BukkitMCDispenser((Dispenser) bs);
}
if(bs instanceof Dropper) {
return new BukkitMCDropper((Dropper) bs);
}
if(bs instanceof Furnace) {
return new BukkitMCFurnace((Furnace) bs);
}
if(bs instanceof Container) { // needs to be after all specific containers
return new BukkitMCContainer((Container) bs);
if(bs instanceof Skull) {
return new BukkitMCSkull((Skull) bs);
}
if(Static.getServer().getMinecraftVersion().gte(MCVersion.MC1_14) && bs instanceof Lectern) {
return new BukkitMCLectern((Lectern) bs);
@@ -14,7 +14,7 @@ public class BukkitMCOfflinePlayer extends BukkitMCAnimalTamer implements MCOffl

OfflinePlayer op;

BukkitMCOfflinePlayer(OfflinePlayer offlinePlayer) {
public BukkitMCOfflinePlayer(OfflinePlayer offlinePlayer) {
super(offlinePlayer);
this.op = offlinePlayer;
}
@@ -12,7 +12,7 @@
import com.laytonsmith.abstraction.blocks.MCMaterial;
import com.laytonsmith.abstraction.blocks.MCSign;
import com.laytonsmith.abstraction.enums.bukkit.BukkitMCLegacyMaterial;
import com.laytonsmith.abstraction.bukkit.BukkitMCCreatureSpawner;
import com.laytonsmith.abstraction.bukkit.BukkitConvertor;
import com.laytonsmith.abstraction.bukkit.BukkitMCItemStack;
import com.laytonsmith.abstraction.bukkit.BukkitMCLocation;
import com.laytonsmith.abstraction.bukkit.BukkitMCMetadatable;
@@ -21,9 +21,7 @@
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.block.CommandBlock;
import org.bukkit.block.CreatureSpawner;
import org.bukkit.block.Dispenser;
import org.bukkit.block.Sign;
import org.bukkit.block.data.BlockData;
@@ -96,11 +94,7 @@ public void setBlockData(MCBlockData data, boolean physics) {

@Override
public MCBlockState getState() {
BlockState bs = b.getState();
if(bs instanceof CreatureSpawner) {
return new BukkitMCCreatureSpawner((CreatureSpawner) bs);
}
return new BukkitMCBlockState(bs);
return BukkitConvertor.BukkitGetCorrectBlockState(b.getState());
}

@Override
@@ -0,0 +1,49 @@
package com.laytonsmith.abstraction.bukkit.blocks;

import com.laytonsmith.PureUtilities.Common.ReflectionUtils;
import com.laytonsmith.abstraction.MCOfflinePlayer;
import com.laytonsmith.abstraction.blocks.MCSkull;
import com.laytonsmith.abstraction.bukkit.BukkitMCOfflinePlayer;

import org.bukkit.OfflinePlayer;
import org.bukkit.block.Skull;

public class BukkitMCSkull extends BukkitMCBlockState implements MCSkull {

Skull skull;

public BukkitMCSkull(Skull skull) {
super(skull);
this.skull = skull;
}

@Override
public Skull getHandle() {
return this.skull;
}

@Override
public MCOfflinePlayer getOwningPlayer() {
OfflinePlayer player = this.skull.getOwningPlayer();
return (player == null ? null : new BukkitMCOfflinePlayer(this.skull.getOwningPlayer()));
}

@Override
public boolean hasOwner() {
return this.skull.hasOwner();
}

@Override
public void setOwningPlayer(MCOfflinePlayer player) {

// Handle resetting the skull owner. The Bukkit API does not allow this and clients will need to refresh chunks
// to see this change.
if(player == null) {
ReflectionUtils.set(this.skull.getClass(), this.skull, "profile", null);
return;
}

// Set the skull owner.
this.skull.setOwningPlayer((OfflinePlayer) player.getHandle());
}
}
@@ -5,6 +5,7 @@
import com.laytonsmith.abstraction.MCCommandSender;
import com.laytonsmith.abstraction.MCLocation;
import com.laytonsmith.abstraction.MCNote;
import com.laytonsmith.abstraction.MCOfflinePlayer;
import com.laytonsmith.abstraction.MCPlayer;
import com.laytonsmith.abstraction.MCWorld;
import com.laytonsmith.abstraction.StaticLayer;
@@ -14,6 +15,7 @@
import com.laytonsmith.abstraction.blocks.MCCommandBlock;
import com.laytonsmith.abstraction.blocks.MCMaterial;
import com.laytonsmith.abstraction.blocks.MCSign;
import com.laytonsmith.abstraction.blocks.MCSkull;
import com.laytonsmith.abstraction.enums.MCBiomeType;
import com.laytonsmith.abstraction.enums.MCInstrument;
import com.laytonsmith.abstraction.enums.MCParticle;
@@ -854,6 +856,142 @@ public Mixed exec(Target t, com.laytonsmith.core.environments.Environment enviro
}
}

@api(environments = {CommandHelperEnvironment.class})
public static class set_skull_owner extends AbstractFunction {

@Override
public String getName() {
return "set_skull_owner";
}

@Override
public Integer[] numArgs() {
return new Integer[]{2};
}

@Override
public String docs() {
return "void {locationArray, owner}"
+ " Sets the owner of the skull at the given location by name or uuid."
+ " Supplying null will clear the skull owner, but due to limitations in Bukkit, clients will only"
+ " see this change after reloading the block."
+ " If no world is provided and the function is executed by a player, the player's world is used."
+ " If the block at the given location isn't a skull, a RangeException is thrown.";
}

@Override
public Class<? extends CREThrowable>[] thrown() {
return new Class[]{CRERangeException.class, CREFormatException.class};
}

@Override
public boolean isRestricted() {
return true;
}

@Override
public MSVersion since() {
return MSVersion.V3_3_4;
}

@Override
public Boolean runAsync() {
return false;
}

@Override
public Mixed exec(Target t, com.laytonsmith.core.environments.Environment environment, Mixed... args)
throws ConfigRuntimeException {
MCWorld defaultWorld = null;
MCCommandSender sender = environment.getEnv(CommandHelperEnvironment.class).GetCommandSender();
if(sender instanceof MCPlayer) {
defaultWorld = ((MCPlayer) sender).getWorld();
}
MCLocation loc = ObjectGenerator.GetGenerator().location(args[0], defaultWorld, t);
MCBlock block = loc.getBlock();
MCBlockState blockState = block.getState();
if(blockState instanceof MCSkull) {
MCSkull skull = (MCSkull) blockState;
MCOfflinePlayer owner = (args[1] instanceof CNull ? null : Static.GetUser(args[1], t));
skull.setOwningPlayer(owner);
skull.update();
return CVoid.VOID;
} else {
throw new CRERangeException("The block at the specified location is not a skull", t);
}
}
}

@api(environments = {CommandHelperEnvironment.class})
public static class get_skull_owner extends AbstractFunction {

@Override
public String getName() {
return "get_skull_owner";
}

@Override
public Integer[] numArgs() {
return new Integer[]{1};
}

@Override
public String docs() {
return "array {locationArray}"
+ " Returns the owner name and uuid of the skull at the given location as an array in format:"
+ " {name: NAME, uuid: UUID}, or null if the skull does not have an owner. The value at the 'name'"
+ " key will be an empty string if the server does not know the player's name."
+ " If no world is provided and the function is executed by a player, the player's world is used."
+ " If the block at the given location isn't a skull, a RangeException is thrown.";
}

@Override
public Class<? extends CREThrowable>[] thrown() {
return new Class[]{CRERangeException.class, CREFormatException.class};
}

@Override
public boolean isRestricted() {
return true;
}

@Override
public MSVersion since() {
return MSVersion.V3_3_4;
}

@Override
public Boolean runAsync() {
return false;
}

@Override
public Mixed exec(Target t, com.laytonsmith.core.environments.Environment environment, Mixed... args)
throws ConfigRuntimeException {
MCWorld defaultWorld = null;
MCCommandSender sender = environment.getEnv(CommandHelperEnvironment.class).GetCommandSender();
if(sender instanceof MCPlayer) {
defaultWorld = ((MCPlayer) sender).getWorld();
}
MCLocation loc = ObjectGenerator.GetGenerator().location(args[0], defaultWorld, t);
MCBlockState blockState = loc.getBlock().getState();
if(blockState instanceof MCSkull) {
MCSkull skull = (MCSkull) blockState;
MCOfflinePlayer owner = skull.getOwningPlayer();
if(owner == null) {
return CNull.NULL;
} else {
CArray ret = new CArray(t);
ret.set("name", owner.getName());
ret.set("uuid", owner.getUniqueID().toString());
return ret;
}
} else {
throw new CRERangeException("The block at the specified location is not a skull", t);
}
}
}

@api(environments = {CommandHelperEnvironment.class})
public static class break_block extends AbstractFunction {

0 comments on commit 0fa2489

Please sign in to comment.