today I'm here to ask you a question, on Minecraft in particular in the PaperMc development (Bukkit Fork) I'm trying to create the "animations" effect like the famous Hypixel lootboxes (Opening phase) so I needed know how I could identify the PlayerHeadMovement Event. I tried with
#EventHandler
public void onPlayerMove(PlayerMoveEvent e) {
System.out.println("A");
}
But it would appear not to detect head movement.
There is no event that specifically focuses on the movement of the player's head.
You can, however, on the PlayerMoveEvent get the from and to movements.
So, to see if the player's head has moved, your code could look like:
private boolean hasPlayerHeadMoved(PlayerMoveEvent e) {
Location from = e.getFrom();
Location to = e.getTo();
return from.getYaw() != to.getYaw() || from.getPitch() != to.getPitch();
}
In your event handler, you would then call the method:
#EventHandler
public void onPlayerMove(PlayerMoveEvent e) {
boolean headHasMoved = hasPlayerHeadMoved(e);
}
Related
#EventHandler
public void playerInteraction(PlayerInteractEvent event)
{
Action action = event.getAction();
Player player = event.getPlayer();
Block block = event.getClickedBlock();
if (action.equals(Action.RIGHT_CLICK_BLOCK))
{
if (block.getType().equals(Material.NETHER_WART_BLOCK))
{
player.setHealth(player.getHealth() -1);
player.playSound(player.getLocation(), Sound.ENTITY_PLAYER_HURT, 10, 1);
}
else if (block.getType().equals(Material.DIAMOND_BLOCK))
{
player.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, 1000, 2));
player.playSound(player.getLocation(), Sound.ENTITY_SPLASH_POTION_BREAK, 10, 1);
}
else if(block.getType().equals(Material.EMERALD_BLOCK))
{
if (player.getHealth() != 20)
{
player.setHealth(player.getHealth() + 1);
player.playSound(player.getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 10, 1);;
}
if (player.getHealth() == 20)
{
player.sendMessage(ChatColor.DARK_RED + "You are already at full health!");
}
}
}
}
For some reason, all of these things happen twice whenever I right click the designated blocks. Anyone know why? I have posted the entire method, it's a player interaction event.
Thanks :)
First of all, make sure yo haven't registered the Listener class containing the event handler twice.
If that's not the case, according to this thread on the spigot forums, since Mojang added the left hand slot to Minecraft some events like PlayerInteractEvent or InventoryClickEvent will be called twice (once for each hand).
One possible fix is to "disable" the left hand on the event handler:
#EventHandler
public void onPlayerInteraction(PlayerInteractEvent event) {
if(event.getAction() == Action.RIGHT_CLICK_BLOCK && event.getHand() == EquipmentSlot.HAND) {
//Do something once
}
}
If you require that both hands could be used to trigger the event you could do the following:
First time the code gets executed you add the player to a list.
Before executing the code you check if the player is in the list. If it's in the list it means the code was executed once so you can skip it.
Schedule a task to remove the player from the list some ticks later.
The code could be as follows:
public class Foo implements Listener {
//An instance of the main plugin class
private MainClass plugin;
private List<UUID> playerBlacklist = new ArrayList<>();
#EventHandler
public void onPlayerInteractEvent(PlayerInteractEvent event) {
if(playerBlacklist.contains(event.getPlayer().getUniqueId)) {
return;
} else {
blacklistPlayer(event.getPlayer());
}
//Do something
}
private void blacklistPlayer(UUID uuid) {
playerBlacklist.add(uuid);
BukkitRunnable runnable = new BukkitRunnable(){
#Override
public void run() {
playerBlacklist.remove(uuid);
}
}
runnable.runTaskLaterAsynchronously(plugin, 5L);
}
}
Let me know if this solved your issue.
I'm currently developing a plugin which only renders an image to a map like this:
public class MapRendererTest extends MapRenderer {
private Image image;
public MapRendererTest(File file) {
try {
this.image = ImageIO.read(file);
}
catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void render(MapView mapView, MapCanvas mapCanvas, Player player) {
mapCanvas.drawImage(0, 0, image);
}
}
everything works fine, but there is this little thing in the red circle that I want to remove but I don't know how.
Things I already tried
Setting an emtpy MapCursorCollection
MapView.setWorld to a world where no-one is playing.
Creating MapCursorCollection with a invisible cursor
It would be amazing if someone could help me with that.
Thanks in advance
To get rid of the cursor, you have to remove all the other map renderers or at least the CraftMapRanderer.
In order to do this, you have to do the following:
#EventHandler
public void onMapInitialized(MapInitializeEvent e) {
e.getMap().removeRenderer(e.getMap().getRenderers().get(0));
e.getMap().addRenderer(new MapRendererTest(new File(Main.getInstance().getDataFolder() + "/image.png")));
}
This only works of course if there is no other custom map renderer assigned to this map, so the only registered is the CraftMapRenderer.
If you have multiple MapRenderers you could loop through the list and remove them.
I am making a plugin for a server I am developer on and I was developing a plugin!
I wanted to do commands to spawn a boss egg in by doing /boss give lvl <lvl> slime after you did the command it would give you an item that you can right click to spawn the boss in! Well like all new developers stuff doesn't always go the way you think it does. Here's my code I put in for checking if a player right click air or a block with the item SLIME_BALL in the players hand.
#EventHandler
public void onPlayerClicks(PlayerInteractEvent event) {
Player player = event.getPlayer();
Action action = event.getAction();
if (action.equals(Action.RIGHT_CLICK_AIR) || action.equals(Action.RIGHT_CLICK_BLOCK)) {
if (player.getItemInHand().getType() == Material.SLIME_BALL) {
player.sendMessage("You have right click a slime ball!");
}
}
}
Given that you are not seeing any stack traces in your logs, I would concur that your event listener is not registered. Let's say your listener class is called MyEventHandler it would be registered in onEnable() method, something similar to this
class MyPlugin extends JavaPlugin {
...
public void onEnable() {
Listener myEvtHnd = new MyEventHandler();
Bukkit.getPluginManager().registerEvents( myEvtHnd, this );
...
}
}
In general, your handler looks appropriate. PlayerInteractEvent provides a convenience method getItem() that returns the player's current item-in-hand. However, regardless of which method is used, you must check that the ItemStack returned is not null, which will happen if the player has no item in-hand.
#EventHandler
public void onPlayerClicks(PlayerInteractEvent event) {
Player player = event.getPlayer();
Action action = event.getAction();
ItemStack item = event.getItem();
if ( action.equals( Action.RIGHT_CLICK_AIR ) || action.equals( Action.RIGHT_CLICK_BLOCK ) ) {
if ( item != null && item.getType() == Material.SLIME_BALL ) {
player.sendMessage( "You have right click a slime ball!" );
}
}
}
Maybe instead of action.equals(), you can use action ==, as in:
if (action == Action.RIGHT_CLICK_AIR || action == Action.RIGHT_CLICK_BLOCK) {
if (player.getItemInHand().getType() == Material.SLIME_BALL) {
player.sendMessage("You have right click a slime ball!");
}
}
I will start off by explicitly stating my main question: what is the correct way to create midi events with the correct 'tick' from ShortMessages with the correct microsecond position when using the Java synthesizer to record to the Java sequencer?
I've been trying to figure this out for several days. My little midi program is quite simple, or should be, at least. There's a piano layout and three buttons. The piano, which uses the synthesizer, works great; you can play notes with the mouse or your computer keyboard.
I've read the Oracle Docs instructions backwards and forwards (and lots of forum threads), but clearly I'm missing something.
Currently I can get the sequencer to record by manually creating a ShortMessage, a MidiEvent, and sending them to the sequencer/add them to the track, but it will only record once. The play back also plays them back with usually the wrong timing. Here's the code that executes these: (if you want me to post additional or all of the code let know).
The code for what happens when I click the record/stop/buttons:
public void actionPerformed(ActionEvent e) {
if(e.getActionCommand() == "Record")
{
mySeq.deleteTrack(track);
track = mySeq.createTrack();
try {
seq.setSequence(mySeq);
} catch (InvalidMidiDataException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
seq.recordEnable(track, ChannelNum);
seq.startRecording();
}
else if(e.getActionCommand() == "Stop")
{
seq.stop();
}
else if(e.getActionCommand() == "Play")
{
mySeq.deleteTrack(track);
track = mySeq.createTrack();
addEvents(track);
seq.setTickPosition(10);
seq.start();
}
}
This is the code for when the user plays a note on the piano:
// The Mouse presses a key, the note on the channel is turned on
// A MidiEvent and ShortMessage are created using the CreateOnEvent method
public void mousePressed (MouseEvent e) {
Key key = (Key) e.getSource ();
channel.noteOn (key.getNote (), 127);
CreateOnEvent(key);
}
public void mouseReleased (MouseEvent e) {
Key key = (Key) e.getSource ();
channel.noteOff (key.getNote ());
CreateOffEvent(key);
}
public void mouseClicked (MouseEvent e) { }
public void mouseEntered (MouseEvent e) { }
public void mouseExited (MouseEvent e) { }
And finally here's the CreateOnEvent Method:
// I originally was sending the events directly to the sequencer
// but here I'm adding the events to an ArrayList of MidiEvents to attempt a work around
// I can then add those events to a track to play them
public void CreateOnEvent(Key key)
{
if(seq.isRecording())
{
ShortMessage myMsg = new ShortMessage();
try {
myMsg.setMessage(ShortMessage.NOTE_ON, ChannelNum, key.getNote(), 127);
} catch (InvalidMidiDataException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
long timeStamp = synth.getMicrosecondPosition();
long tick = seq.getTickPosition();
event = new MidiEvent(myMsg, tick);
seqReceiver.send(myMsg, timeStamp);
Events.add(event);
}
}
How can I check whether the mediaplayer is playing or stopped, using Java Media Framework?
You can call getState and check against Controller.Started:
if (mediaPlayer.getState() == Controller.Started)
// Register ControllerListener :
public class myPlayer implements ControllerListener {
// ....
Player player = Manager.createRealizedPlayer(url);
player.addControllerListener(this);
// ....
// And check for EndOfMedia event in the controllerUpdate method:
public void controllerUpdate(ControllerEvent event) {
if (event instanceof EndOfMediaEvent) {
// Take appropriate action
}
}
} // End of class
By checking the state and by listening to EndOfMedia event, one could detect if media is being played or stopped.
It seems like a bit changed since the accepted answer.
The following works for me:
if(this.player.getStatus() == MediaPlayer.Status.STOPPED){
// Do something
}