PlayerJoinEvent isn't working correctly - Minecraft - java

I created a config file for my plugin and I'm trying to get the PlayerJoinEvent to work so that when they join they will be displayed the message that is set in the config. When they join, no message is displayed though.
Code:
#EventHandler
public void onPlayerJoin(PlayerJoinEvent e) {
Player p = e.getPlayer();
String welcomeMessage = ChatColor.translateAlternateColorCodes('&',
plugin.getConfig().getString("Message"));
p.sendMessage(welcomeMessage);
}
Config:
Message: '&4did it work?'
And this part isn't as neccessary but incase you are wondering I have added this portion of the code for the config
private void registerConfig() {
getConfig().options().copyDefaults(true);
saveConfig();
}

Did you register your EventHandler on the PluginManager?
You can achieve this by placing the following code in your plugins onEnable() method:
getServer().getPluginManager().registerEvent(new MyPlayerJoinListener(), this);
Hope it helps!

Related

ListenerAdapter changes Memory Adress randomly? - Discord JDA API

So I just started playing around with JDA API trying to create a little /info command which looked like shown below.
Issue: Unfortunately the bot does not react when I type /info.
While I was debugging, I found out, that the Info command never get's called and I will explain why later, after showing you the 3 classes that are involved in this problem.
public class InfoCommand extends Command {
public InfoCommand(String name) {
super(name);
}
#Override
public void handle(MessageReceivedEvent event, String... params) {
EmbedBuilder builder = new EmbedBuilder();
builder.setTitle("Test Title");
builder.setDescription("Test Description" );
builder.setFooter("Created by t0gepi");
builder.setColor(0xf45642);
event.getChannel().sendTyping().queue();
event.getChannel().sendMessageEmbeds(builder.build()).queue();
}
}
It has a method handle which will be called by a CommandManager, whenever /info is typed in the discord server.
So far so good.
Now the Main method is also quite simple. It just starts the bot and adds the CommandManager as a Listener to JDA:
public class Main {
public static JDA jda;
public static void main(String[] args) throws LoginException {
ResourceManager.init();
jda = JDABuilder.createDefault(ResourceManager.getProperty("discord.bottoken")).build();
jda.getPresence().setStatus(OnlineStatus.IDLE);
jda.getPresence().setActivity(Activity.playing("Sleeping"));
try {
jda.awaitReady();
} catch (InterruptedException e) {
e.printStackTrace();
}
CommandManager commandManager = new CommandManager();
commandManager.addCommand(new InfoCommand("info"));
jda.addEventListener(new CommandManager());
}
}
Lastly, let's get to the CommandManager:
public class CommandManager extends ListenerAdapter {
private Set<Command> commands;
public CommandManager(){
this.commands = new HashSet<>();
}
public void addCommand(Command command){
commands.add(command);
}
#Override
public void onMessageReceived(#NotNull MessageReceivedEvent event) {
String[] msg = event.getMessage().getContentRaw().split(" ");
String prefix = ResourceManager.getProperty("command.prefix");
String[] params = null;
if(!msg[0].startsWith(prefix)){
return;
}
if(msg.length > 1){
params = Arrays.copyOfRange(msg,1,msg.length);
}
Iterator<Command> iterator = commands.iterator();
Command command;
while(iterator.hasNext()){
command = iterator.next();
if(command.getAliases().stream().anyMatch(alias -> msg[0].equalsIgnoreCase(prefix + alias))){
command.handle(event, params);
return;
}
}
// Do nothing here if command wasn't found.
}
}
Now let's get to the actual issue, why does the InfoCommands handle method not get called? Keep in mind that
InfoCommand has bin initialized and added to the CommandManager
The CommandManagers onMessageReceived method is in fact being called when a message is typed
As I was debugging, I found out why but could not find an explanation to it.
The reason why the handle method of InfoCommand does not get called, is because as to the time when onMessageReceived gets called, the CommandManagers set of commands is empty.
Why is that? I added the InfoCommand in the beginning right?
When I added the InfoCommand in the beginning, the set of commands had a size of 1. All good. But when onMessageReceived got called, the set of Commands suddenly had a size of 0, which means that the Iterator doesn't have anything to iterate over.
Why is that? I furthermore found out the following:
As to the time where I initialized the CommandManager, the CommandManager had a different memory adress than when it's onMessageReceived method got called.
So somehow, JDA must have created another new instance of CommandManager and used that, instead of my instance, right?
I hope someone understands this and let me know if you have any questions :)
Thanks for reading that far and if you'd like, you can take a better look at all the files in this Project here. There really aren't much more.
You are creating a new instance of your command manager when you register it:
jda.addEventListener(new CommandManager());
Instead, you should just pass in the instance you previously created:
CommandManager commandManager = new CommandManager();
commandManager.addCommand(new InfoCommand("info"));
jda.addEventListener(commandManager);

Minecraft Forge FMLClientSetupEvent fired on Server?

As stated in the Title I think that an FMLClientSetupEvent is Fired on a Forge-Minecraft dedicated Server. Forge Versions should be the same. All in all, this leads to the Error
java.lang.RuntimeException: Attempted to load class net/minecraft/client/renderer/entity/EntityRenderer for invalid dist DEDICATED_SERVER
I figured out that this is due to the CustomRender class which is a subclass of EntityRenderer.
When deleting the line "RenderingRegistry.registerEntityRend..." where I register the CustomRender the Server starts just fine.
Any ideas on that? I'm really not getting it myself because I can't debug the server app.
Documentation of FMLClientSetupEvent: https://mcforge.readthedocs.io/en/latest/conventions/loadstages/
My Code:
#Mod(Utils.MOD_ID)
public class Main {
public Main() {
ModItems.ITEMS.register(FMLJavaModLoadingContext.get().getModEventBus());
ModSounds.SOUNDS.register(FMLJavaModLoadingContext.get().getModEventBus());
ModEntityType.ENTITY_TYPES.register(FMLJavaModLoadingContext.get().getModEventBus());
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::commonSetup);
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::clientSetup);
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::serverSetup);
}
private void commonSetup(FMLCommonSetupEvent evt) {
}
private void clientSetup(FMLClientSetupEvent evt) {
Phaser.arrow = ModEntityType.LASERSTRAHL_ENTITY.get();
RenderingRegistry.registerEntityRenderingHandler(Phaser.arrow, renderManager -> new CustomRender(renderManager));
}
private void serverSetup(FMLDedicatedServerSetupEvent evt) {
}
}
I figured it out. The event isn't fired but apparently the Server doesn't like the EntityRenderer class being imported. So i made a new class for client setup stuff and called that after the FMLClientSetupEvent.

How do I turn off the chat for a specific player?

I am making a plugin where people can toggle the chat for themselves on the server.
What I have right now works pretty well:
#EventHandler(priority = EventPriority.HIGHEST)
public void onPlayerChat(#NotNull AsyncPlayerChatEvent e) {
if(TOGGLED_USERS_BY_UUID.contains(e.getPlayer().getUniqueId().toString())) {
e.setCancelled(true);
e.getPlayer().sendRawMessage(ToggleChat.LANG.get("cannotChat"));
return;
}
String message = e.getMessage();
getLogger().info(String.format("<%s>: %s", e.getPlayer().getName(), message));
e.setCancelled(true);
for(Player p : getServer().getOnlinePlayers()) {
if(!TOGGLED_USERS_BY_UUID.contains(p.getUniqueId().toString()))
p.sendRawMessage(String.format("<%s> %s", e.getPlayer().getName(), message));
}
}
But the problem comes when users have other things for their chat, such as a specific level for their chat message like (lvl) [username] - message or something.
How do I make it so that I don't have to re-send the message to users or just cancel the event for a specific user?
Thanks!
#EventHandler
public void onPlayerChat(AsyncPlayerChatEvent event) {
event.getRecipients().remove(/*player who shouldn't see chat*/);
}
If you want to filter players by their xp levels, you can use
getRecipients().removeIf(p -> p.getLevel() < minimumLevel)

Eclipse Listener to detect File changes?

I am searching a listener in Eclipse, that will detect if a file is changed externally by third party software, like MKS.
I used IResourceChangeListener and it worked. But problem is, it also listens other changes of the file. For example, when I delete the markers, it also listens and execute the codes I wanted after listening.
Is there any Listener, which listens only if the file is changed (newly opened/refreshed) by third party software?
Updated:
My code:
public class Startup implements IStartup {
IWorkspace workspace = ResourcesPlugin.getWorkspace();
IResourceChangeListener listener = new IResourceChangeListener() {
public void resourceChanged(IResourceChangeEvent event) {
if(event.getType() == IResourceChangeEvent.POST_CHANGE && IResourceDelta.MARKERS!=0){ //Filtering listener
System.out.println("Listener code should be implemented here");
}
System.out.println("listener is working"); //This line always get executed. That means the listener is working
}
};
#Override
public void earlyStartup() {
workspace.addResourceChangeListener(listener,IResourceChangeEvent.POST_CHANGE);
//... some time later one ...
// workspace.removeResourceChangeListener(listener);
}
}

Issues with creating custom events in android

I am writing a custom event and would like some help please. Most of what I am about to talk about is based on the help provided at Custom event listener on Android app
So here is my issue. I am writing an app that needs to download updated images from the web, store the images on the phone, then later display those images. Basically, I download any needed images during a splash screen. Then when the images are downloaded and stored, the splash screen clears and any necessary (newly downloaded) images are displayed on the screen. Here is the problem: the download process is done via an asynctask so the part where the images are loaded on to the screen can't be done inside the asynctask. It has to be done on the main UI thread. I would like to create an event and a custom event listener for the main thread to listen for that basically tells the main UI thread that it is safe to start loading the downloaded images from memory.
According to the discussion from the link above, I came up with this so far... a download listener interace
public interface DataDownloadListener {
void onDownloadStarted();
void onDownloadFinished();
}
an event class...
public class DataDownloadEvent {
ArrayList<DataDownloadListener> listeners = new ArrayList<DataDownloadListener>();
public void setOnDownload(DataDownloadListener listener){
this.listeners.add(listener);
}
}
My problem is that I don't understand where to put the last two steps in those instructions. I thought I would have to put the listener and event inside the class that actually initiates the downloads. But where? Here is my function that initiates the download and saves it to the device:
public String download(String sourceLocation) {
String filename = "";
String path = "";
try {
File externalStorageDirectory = Environment
.getExternalStorageDirectory();
URL urlTmp = new URL(sourceLocation);
filename = urlTmp.getFile()
.substring(filename.lastIndexOf("/") + 1);
path = externalStorageDirectory + PATH;
// check if the path exists
File f = new File(path);
if (!f.exists()) {
f.mkdirs();
}
filename = path + filename;
f = new File(filename);
//only perform the download if the file doesn't already exist
if (!f.exists()) {
Bitmap bitmap = BitmapFactory.decodeStream(urlTmp.openStream());
FileOutputStream fileOutputStream = new FileOutputStream(
filename);
if (bitmap != null) {
bitmap.compress(getFormat(filename), 50, fileOutputStream);
Log.d(TAG, "Saved image " + filename);
return filename;
}
}
else{
Log.d(TAG, "Image already exists: " + filename + " Not re-downloading file.");
}
} catch (MalformedURLException e) {
//bad url
} catch (IOException e) {
//save error
}
return null;
}
And the last step about registering the listener, where do I put that? The instructions say to put that somewhere during initialization. Does that mean in the onCreate method of my main activity? outside the class in the import section of the main activity? Never done a custom event before, so any help would be appreciated.
According to the discussion from the link above, I came up with this so far... a download listener interace
public interface DataDownloadListener {
void onDownloadStarted();
void onDownloadFinished();
}
an event class...
public class DataDownloadEvent {
ArrayList<DataDownloadListener> listeners = new ArrayList<DataDownloadListener>();
public void setOnDownload(DataDownloadListener listener){
this.listeners.add(listener);
}
}
Ok...
Now in your download procedure, at the start of the download, cycle all the elements on the listeners ArrayList and invoke the onDownloadStarted event to inform all your listeners that the download is just started (in this event i presume you'll need to open the splashscreen).
Always in your download procedure, at the and of the download, cycle all the elements on the listeners ArrayList and invoke the onDownloadFinished event to inform all your listeners that the download is finished (now close the splashscreen).
How to cycle listeners on download completed
foreach(DataDownloadListener downloadListener: listeners){
downloadListener.onDownloadFinished();
}
How to cycle listeners on download started
foreach(DataDownloadListener downloadListener: listeners){
downloadListener.onDownloadStarted();
}
Don't make it static if possible... In the class that you'll use to download your files, simply add what you put in your DataDownloadEvent class (listeners arrayList and facility methods for adding and removing). You have no immediate need to use a class in that way (static members I mean).
Example
public class DownloadFileClassExample{
private ArrayList<DataDownloadListener> listeners = new ArrayList<DataDownloadListener>();
public DownloadFileClassExample(){
}
public void addDownloadListener(DataDownloadListener listener){
listeners.add(listener);
}
public void removeDownloadListener(DataDownloadListener listener){
listeners.remove(listener);
}
//this is your download procedure
public void downloadFile(){...}
}
Then access you class in this way
DownloadFileClassExample example = new DownloadFileClassExample();
example.addDownloadListener(this); // if your class is implementing the **DataDownloadListener**
or use
example.addDownloadListener( new DataDownloadListener{...})

Categories

Resources