Hey i just started with Java, RMI and JFrame about 2 weeks ago.
I'm doing a game, it works fine as a console but now i'm adding a GUI and i'm getting confused about how to get the Remote Client messages to my Text Area
Remote Client Interface
public interface IRemoteClientObject extends Remote {
public void notifyLogin(String player) throws RemoteException;
public void notifyLogout(String player) throws RemoteException;
public void notifyStatus(String player, PlayerStatus status) throws RemoteException;
public boolean challenge(String player) throws RemoteException;
}
Remote Client
public class RemoteClientObject extends UnicastRemoteObject implements
IRemoteClientObject {
/**
*
*/
private static final long serialVersionUID = -7209335248515276286L;
/**
* #throws RemoteException
*/
public RemoteClientObject() throws RemoteException {
}
#Override
public void notifyLogin(String player) throws RemoteException {
System.out.println("\n" + player + " joined the game");
}
#Override
public void notifyLogout(String player) throws RemoteException {
System.out.println("\n" + player + " left the game");
}
#Override
public void notifyStatus(String player, PlayerStatus status) throws RemoteException {
if (status.equals(PlayerStatus.PLAYING))
{
System.out.println("\n" + player + " is now playing");
}
else if (status.equals(PlayerStatus.READY))
{
System.out.println("\n" + player + " is available to play");
}
else
{
System.out.println("\n" + player + " is unavailable to play");
}
}
}
In my program without any GUI, for example when a player login (it sends a message to all players with that notification)
for (Player player : serverObject.getPlayers())
{
player.getClient().notifyLogin(username);
}
But now i don't want that text in the System.out, i want it in a text area
So can anyone make me a description about how to do this?Code is not the most important, i just want to understand how this works from a remote client to GUI (JTextArea)?
I'm not sure exactly what you have already. If the GUI in the picture is already built and you have your JTextArea object created, then just replace the line System.out.println(...) with myTextArea.setText(...) or myTextArea.append(...) depending if you want to keep previous content or replace it.
With my understanding you would have to add a button listener to a button (or a mouse listener for the text box) that would look for a certain keystroke (maybe the enter button) or you could even add a JButton to your GUI that the user would click to "submit" their text in that text area.
In the button listener you would just write something like JTextArea.getText(); (the "JTextArea" would just be whatever you called the text area variable.
Related
I am trying to create a bot that checks if a user attempts to enter a new voice channel, but when trying to override the onVoiceChannelUpdate method, it stays grayed out and gives me error that I don't have the parameters class.
This is the code I have for this method:
#Override
public void onVoiceChannelUpdate(VoiceChannelUpdateEvent event) {
User user = event.getUser();
VoiceChannel oldVoiceChannel = event.getOldVoiceChannel();
VoiceChannel newVoiceChannel = event.getNewVoiceChannel();
if (checkUserVoiceChannelRequest(user, oldVoiceChannel)) {
System.out.println(user.getName() + " has left the voice channel " + oldVoiceChannel.getName() + " and entered " + newVoiceChannel.getName() + ".");
}
}
I tried multiple ways of doing it, but all the methods have the exact same problem. I have some methods from before that check messages and all that and they work, but for any of the other methods that I use, the parameter class is not existent.
Errors showing:
Tried with onGuildVoiceUpdate method also, but it has the same issue:
can you try
public class Test extends ListenerAdapter {
#Override
public void onGuildVoiceUpdate(GuildVoiceUpdateEvent event) {
AudioChannel oldChannel = event.getChannelLeft();
AudioChannel newChannel = event.getChannelJoined();
}
}
Using JDA 5.0.0-beta.2.
If that does not work it might be an issue with your IDE so try to invalidate your cache.
You're looking for the GuildVoiceUpdateEvent instead.
#Override
public void onGuildVoiceUpdate(GuildVoiceUpdateEvent event) {
AudioChannel oldChannel = event.getChannelLeft();
AudioChannel newChannel = event.getChannelJoined();
...
}
I have created an ItemStack which should be given to players when they join, but it doesn't work as expected.
Here is my attempt:
public class Main extends JavaPlugin implements Listener{
public void onEnable(){
Bukkit.getServer().getPluginManager().registerEvents(this, this);
registerListeners();
}
private void registerListeners() {
PluginManager pm = Bukkit.getPluginManager();
}
public static void giveItems(Player p) {
}
#EventHandler
public void onPlayerJoin(PlayerJoinEvent e) {
Player p = e.getPlayer();
ItemStack t = new ItemStack(Material.TNT, 1);
ItemMeta tmeta = t.getItemMeta();
tmeta.setDisplayName("§cTNT §7(Right click to use)");
t.setItemMeta(tmeta);
for(Player pl : Bukkit.getOnlinePlayers()){
p.getInventory().setItem(4, t);
p.getInventory().addItem(t);
}
}
#SuppressWarnings("deprecation")
#EventHandler
public void onRightClick(PlayerInteractEvent e) {
if(e.getAction() == Action.RIGHT_CLICK_AIR || e.getAction() == Action.RIGHT_CLICK_BLOCK) {
if(e.getItem() != null && e.getItem().getType() == Material.TNT) {
Player p = e.getPlayer();
TNTPrimed tnt = (TNTPrimed) p.getWorld().spawn(p.getLocation(), TNTPrimed.class);
tnt.setVelocity(p.getLocation().getDirection().normalize().multiply(1));
p.updateInventory();
And it failed.
How can I successfully give ItemStacks to Players when they join the server?
Uh, why are you looping through all players in the server when you already have the player you want to give the item to in the variable p? You're also not using proper chat color codes.
Use this instead:
// Imports and other code here...
#EventHandler
public void onPlayerJoin(PlayerJoinEvent e){
Player p = e.getPlayer();
ItemStack t = new ItemStack(Material.TNT);
ItemMeta tmeta = t.getItemMeta();
tmeta.setDisplayName(ChatColor.RED + "TNT " + ChatColor.GRAY + "(Right click to use)");
t.setItemMeta(tmeta);
p.getInventory().addItem(t);
}
Other than that, I don't see anything wrong with your setup.
Looking into your code the following mistakes should be corrected:
Remove the useless method registerLiteners() and all of its calls. The method doesn't really do anything.
You should not interate all online players to add the ItemStack to your Player.
Second of all: from your question, what I can understand as your situation is: you want a player to join the server and receive an item for that. The way you're handling it is that everytime a player joins the server, he will get items added to his inventory for every player online in the server. The situation you're probably in is that you're testing the plugin on your own, and there is no player online when you join, what leads to no items being given.
All things considered, the correct way to get your intended behaviour should be the following:
#EventHandler
public void onPlayerJoin(PlayerJoinEvent e) {
Player joined = e.getPlayer();
ItemStack itemToAdd = new ItemStack(Material.TNT);
ItemMeta stackMeta = itemToAdd.getItemMeta();
stackMeta.setDisplayName(ChatColor.RED + "TNT " + ChatColor.GRAY + "(Right click to use)"); //Using ChatColor is recommended over § character.
itemToAdd.setItemMeta(stackMeta);
joined.getInventory().addItem(itemToAdd);
}
The event will add your custom itemstack to the player's inventory after he joins the server.
It's also important to point out that, although it's not part of your question, your PlayerInteractEvent should be fixed to only listen to your custom ItemStack. It will be fired with any TnT held.
In my application I have autocompleteTextField. I need to get id of player when text in input changed. I am trying to play with models which are recommended by this question: using AutoCompleteTextField in wicket without String as the generic type but with no success. Behaviour stop working when I use PropertyModel or when I set class Player.class instead of null. I dont understand why.
final AutoCompleteTextField<Player> playersField = new AutoCompleteTextField<Player>("players",
new Model<Player>(selectedPlayer), null, new AbstractAutoCompleteRenderer<Player>() {
#Override
protected void renderChoice(Player player, Response response, String criteria) {
response.write(getTextValue(player));
}
#Override
protected String getTextValue(Player player) {
return player.getName() + " " + player.getSurname() + " "
+ player.getPlayerDiscriminator();
}
}
, settings) {
#Override
protected Iterator<Player> getChoices(String prefix) {
List<Player> choices = getPlayers();
return choices.iterator();
}
};
add(playersField);
playersField.add(new AjaxFormComponentUpdatingBehavior("onchange") {
#Override
protected void onUpdate(AjaxRequestTarget target) {
System.out.println("do something");
// All I need here is just Id of player
}
}
});
From the question you linked to:
You probably already know this but if your custom class is really custom, you'll also need an IConverter that handles the String<->Someclass conversions: you can either register it with the application or override your component's getConverter(Class clazz ) method to return it.
Did you do that?
Also, if this doesn't fix the problem, please describe how it "stops working" in more details.
I'm trying to use events to do something on actor but i don't understand how to do it properly.
I have a button on my screen and a text (just for example). they are both actors in a stage
my purpose is: if i click on the button, i would like to change text
I add listener on my button, i get the click but i don't know how to send event (or anything else) to my text to set it.
Main class with stage definition and his
public class AGame implements ApplicationListener {
private WorldRendererTouchPad renderer;
private Stage stage;
private static Vector3 cameraVelocity=new Vector3(0,0,0);
private ButtonJump button;
public static final int SCREEN_WIDTH=800;
public static final int SCREEN_HEIGHT=480;
public void create() {
stage = new Stage();
stage.setViewport(SCREEN_WIDTH, SCREEN_HEIGHT, true);
stage.getCamera().translate(-stage.getGutterWidth(), -stage.getGutterHeight(), 0);
renderer = new MyRenderer(SCREEN_WIDTH, SCREEN_HEIGHT);
stage.addActor(renderer);
renderer.create();
button=new ButtonJump();
stage.addActor(button);
button.create();
Gdx.input.setInputProcessor(stage);
}
....
resize and other methods
}
MyRenderer class (contains text actor):
public class MyRenderer {
private TextTest text;
public MyRenderer(float screenWidth, float screenHeight) {
setBounds(0, 0, screenWidth, screenHeight);
}
public void create() {
this.initActors();
}
private void initActors() {
text=new TextTest("Hello world!");
addActor(text);
}
// is it usefull?
public void setText(String newText) {
text.setText(newText);
}
}
and the ButtonJump class (extends MyButton just here for define Skin and ButtonStyle)
public class ButtonJump extends MyButton {
public boolean isJump=false;
private static InputListener buttonListener=new InputListener() {
public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
Gdx.app.log("event" , "="+event.toString());
// do something to update text
return true;
}
};
public ButtonJump() {
super();
}
public void create() {
this.setPosition(getStage().getWidth()-60, 30);
this.addCaptureListener(buttonListener);
}
public void capture() {
if (this.isJump)
Gdx.app.log("jump button", "Jump is set");
else
Gdx.app.log("jump button", "No jump");
}
}
If you use the clicklistener you need to let the other actor hold an reference to it to call a method on click. It is not that good to let all Actor know of each other. Use an anonymous way.
There is a "common" system for it in games.
If you really want to use Events, do implement an Event-System. Therefore you have an interface Listen and an Interface Event_Handler. At the start of your game you init one Implementation of the Eventhandler. The interface should at least look like this:
public interface Interface_EventHandler extends Disposable
{
public void handleEvent(final Event... e);
public void registerListener(final Interface_Listen listener,
final Event_Type... type);
public void unregisterListener(final Interface_Listen... listener);
public void unregisterAllListener();
public void unregisterAllListener(final Event_Type... type);
public void processEvents();
public void processEvents(final int maxTimeInMS);
}
Okay so now how does it work. The handler has an hashmap with all eventtypes as Key and an list of listeners as Value. So if someone want to notice an event he registers with the registerListerner at the handler for the right Event_Type (Enum). It need to have the interface Listen to get events. Everyone can now push an Event into the handler with the handleEvent(...) method. Or even more than one.. (varargs) ..
Okay that still does not explain how it work. We now have a registered listener (actor for example) and we have events that get into the handler.
Every Rendercycle you call the processEvents() at the hanlder once. That mean that every event that get pushed in at a frame get handled at the next frame. (Asynchronus) While that he iterates over all events and push them to the listeners. Moreover the listener should have a queue too where they put all events and when they are at their .act() they handle the events. (more asynchronus).
Okay here is an Handler i use:
package com.portaaenigma.eventsystem;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import com.badlogic.gdx.utils.TimeUtils;
import com.portaaenigma.managers.Logger;
public class EventHandler implements Interface_EventHandler
{
private HashMap> listeners;
private LinkedList events;
public EventHandler()
{
listeners = new HashMap<Event_Type, ArrayList<Interface_Listen>>();
// add the arraylist for every Eventtype
for (Event_Type e : Event_Type.values())
{
listeners.put(e, new ArrayList<Interface_Listen>());
}
events = new LinkedList<Event>();
}
#Override
public void handleEvent(final Event... e)
{
for (Event event : e)
{
events.push(event);
}
}
#Override
public void unregisterListener(final Interface_Listen... listener)
{
for (Event_Type e : Event_Type.values())
{
for (Interface_Listen interface_Listen : listener)
{
listeners.get(e).remove(interface_Listen);
}
}
}
#Override
public void processEvents()
{
while (events.size() != 0)
{
// get the first element and delete it
Event e = events.pop();
for (Interface_Listen l : listeners.get(e.getType()))
{
l.handleEvent(e);
}
}
}
#Override
public void processEvents(final int maxTimeInMS)
{
int startSize = 0;
if (events.size() != 0)
{
startSize = events.size();
Logger.log("Processing Events: " + events.size());
}
long startTime = TimeUtils.millis();
while (events.size() != 0)
{
// get the first element and delete it
Event e = events.pop();
for (Interface_Listen l : listeners.get(e.getType()))
{
l.handleEvent(e);
}
// stop handling if time is up
if (startTime - TimeUtils.millis() > maxTimeInMS)
{
Logger.log("Handled " + (events.size() - startSize) + " Events");
break;
}
}
}
#Override
public void registerListener(final Interface_Listen listener,
Event_Type... type)
{
for (Event_Type event_Type : type)
{
listeners.get(event_Type).add(listener);
}
}
#Override
public void unregisterAllListener()
{
Logger.log("UnregisterAll");
for (Event_Type e : Event_Type.values())
{
listeners.get(e).clear();
}
}
#Override
public void unregisterAllListener(final Event_Type... type)
{
for (Event_Type event_Type : type)
{
listeners.get(event_Type).clear();
}
}
#Override
public void dispose()
{
unregisterAllListener();
events.clear();
listeners.clear();
}
}
The interface for all listeners is simple it's just this:
public interface Interface_Listen
{
public void handleEvent(final Event e);
}
Last but not least the event. How can you now send different data? Quiet simple. Have an hashmap out of Strings and Strings and for sure the EventType.
public class Event
{
private Event_Type type;
private HashMap<String, String> m_messages;
public Event(final Event_Type e, final Event_Message... m)
{
m_messages = new HashMap<String, String>();
for (Event_Message message : m)
{
m_messages.put(message.m_key, message.m_value);
}
type = e;
}
public Event_Type getType()
{
return type;
}
public void addMessages(final Event_Message... m)
{
for (Event_Message event_Message : m)
{
m_messages.put(event_Message.m_key, event_Message.m_value);
}
}
public String getMessage(final String name)
{
if (m_messages.get(name) == null)
{
Logger.error("Message not found: " + name);
}
// if null return an empty string
return m_messages.get(name) != null ? m_messages.get(name) : "";
}
public void clearMessages()
{
m_messages.clear();
}
}
Okay i hope this does explain how to implement an EventSystem at a Game. This meight not be the regular way at other Software but in games you queue up the events and handle them once in a Gameloop cycle. Also the listeners do the same.
So in your case. Implement such an handler and register the actors as listener. Sure they need to implement the listener interface and do something with the event. Let the one actor push an event into the handler which directs to the other actor and your are done. And they event dont need to know of each other and it does work for as much actors as you whish. You can even create 1 event for different classes different actors and so on. Usefull for example at mapchange. You push one event with the notice.. "changemap".. and every actor knows he need to stop moving and every subsystem knows that it does need to stop because of an mapchange and so on ...
It seems to be a bit overkill but it has alot of advantages and worth to use even at early stages. I made the misstake and started using it laterly and now i regret it.
Sorry for the bracing. It's not the regular java standart but more clear i think... Sorry for alot of varargs just like it at that point. Meight be confusing.
Literatur:
Game Coding Complete, Fourth Edition Chapter 11
public String commando(String username, String channel, String text) throws RemoteException{
String[] result = text.split(" ", 3);
if(result[0].equalsIgnoreCase("/join")){
channel = result[1];
setChannel(channel);
joinChannel(username, channel);
}
else if(result[0].equalsIgnoreCase("/leave")){
channel = result[1];
setChannel(channel);
leaveChannel(username, channel);
}
else if(result[0].equalsIgnoreCase("/whisper")){
for (int x=2; x<result.length; x++)
newPrivateMessage(username, result[1], result[x]);
}
else if(result[0].equalsIgnoreCase("/exit")){
System.exit(0);
}
else{
error(brukernavn, "Wrong!");
}
return tekst;
}
I need the error to be in red. This message ("Wrong!") goes to the user that wrote something like /dfdsfsd
I get the message up on the screen, but i cant get it in red. Some idea?
EDIT:
Interference:
public interface ChatFront extends Remote {
void error(String to, String message) throws RemoteException;
}
public interface Klient extends Remote {
void error(String to, String message) throws RemoteException;
}
In the server:
class ChatFrontImpl extends UnicastRemoteObject implements ChatFront {
private UserDAO b = new UserDAO();
private Hashtable<String, ArrayList<String>> chanel = new Hashtable<String, ArrayList<String>>();
private ArrayList<Klient> clients= new ArrayList<Client>();
public ChatFrontImpl() throws RemoteException {
}
public void error(String to, String message) throws RemoteException{
errorTo(to, message);
}
private void errorTo(String to, String message) throws RemoteException{
for(Client k: clients){
if(k.findName().equals(to)){
k.error(to, message);
}
}
}
I have edited some of the names (use Norwegian) so this can be a problem for u, but the program works. The only problem is that i cant get red color on the error message
EDIT 2: Forgot the GUI in client:
public class GUI extends javax.swing.JFrame {
GUILogikk gl = new GUILogikk(this);
public void error(String to, String message){
//chatFelt.setCaretColor(Color.RED);
chatFelt.append("" + message + "\n");
chatFelt.setCaretPosition(chatFelt.getText().length());
}
}
If you're using a console window, you'll have to find functions specific to your operating system to set text color. Those functions vary across operating systems, so either reconsider using a console window or address the issue for each system you plan to use your application on. If you're using something like Swing, you can inspect available text color properties associated with the component you're attempting to draw on (setSelectedTextColor(), etc). More here: JTextArea
If you simply want to draw on a Graphics object, you can do the following:
g.setColor(Color.RED);
g.drawString("WRONG!", 32, 32); // text, x, y