How to choose the block that the item can be placed on? - java

I would like to know how to choose the block that my TNT be placed on. Here is my code.
ItemStack tnt = new ItemStack(Material.TNT, 1);
As in give #p tnt 1 0 {PlaceOn:emerald_block}.
I am using Spigot for Minecraft 1.12 and Eclipse.

There is no way to do that via the Spigot API natively, you need to use NMS and NBT:
net.minecraft.server.v1_12_R1.ItemStack stack = CraftItemStack.asNMSCopy(tnt);
NBTTagList tags = (NBTTagList) stack.getTag().get("CanPlaceOn");
if (tags == null)
tags = new NBTTagList();
tags.add(new NBTTagString("minecraft:emerald_block"));
stack.getTag().set("CanPlaceOn", tags);
ItemStack toUse = CraftItemStack.asCraftMirror(stack);

Generally speaking if you can avoid using NMS you should, and there is a pretty easy way to do this. Whenever a block is placed by a player, a BlockPlaceEvent is called by the server. If you are unsure how they work, look here: http://bukkit.gamepedia.com/Event_API_Reference.
An example of how to handle this behavior is below:
public void onBlockPlace(BlockPlaceEvent e) {
if (e.getBlockPlaced().getType() == Material.TNT) {
Material belowType = e.getBlockPlaced().getRelative(BlockFace.DOWN).getType();
// your code here...
}
}
This code allows you to check if the block that is placed is TNT, then it retrieves the type of the block directly below it.
Hope this helps!!

Related

How do I get the block under the player?

I want to know which block is under the Player .And if the BLock is identical to another block (selected before), do something.
i tried something like this: (But I know it doesn't work at all). Thank you!
BlockPos PlayerIsStandingOn = player.getPosition().down();
Block PlayerIsStandingOnBlock = worldIn.getBlockState(PlayerIsStandingOn);
if (PlayerIsStandingOn == randomBlock) { }
You're close but getBlockState returns IBlockState not Block. You could do it like this:
BlockPos posBelow = player.getPosition().down();
IBlockState blockStateBelow = player.world.getBlockState(posBelow);
then you can either check if the block is a specific material like so, I think this is likely what you're after; this will return if the Material is not GROUND (dirt):
if(blockStateBelow.getMaterial() != Material.GROUND)
return;
//your logic here
Or you can do a comparison to check if two blocks are the same:
if(!Block.isEqualTo(blockStateBelow.getBlock(), <your other block>))
return;
//your logic here
And so on...
Edit
This answer was originally written for 1.12.2, it seems a few things have changed in 1.15.2
BlockPos posBelow = player.getPosition().down();
BlockState blockStateBelow = player.world.getBlockState(posBelow);
Block below = blockStateBelow.getBlock();
if(!below.equals(<your other block>))
return;

How to distinguish the mode (Java/JS/Android) the Processing sketch runs?

I write a multiplatform logic game, that will have to work in all modes: Java, JS and Android. I need to do some things different in all modes (especially, but not limited to, storage, for Java/Android I want to use load/saveTable and for JS - localStorage).
To do that I need to get the information, which is the mode the sketch runs. And I need to do this in runtime, just to avoid keeping different source for all platforms.
I was looking in the docs but found nothing in the topic. My Google research also led me to thoughts, that nobody even asked for that...
I was thinking about using try/catch to check some functions that exist in Java but not in JS, but this seems to be rather unelegant and whatismore I can not find the propper way for that.
What I have found is:
try {
PApplet a;
a = new PApplet();
mode = "JAVA";
}
catch(Throwable e) {
mode = "JS";
}
This distinguishes Java and JavaScript, but can not recognize Android...
So to summarize - what's the best way to distinguish, whether I run the sketch in JS or Java mode on runtime?
Ok, I have found quite nice way with try/catch:
String mode;
mode = "unknown";
try {
java.lang.Object a;
a = new java.lang.Object();
mode = "JAVA";
}
catch(Throwable e) {
mode = "JS";
}
This distinguishes JavaScript from the Java/Android but can not distinguish Android from Java. But since the differences are minimal this not causes significant problems with compatibility to me.
If someone knows the way to do this better - please post your answer!
I figured out how to detect Java vs. Android mode. Kind-of a hack:
import java.lang.reflect.*;
Method getInternalProcessingMethod(String methodName) {
/*
* Helper method that can be used to return
* an internal processing method by name
*/
Class cls = this.getClass();
try {
return cls.getMethod(methodName);
} catch (Exception e) {
return null;
}
}
boolean isAndroidMode() {
/*
* Determine if we're running in Android mode or not
*/
// What?
// In Android mode 'displayDensity' is a field and in Java
// mode 'displayDensity' is a method. This is a hack...but
// it works.
if (getInternalProcessingMethod("displayDensity") == null) {
return true;
}
return false;
}
And then you can use this to do something like what I use it for:
void settings() {
IS_ANDROID_MODE = isAndroidMode();
if (IS_ANDROID_MODE) {
println("Android mode detected");
fullScreen();
SAVE_LOCATION = "blah.json";
} else {
println("Java mode detected");
size(600, 1233);
SAVE_LOCATION = "data/blah.json";
}
}
Now I can have my test app run on my desktop in a small window but then run fullscreen with a different save file path on Android.

How to use R model in java to predict with multiple models?

I have this constructor:
public Revaluator(File model,PrintStream ps) {
modelFile=model;
rsession=Rsession.newInstanceTry(ps, null);
rsession.eval("library(e1071)");
rsession.load(modelFile);
}
i want to load a model and predict with it.
the problem that Rsession.newInstanceTry(ps, null); is always the same session, so if i load another model, like:
Revaluator re1=new Revaluator(new File("model1.RData"),System.out);
Revaluator re2=new Revaluator(new File("model2.RData"),System.out);
Both re1 and re2 using the same model, since the var name is model, so only the last one loaded.
the evaluate function:
public REXP evaluate(Object[] arr){
String expression=String.format("predict(model, c(%s))", J2Rarray(arr));
REXP ans=rsession.eval(expression);
return ans;
}
//J2Rarray just creates a string from the array like "1,2,true,'hello',false"
i need to load about 250 predictors, is there a way to get every instance of Rsession as a new separated R Session?
You haven't pasted all of your code in your question, so before trying the (complicated) way below, please rule out the simple causes and make sure that your fields modelFile and rsession are not declared static :-)
If they are not:
It seems that the way R sessions are created is OS dependent.
On Unix it relies on the multi-session ability of R itself, on Windows it starts with Port 6311 and checks if it is still free. If it's not, then the port is incremented and it checks again, if it's free and so on.
Maybe something goes wrong with checking free ports (which OS are you working on?).
You could try to configure the ports manually and explicitly start different local R servers like this:
Logger simpleLogger = new Logger() {
public void println(String string, Level level) {
if (level == Level.WARNING) {
p.print("! ");
} else if (level == Level.ERROR) {
p.print("!! ");
}
p.println(string);
}
public void close() {
p.close();
}
};
RserverConf serverConf = new RserverConf(null, staticPortCounter++, null, null, null);
Rdaemon server = new Rdaemon(serverConf, this);
server.start(null);
rsession = Rsession.newInstanceTry(serverConf);
If that does not work, please show more code of your Revaluator class and give details about which OS you are running on. Also, there should be several log outputs (at least if the log level is configured accordingly). Please paste the logged messages as well.
Maybe it could also help to get the source code of rsession from Google Code and use a debugger to set a breakpoint in Rsession.begin(). Maybe this can help figuring out what goes wrong.

JInput doesn't update / refresh

I'm using JInput for Gamepad control on Win7 64bit. I ran into a problem: Once I get the DefaultEnvironment the controller list doesn't get updated or refreshed.
for (Controller c : ControllerEnvironment.getDefaultEnvironment().getControllers()) {
if (c.getType() == Controller.Type.GAMEPAD) {
pluggedControllers.put(c);
}
}
So if a controller gets plugged in or out after i called ControllerEnvironment.getDefaultEnvironment() nothing changes. The list will still provide a dead controller and new controllers can't be added.
Currently I'm using this workaround which is quite ugly I think. Any ideas how I can make it work with out this hack:
if (System.getProperty("os.name").equals("Windows 7") &&
System.getProperty("os.arch").equals("amd64"))
try {
Class<?> clazz = Class.forName("net.java.games.input.DefaultControllerEnvironment");
Constructor<?> defaultConstructor = clazz.getDeclaredConstructor();
defaultConstructor.setAccessible(true); // set visibility to public
Field defaultEnvironementField = ControllerEnvironment.class.getDeclaredField("defaultEnvironment");
defaultEnvironementField.setAccessible(true);
defaultEnvironementField.set(ControllerEnvironment.getDefaultEnvironment(), defaultConstructor.newInstance());
} catch (Exception e) {
e.printStackTrace();
}
This has been asked for occasionally in the past. 2 ways to solve this.
1) Plug all your controllers in before you start the game. Not all existing games support this either.
2) Implement the interface interface that exists. I've asked a number of times for a volunteer to do the work, but whenever I do, this suddenly becomes less of a priority.
Get your controllers by calling
DirectAndRawInputEnvironmentPlugin directEnv = new DirectAndRawInputEnvironmentPlugin();
controllers = directEnv.getControllers();

Is it ok to handle a class metadata through reflection to ensure a DRY approach?

The title might seem unsettling, but let me explain.
I'm facing an interesting challenge, where I have a hierarchy of classes that have associated an object that stores metadata related to each one of its attributes (an int-valued enum with edit flags like UPDATED or NO_UPDATE).
The problem comes when merging two objects, because I dont want to check EVERY field on a class to see if it was updated and skip or apply the changes.
My idea: Reflection.
All the objects are behind an interface, so I could use IObject.class.getMethods() and iterate over that array in this fashion:
IClass class = //Instance of the first class;
IAnotherClass anotherClass = //Instance of the second class;
for(Method m : IObject.class.getMethods()) {
if(m.getName().startsWith("get")) {
try {
//Under this method (which is a getter) I cast it on
//both classes who implement interfaces that extend an
//interface that defines the getters to make them
//consistent and ensure I'll invoke the same methods.
String propertyClass = (String)m.invoke(class);
String propertyAnotherClass = (String)m.invoke(anotherClass);
if(propertyClass != propertyAnotherClass) {
//Update attribute and attribute status.
}
} catch (Exception e) {
}
}
}
Is there another way to implement this or should I stick to lengthy methods invoking attribute per attribute and doing the checks like that?. The objects are not going to change that much and the architecture is quite modular, so there is not much update involved if the fields change but having to change a method like that worries me a little.
EDIT 1: I'm posting a working code of what I have got so far. This code is a solution for me but, tough it works, I'm using it as a last resource not because I have time to spend but because I don't want to rediscover the wheel. If I use it, I'll make a static list with the methods so I only have to fetch that list once, considering the fact that AlexR pointed out.
private static void merge(IClazz from, IClazz to) {
Method methods[] = from.getClass().getDeclaredMethods();
for(Method m : methods) {
if(m.getName().startsWith("get") && !m.getName().equals("getMetadata")) {
try {
String commonMethodAnchor = m.getName().split("get")[1];
if(!m.getReturnType().cast(m.invoke(from)).equals(m.getReturnType().cast(m.invoke(to)))) {
String setterMethodName = "set" + commonMethodAnchor;
Method setter = IClazz.class.getDeclaredMethod(setterMethodName, m.getReturnType());
setter.invoke(to, m.getReturnType().cast(m.invoke(from)));
//Updating metadata
String metadataMethodName = "set" + commonMethodAnchor + "Status";
Method metadataUpdater = IClazzMetadata.class.getDeclaredMethod(metadataMethodName, int.class);
metadataUpdater.invoke(to.getMetadata(), 1);
}
} catch (Exception e) {
}
}
}
}
metadataUpdater sets the value to 1 just to simulate the "UPDATED" flag I'm using on the real case scenario.
EDIT 3: Thanks Juan, David and AlexR for your suggestions and directions! They really pointed me to consider things I did not consider at first (I'm upvoting all your answers because all of them helped me).
After adding what AlexR sugegsted and checking jDTO and Apache Commons (finding out that in the end the general concepts are quite similar) I've decided to stick to my code instead of using other tools, since it is working given the object hierarchy and metadata structure of the solution and there are no exceptions popping up so far. The code is the one on the 2nd edit and I've placed it on a helper class that did the trick in the end.
Apache Commons Bean Utils may resolve your problem: http://commons.apache.org/beanutils/
If you want to copy all properties, try to use copyProperties: http://commons.apache.org/beanutils/v1.8.3/apidocs/src-html/org/apache/commons/beanutils/BeanUtils.html#line.134
Look an example from: http://www.avajava.com/tutorials/lessons/how-do-i-copy-properties-from-one-bean-to-another.html
FromBean fromBean = new FromBean("fromBean", "fromBeanAProp", "fromBeanBProp");
ToBean toBean = new ToBean("toBean", "toBeanBProp", "toBeanCProp");
System.out.println(ToStringBuilder.reflectionToString(fromBean));
System.out.println(ToStringBuilder.reflectionToString(toBean));
try {
System.out.println("Copying properties from fromBean to toBean");
BeanUtils.copyProperties(toBean, fromBean);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
System.out.println(ToStringBuilder.reflectionToString(fromBean));
System.out.println(ToStringBuilder.reflectionToString(toBean));
I think the best approach would be using proxy objects, either dynamic proxies or cglib enhancers or something like it, so you decorate the getters and setters and you can keep track of the changes there.
Hope it helps.
Your approach is OK, but keep in mind that getMethod() is much slower than invoke(), so if your code is performance critical you will probably want to cache the Method objects.

Categories