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.
Related
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!!
I want to parse a String, which contains a number, using JDT to find out whether the contained number is inside the valid Range of one of the Primitive Types.
Let's say i got a float value like this as String "1.7976931348623157e350" and want to see whether it is still inside the allowed range for primitive type 'double'. (In this case it would not be inside the valid range, because the maximum exponent of double is 308).
I don't want to use the standard methods like : Double.parseDouble("1.7976931348623157e350"), because I'm afraid it might be too slow if I have a big amount of primitive types, which I want to check .
If you know the Eclipse development environment you will know that inside a normal java file, eclipse is able to tell whether a variable is out of range or not, by underlining it red, in the the case of 'out of range'. So basically i want to use this functionality. But as you can guess - it's easier said then done!
I have started experimenting with the ASTParser from this library: org.eclipse.jdt.core.dom
But I must admit I was not very successful here.
First i tried calling some of those vistor methods using methods like:
resolveBinding() , but they always only returned me "Null".
I have found some interesting class called ASTSyntaxErrorPropagator , but i'm not sure how this is used correctly. It seems to propagate parsing problems or something like that and gets it's information delivered by some thing class called CodeSnippetParsingUtil I assume. Anyways, these are only speculations.
Does anyone know how to use this ASTParser correctly?
I would be really thankful for some advice.
Here is some basic code-snipped which I tried to debug:
public class DatatypesParser {
public static void main(String[] args) {
ASTParser parser = ASTParser.newParser(AST.JLS4);
Map options = JavaCore.getOptions();
JavaCore.setComplianceOptions(JavaCore.VERSION_1_7, options);
String statement = new String("int i = " + Long.MAX_VALUE + ";");
parser.setSource(statement.toCharArray());
parser.setKind(ASTParser.K_STATEMENTS);
parser.setResolveBindings(true);
parser.setBindingsRecovery(true);
ASTNode ast = parser.createAST(null);
ast.accept(new ASTVisitor() {
#Override
public boolean visit(VariableDeclarationStatement node) {
CodeSnippetParsingUtil util = new CodeSnippetParsingUtil();
return true;
}
});
}
I don't want to use the standard methods like :
Double.parseDouble("1.7976931348623157e350"), because i'm afraid it
might be too slow if i have a big amount of primitive types, which i
want to check .
Under the hood JDT is actually using the standard methods of Double to parse the value, and quite a bit more - so you should always use the standard methods if performance is a concern.
Here is how the double gets parsed by JDT.
From org.eclipse.jdt.internal.compiler.ast.DoubleLiteral:
public void computeConstant() {
Double computedValue;
[...]
try {
computedValue = Double.valueOf(String.valueOf(this.source));
} catch (NumberFormatException e) {
[...]
return;
}
final double doubleValue = computedValue.doubleValue();
if (doubleValue > Double.MAX_VALUE) {
// error: the number is too large to represent
return;
}
[...]
}
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.
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();
I am writing a Java applet, and would like to know the best way to include it in a web page.
I'd like it to prompt the user to install JRE if she hasn't it already.
This feature should (ideally) work cross-browser on any OS Java runs on.
Another requirement is that the applet should not be loaded on page load, but after a user action, not to load the JVM on every page load.
I guess this is the official SUN way, but it uses document.write(), so I can't use it after the page has finished rendering.
I would recommend just using the applet tag. As Alex B comments, most browsers will prompt the user to install at that point if they don't have the JRE.
Even Sun recommends using the applet tag except on Intranets unless you are on an intranet. I imagine the logic here is that you can host the JRE download on an internal server, and use the embed & object tags to direct the download to that server.
I used to use the embed & object tags, but that ends up being a hassle due to the version numbers. Lets say you require Java 1.5. So you specify that in the object & embed tags to make sure the user will have to upgrade if they don't have 1.5. However, that's not really what you want, you want it to upgrade them to the very latest JVM. In any event, it was not the smartest behavior when I last played with it-- it's possible they have improved it now.
I agree with jwls, it is better to use an applet tag because using embed and object are very awkward to get right cross browser - to the point where a custom setup per browser is getting necessary.
However using the applet tag you need to beware of users on Microsoft's VM 1.1. When I tested in February they still accounted for 5% of Java versions. If these users visit a page where a later version is required they will see a horrible grey area.
The solution for this (after discussion on java.net) was to use a small applet which checks the Java version and redirects to a failure page if the target version isn't met. Here is my source:
JavaRedirectorApplet.java
import java.applet.Applet;
import java.net.URL;
/**
* Applet built for bytecode 1.1
*
* If applet is less than a set level redirects to a given page, else does nothing
*/
public class JavaRedirectorApplet extends Applet {
/** The required java version */
private final static String PARAM_REQUIRED_JAVA_VERSION = "REQUIRED_JAVA_VERSION";
/** The failure page */
private final static String PARAM_FAILURE_PAGE = "FAILURE_PAGE";
/**
* Initializes the applet
*/
public void init() {
// evaluate the required Java version
double requiredJavaVersion = -1;
String requiredJavaVersionString = getParameter(PARAM_REQUIRED_JAVA_VERSION);
if (requiredJavaVersionString != null) {
try {
requiredJavaVersion = Double.valueOf(requiredJavaVersionString).doubleValue();
} catch (Exception e) {
// ignored, caught below
}
}
if (requiredJavaVersion < 0) {
System.err.println(PARAM_REQUIRED_JAVA_VERSION + " not set or set incorrectly (must be set to a number greater than 0)");
return;
}
// get the failure page
URL failurePageURL = null;
String failurePageString = getParameter(PARAM_FAILURE_PAGE);
if (failurePageString != null) {
try {
failurePageURL = new URL(getCodeBase().getProtocol(),
getCodeBase().getHost(),
getCodeBase().getPort(),
failurePageString);
} catch (Exception e) {
// ignored, caught below
}
}
if (failurePageURL == null) {
System.err.println(PARAM_FAILURE_PAGE + " not set or set incorrectly (must be set to a valid path)");
return;
}
// check to see whether valid
if (!isValidVersion(requiredJavaVersion)) {
// not valid redirect self
getAppletContext().showDocument(failurePageURL, "_self");
}
// seems fine
}
/**
* Check the Java version against a required version
*
* #param versionRequired
* #return the verdict
*/
public static boolean isValidVersion(double versionRequired) {
try {
double javaVersion = Double.valueOf(System.getProperty("java.version").substring(0, 3)).doubleValue();
if (javaVersion < versionRequired) {
return false;
} else {
return true;
}
} catch (NumberFormatException e) {
return false;
}
}
}
Example HTML
<!-- place before the actual applet -->
<div style="display: none;">
<applet code="JavaRedirectorApplet" width="0" height="0">
<param name="REQUIRED_JAVA_VERSION" value="1.4"/>
<param name="FAILURE_PAGE" value="/failurePage.html" />
</applet>
</div>