I'm trying some alterations in minecraft src. I'm trying to override a method in a class so I don't have to edit the original class.
In the regular class I want to alter this method:
public void sendChatMessage(String par1Str)
{
this.sendQueue.addToSendQueue(new Packet3Chat(par1Str));
}
So in my subclass I have this code:
package cobalt.gui;
import cobalt.hacks.*;
import net.minecraft.client.Minecraft;
import net.minecraft.src.EntityClientPlayerMP;
import net.minecraft.src.NetClientHandler;
import net.minecraft.src.Session;
import net.minecraft.src.World;
public class Console extends EntityClientPlayerMP {
public Console(Minecraft par1Minecraft, World par2World,
Session par3Session, NetClientHandler par4NetClientHandler) {
super(par1Minecraft, par2World, par3Session, par4NetClientHandler);
}
#Override
public void sendChatMessage(String par1Str) {
if (par1Str.startsWith(".help")) {
//Do stuff
return;
}
}
}
From my understanding, anytime a method is called, it should be "redirected" for the subclass to handle? (Tell me if I'm wrong ha)
The if statement does work correctly if I modify the original class.
Thank you very much!
This would only work if somehow the rest of the minecraft code starts using your class, Console, where it meant to use EntityClientPlayerMP. Without that, your function will not be called.
If you want to change the behavior of the game, the easiest way would be to change EntityClientPlayerMP itself. If you want to use the modified class Console elsewhere in the code, then what you have done is fine.
It depends on the actual object type. If the object is of type Console e.g. EntityClientPlayerMP obj = new Console(..) and obj.sendChatMessage(..) it'll work. But if the object itself is of type EntityClientPlayerMP like new EntityClientPlayerMP(..) It won't work
Related
Maybe what I am trying to do is not worthwhile, it sure feels that way after spending many days on it.
I have A Base Class shown here:
package jimmy.kilmer.com;
import java.awt.Color;
import jarPackageImports.AI;
import jarPackageImports.MovementAction;
import jarPackageImports.Info;
import jarPackageImports.PlayerAction;
public class GameAI extends AI {
public gameAI(Info info) {
super(info);
setJerseyNumber(32);
}
public Color getColor() {
return Color.RED;
}
public String getName() {
return "Usain Bolt";
}
public PlayerAction update() {
// TODO game movement actions
// all available methods not listed here...
info.getVelocity();
info.getX();
info.getY();
MovementAction steeringBehavior = null;
return steeringBehavior;
}
//basically used for testing setup
public int[][] populateAllPossibleNodes() {
int[][] allPossibleNodes = new int[screenWidth/20][screenHeight/20];
return allPossibleNodes;
}
}
I have been given a jar, that sets up the game environment. It uses reflection for the setup. I am not familiar with reflection, unfortunately, as I am more beginner level.
I have read a lot about TDD, and am convinced that can help me stay orderly, and code in a disciplined way. I have some say that TDD is not really useful for Game development, which the arguments may be true, in regard to making an "enjoyable game." But, from a purely coding standpoint, I remain steadfast in my believe that TDD is the way to go. But, that remains to be seen, since it is still theoretical. I would like to try it.
I have installed Junit 5, and have done many tutorials, but it's all pretty basic examples. My particular test case uses reflection, super classes, derived classes, dynamic data. My head is spinning.
My goal is just to get setup such that I can start doing some Test driven development.
Here is my Junit test class:
package jimmy.kilmer.com;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import jarPackageImports.Info;
class GameAITest {
private GameAITest AIObject;
private jarPackageImports.Info info;
#BeforeEach
void setUp() throws Exception {
AIObject = new GameAITest(info);
#AfterEach
void tearDown() throws Exception {
}
#Test
void testPopulateAllPossibleNodes() {
// 1. given/arrange
int[][] array1 = new int[80][65];
// 2. when/act
int[][] array2 = AIObject.populateAllPossibleNodes();
// 3. then/assert
assertArrayEquals(array1, array2);
}
}
That is my best stab so far, but it still get a compile error. Specifically:
java.lang.NullPointerException:Cannot invoke "jarPackageImports.Info.getScene()" because "this.info" is null
In summation:
maybe everything I am trying is rubbish?
Do I need to use dynamic junit testing? I would have to read up on that.
Do I need to mock (use Mockito?) to instantiate an object to test? I would need to read up on that as well.
Is it possible to instantiate an object from GameAI? Do I need to/how would I use relection to do that? class.getConstructors()? And, I would have to read up on that.
thanks in advance.
Using EasyMock 3.2. In order to unit test an UI, I have to mock some dependencies. One of them is Page. Base class for UI tests looks like this:
abstract class AbstractUiTest {
#Before
public function setUpUiDependencies() {
Page page = createNiceMock(Page.class);
Ui.setCurrentPage(page);
}
}
Most of the time I don't use the page explicity, it's just there not to throw NullPointerException when e.g. Ui calls getPage().setTitle("sth") etc.
However, in a few tests I want to explicity check if something has happend with the page, e.g.:
public class SomeTest extends AbstractUiTest {
#Test
public void testNotification() {
// do something with UI that should cause notification
assertNotificationHasBeenShown();
}
private void assertNotificationHasBeenShown() {
Page page = Ui.getCurrentPage(); // this is my nice mock
// HERE: verify somehow, that page.showNotification() has been called
}
}
How to implement the assertion method? I would really want to implement it without recording behavior to the page, replaying and verifying it. My problem is a bit more complicated, but you should get the point.
EDIT: I think that perhaps this is not really needed, since simply using replay and verify should check that the expected methods were actually called. But you said you want to do this without replaying and verifying. Can you explain why you have that requirement?
I think that you can use andAnswer and an IAnswer. You don't mention what the return value of page.showNotification() is. Assuming it returns a String, you could do this:
import static org.easymock.EasyMock.expect;
import static org.junit.Assert.assertTrue;
import java.util.concurrent.atomic.AtomicBoolean;
import org.easymock.IAnswer;
import org.junit.Ignore;
import org.junit.Test;
public class SomeTest extends AbstractUiTest {
#Test
public void shouldCallShowNotification() {
final AtomicBoolean showNotificationCalled = new AtomicBoolean();
expect(page.showNotification()).andAnswer(new IAnswer<String>() {
#Override
public String answer() {
showNotificationCalled.set(true);
return "";
}
});
replay(page);
Ui.getCurrentPage();
verify(page);
assertTrue("showNotification not called", showNotificationCalled.get());
}
}
If showNotification returns void, I believe you would need to do this:
import static org.easymock.EasyMock.expectLastCall;
import static org.junit.Assert.assertTrue;
import java.util.concurrent.atomic.AtomicBoolean;
import org.easymock.IAnswer;
import org.junit.Ignore;
import org.junit.Test;
public class SomeTest extends AbstractUiTest {
#Test
public void shouldCallShowNotification() {
final AtomicBoolean showNotificationCalled = new AtomicBoolean();
page.showNotification();
expectLastCall().andAnswer(new IAnswer<Void>() {
#Override
public Void answer() {
showNotificationCalled.set(true);
return null;
}
});
replay(page);
Ui.getCurrentPage();
verify(page);
assertTrue("showNotification not called", showNotificationCalled.get());
}
}
Note: I've used an AtomicBoolean to record whether the method was called. You could also use a boolean array of a single element, or your own mutable object. I used AtomicBoolean not for its concurrency properties, but simply because it is a handy mutable boolean object that is already present in the Java standard libraries.
The other thing that I have done to verify that a method was being called is to not use a mock at all, but to create an instance of Page as an anonymous inner class and override the showNotification method, and record somewhere that the call occurred.
Use a nice mock in the tests where you don't care what happens to page and a normal mock in those tests where you want to test something explicit - and use expect, verify etc. I.e. have two variables in your setup method: nicePage (acts as a stub) and mockPage (acts as a mock)
i am on the creation of an app in android. its a calculator app. the main activity is where the user could input the equation, and the second activity is where the user can add/edit/delete variables. so i made a new class in another file named Global.java. then i extended it to application, imported everything i need, made s private string, made some public functions, edited the manifest, and initialized it right on my main activity. everything works fine while im only using a string to be passed by the functions but when i started adding what i need, an ArrayList, and made some functions so i could access the list then run it, the app closes. i think its because the arraylist is not allowed to be passed to different classes? am i right or am i just missing something?
please dont downvote my post if i didn't post something needed. i am using aide so there is no log output. code:
Global.java
...
import android.app.*;
import java.util.*;
public class Global extends Application
{
private String s;
public static ArrayList<String> sList;
public String getS() {
return s;
}
public void setS(String ss) {
s=ss;
}
public void add() {
sList.add(s);
}
}
MainActivity.java
...
String s;
...
global=(Global)getApplicationContext();
...
global.setS("jian"); //this one works
global.sList.add("jian"); // this one dont
...
Are you sure you initialized sList, like this:
sList = new ArrayList<String>();
If you didn't, you might want to change its declaration to include this initialization.
public static ArrayList<String> sList = new ArrayList<String>();
Just do
global.add("jian");
since you have an add function to take care of the addition of item to arraylist.
Also, try with this:
public void add(String ss) {
sList.add(ss);
}
You are not instantiating your arraylist.
public static ArrayList<String> sList = new Arraylist<String>();
Also you should read beginner tutorials on Java and android, using a public extension of application like this is a bad idea and you can get log outputs from different apps if Aide doesn't provide that, search play store
I have a java we application that is working with velocity. I get two variables in the first page via url that I extract using ureq.getParameter() method. One of the other classes that has a velocity container and I need to send one of the variables from the url to this velocity container. I tried creating an instance of the first class in the second class and using getVariable name method to do that but it did not work. Can someone tell me how I can do this?
Class 1:
package org.olat.dispatcher;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.olat.core.gui.UserRequest;
public class RemoteLoginformDispatcher implements Dispatcher {
private static final String PARAM_newUrl = "ret";
private static String newURL;
#Override
public void execute(
final HttpServletRequest request,
final HttpServletResponse response,
final String uriPrefix) {
UserRequest ureq = null;
try {
ureq = new UserRequest(uriPrefix, request, response);
newURL = ureq.getParameter(PARAM_newUrl);
} catch () {
}
}
public String getURL(){
return newURL;
}
}
Class 2:
public class BaseChiefController extends DefaultChiefController implements ContentableChiefController {
//Velocity container mainvc created here. It interacts with a html file. Removed the code that would not really matter
//mainvc.contextPut("newURL", "something");
//The below statement works. When I try with something, the something appears in the html file.
mainvc.contextPut("newURL", myLogin.getURL());
}
To create an instance of another class, simply create a "public CLASSNAME" method, and inside define all class variables with the "this" modfier. Then, call out the function you wish to use from that method, and when you want to use the class, just do "new CLASSNAME(args);"
Although, I am not really sure I am understanding your question.
Maybe this is your answer. You can use variables from one class to another class by making the variable static, then doing "CLASSNAME.VARIABLENAME = WHATEVER".
EDITED:
Okay, so as far as I can tell, you are using a method to return a static value from the class, which is much slower than just doing "newURL", RemoteLoginformDispatcher.newURL);.
Why not try this, as it is probably faster, and it should always work if newURL is defined. Otherwise, you have a different problem, and newURL is not being defined. If this is the case, try printing the caught Exception.
I am building a user interface in netBeans (coding by hand, more flexible) with multiple toolbars.
What I am trying to do is create an actionListener for each button. I am retrieving names of the functions from XML and parse them to string. I will write implementations for those functions in a separate class, but my problem is the following:
How do I make the link between the function name and the string containing it's name?
Example: String is Open(), function will be Open(someParameter) and in the definitions class there will be static void Open(param).
First of all, consider my comment about your idea of dynamic button behavior resolved from strings being a wrong approach. However if you still need exactly what you asked, what you need is Reflection API.
Here's an example:
Class c = SomeClassWithMethods.class;
Method m = c.getMethod("someMethodName", String.class, Integer.class, Integer.TYPE);
m.invoke(baseObjectFromWhichToCallTheMethod, "stringParam", 10, 5);
Added:
Another option, which is a little bit prettier than reflection, but still a messy design, would be to use a map to link those Strings to methods. The code is a bit longer, but from the Java perspective it is much better than using reflection for your task (unless you have some specific requirement of which I'm not aware). This is how it would work:
//Interface whose instances will bind strings to methods
interface ButtonClickHandler {
void onClick();
}
class SomeClassYouNeed {
//One of the methods that will be bound to "onButtonOneClick()"
public void onButtonOneClick() {
log.info("ButtonOneClick method is called");
}
public void onButtonTwoClick() {
log.info("ButtonTwoClick method is called");
}
//Map that will hold your links
private static Map<String, ButtonClickHandler> buttonActionMap;
//Static constructor to initialize the map
static {
buttonActionMap = new Map<String, ButtonClickHandler>();
buttonActionMap.put("onButtonOneClick()",new ButtonClickHandler() {
#Override
public void onClick() {
onButtonOneClick();
}
});
buttonActionMap.put("onButtonTwoClick()",new ButtonClickHandler() {
#Override
public void onClick() {
onButtonTwoClick();
}
});
}
public void callByName(String methodName) {
final ButtonClickHandler handler = buttonActionMap.get(methodName);
if (handler == null) {
throw new IllegalArgumentException("No handler found by name: "+methodName);
}
handler.onClick();
}
}
After you call callByName("onButtonTwoClick()") it will fetch the respective instance of ButtonClickHandler which will use the static method onButtonTwoClick() to process the click of the button.
It seems to me that you are looking for the equivalent of JS "eval" function in Java. This might help. Nevertheless it is generally not a good idea as #Max stated, you might want to rethink your design.
If i have understood your question correctly you are trying to generate your code files based on some strings taken from a XML file. I can suggest you this library to generate your codes.
For tutorials you can visit this link.
You may even use the Java Reflection API. Here is a link for the tutorial.
Its upto you, that which of the above two you use.