Toggle AWT Canvas and Fullscreen

Yeah, I forgot about that one. You even get update support and so on… just like applets: always running the latest release automatically.

getdown seems interesting. I notice it is written in java. How do I deploy it without using it as an Applet or without Webstart and not as an exe?

I dont particularily wish to give the end user an exe file as that is so open to hacking and is the most dangerous present to give a hacker. If I were to provide an exe the user would have to download it everytime and I feel that would be so clunky compared with an applet. Especially considering an applet only requires its security certificate to be accepted on the first time.

its a really nice suggestion however looking at its documentation getdown isnt anything that my applet doesnt already do.

My applet is the downloader of my application. I just thought it would be odd to use a separate frame for the display when I have a perfectly good applet canvas. I never had a problem with other 3D engines.

The reason I initially chose the applet route is so I could ensure the user was verified before receiving any code and to ensure it was the applet that my website provided that users were using. At every level I am making it so difficult for a hacker to have any purchase.

I believe a hacker would need to hack the JVM to interfer with my application.

regards

@Penny Did you try jme3_est_swing in your context (applet + fullscreen) ?

David, I havent as yet. I believe I have overlooked the suggestion in error to which I appologise. I will investigate and report my findings in the next day or two.
Regards

Hi David,

I have attempted to test your suggestion. However, I am having difficulty in locating…

import jme3_ext_swing.Function;
import jme3_ext_swing.ImagePanel;
import jme3_ext_swing.JmeForImagePanel;
import samples.CameraDriverAppState;
import samples.CameraDriverInput;
import samples.HelloPicking;

I have set my lib path to…

D:/Program Files/jmonkeyplatform/jmonkeyplatform/libs/*

in a hope to capture these in the libs provided by JME but also didnt work.

I would appreciate your assistance on this very much. Maybe if I knew which jars they were located in I could specifically path these.
Regards

Do you use jmonkeyplatform SDK or another build tool (gradle, maven,…) ?

The jar (binary) of jme3_ext_swing can be download from Package jme3_ext_swing - davidb
Other dependencies are part of jme3 libs : jme3-core, jme3-desktop and jme3-lwjgl (available as netbeans libraries in SDK or as maven artifact from http://updates.jmonkeyengine.org/maven/ )

The samples’s classes aren’t included in any jar, copy/paste source from jme3_ext_swing/src/test/java/samples at master · davidB/jme3_ext_swing · GitHub .

If you prefer to build jme3_ext_swing yourself , you need to install gradle 2.1+ and :

git clone https://github.com/davidB/jme3_ext_swing.git
cd jme3_ext_swing
gradle assemble

Every 3 major java IDE have a plugin to import a gradle project

I hope, it helps you

Ok, thank you for that. I have successfully compiled my test project.

I dont use any SDK sorry. I am very happy writing code using notepad and javac to compile. I have only been programming Java for about 15 years so I am a bit new to this compared to other languages that I have used.

I just need to find out why I am getting this…

ERROR [Thread-14]:Sun Feb 15 13:25:44 GMT 2015
Thread=Thread[Thread-14,4,****-threadGroup]
java.lang.NoClassDefFoundError: com/jme3/app/SimpleApplication
test.SwingJAppletTest.createGUI(80)
test.SwingJAppletTest.access$100(19)
test.SwingJAppletTest$Runner.run(53)

When my html is this…

<html>
<body>
<object id=size2 class=play2 type="application/x-java-applet" width="900" height="675">
<param name="code" value="test/SwingJAppletTest.class" />
<param name="archive" value="test.jar,jME3-core.jar,jME3-desktop.jar,jME3-lwjgl.jar" />
</object>
</body>
</html>

and all the appropriate jars are located in the same directory.

Im sure I will work it out :smile:

Sorry, I can’t help you to setup your build to generate : or with the right configuration : not enough informations (log, java plugin version, url, directory layout,…). But from what I see, you doesn’t have some transitive dependency like the jar with native library. I guess in your log you should have previous error about classloading,…

Also, I guess you already have a working applet with jME before you ask : “how to do fullscreen ?”.

Note: tag is only for IE (see Using applet, object and embed Tags )

IMO, using only javac + notepad is like trying to do run 100 miles or km with rollers (vs with a car). It’s ok for learning, or making quick proto but pain in a ass, when you have to deal with dependencies lib, multi-project,…

No problems. I might port this test app to my class loader to ensure all the classes are present. Just not sure why the standard class loader isnt picking up the jars.

I appreciate what you are saying about my methods. This is my home project to which I use to satisfy my intregue. For me using an SDK is cheating however I appreciate that some individuals may be commercially driven and wish to blaze over the internal workings.

Many Thanks for your help
Regards

“cheating” what ?? it’s not a contest, why it’s more cheating than using notepad+javac vs writing asm (native or for jvm) with a hexeditor. My goal is to make lib, game not to waste time using silex vs lighter. It’s a matter of taste. And I contribute some plugins + issue to maven, gradle, netbeans, eclipse to understand enough how they work and to trust them to help reach my goals quicker. The 4 projects are free to use and opensource. And you’re free to not use them :smiley:

Anyways tell me, if you have other issues with jme3_ext_swing, contribution, issue (on github),… are welcome. (I have to do some doc, it’s maybe my less documented project).

As I suspected it was a security certificate mismatch. Once I has signed all the JME jars with my certificate the applet ran. Unfortunately, when I went to fullscreen the screen remained blank just like my previous attempts :frowning:

I click on the blank screen and it returns to the browser applet where some cubes are rendered on a green backdrop as prior to the full screen switch.

I notice there were only 30 frames per second. I had a brief look to see if a limiter has been placed but I couldnt see one. It’s quite a drop from the 5000 fps I get using the display context. Writing the off screen buffer to the awt panel seems quite expensive.

What a shame! I was hoping this would be my answer.

with the appletviewer (no security, dll/so issue) I switch to fullscreen and back to normal.

My code includes a limiter, else you’ll waste too many CPU to copy to Image, 30/60 fps is enough

settings.setFrameRate(Math.max(1, Math.min(60, framerate)));

called from

Can you share the project, a minimal sample ? Then I can take a look.

Hi, I thought the fps might have been limited.

I have been working on a solution that actually toggles between a canvas context and a display context by creating a new SimpleApplication each time. The reason for this is that it seems lwjgl is locked into the context of the SimpleApplication and the only way to release it is to call stop() on the SimpleApplication. The documentation states that once stop() has been called it can no longer be used, I have tried restarting it without success, so the only remaining option is to create a new SimpleApplication each time.

Initially this seems to work very well. My test app starts with a frame containing a canvas. When I click the canvas the current SimpleApplication shuts down and a new one is created and the full screen is displayed. The problem which I am currently experiencing is that when I try to go back to using the canvas context it seems the JME platform is stuck in fullscreen mode despite the AppSettings full screen parameter being false.

I wonder if you or anyone with more experience with JME can provide me with a solution to this.

Please find below the code to my test app…

test/test.java

package test;
import com.jme3.app.SimpleApplication;
import com.jme3.asset.AssetManager;
import com.jme3.system.JmeSystem;
import com.jme3.system.NanoTimer;
import com.jme3.system.Timer;
import com.jme3.renderer.queue.RenderQueue.Bucket;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial.CullHint;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Box;
public class Test
 {
 private boolean initialised=false,fullscreen=false,changing=false;
 private Timer timer;
 private Node rootNode,guiNode;
 private SimpleApplication currentApplication;
 private InputProcessor inputProcessor;
 private TestFrame tf;
 public static void main(String[] args)
  {
  Test t=new Test();
  }
 private Test()
  {
  timer=new NanoTimer();
  rootNode=new Node("Root Node");
  guiNode=new Node("Gui Node");
  guiNode.setQueueBucket(Bucket.Gui);
  guiNode.setCullHint(CullHint.Never);
  inputProcessor=new InputProcessor(this);
  tf=new TestFrame();
  createApplication(fullscreen);
  }
 public void createApplication(boolean _fullscreen)
  {
  if(_fullscreen)
   {
   currentApplication=new CanvasScreen(this);
   currentApplication.start();
   }else{
   currentApplication=new CanvasApplet(this);
   currentApplication.start();
   tf.setCanvas(((CanvasApplet)currentApplication).getCanvas());
   tf.validate();
   }
  }
 public Timer getTimer()
  {
  return timer;
  }
 public Node getRoot()
  {
  return rootNode;
  }
 public Node getGUI()
  {
  return guiNode;
  }
 public InputProcessor getInputProcessor()
  {
  return inputProcessor;
  }
 public boolean getFullscreen()
  {
  return fullscreen;
  }
 public void setFullscreen(boolean _fullscreen)
  {
  if(fullscreen==_fullscreen)return;
  fullscreen=_fullscreen;
  changing=true;
  currentApplication.stop();
  }
 public void simpleInitApp()
  {
  if(initialised)return;
  initialised=true;
  Box b=new Box(1,1,1);
  Geometry geom=new Geometry("Box",b);
  Material mat=new Material(currentApplication.getAssetManager(),"Common/MatDefs/Misc/Unshaded.j3md");
  mat.setColor("Color",ColorRGBA.Blue);
  geom.setMaterial(mat);
  rootNode.attachChild(geom);
  }
 public void destroyed()
  {
  if(!changing)return;
  changing=false;
  createApplication(fullscreen);
  }
 }

test/TestFrame.java

package test;
import java.awt.Canvas;
import java.awt.Frame;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class TestFrame extends Frame
 {
 private static final long serialVersionUID=1;
 private Canvas canvas=null;
 public TestFrame()
  {
  super("TestFrame");
  setBounds(10,10,600,500);
  setVisible(true);
  addWindowListener(new WindowAdapter(){public void windowClosing(WindowEvent _e){System.exit(0);}});
  }
 public void setCanvas(Canvas _canvas)
  {
  if(canvas==_canvas)return;
  if(canvas!=null)remove(canvas);
  canvas=_canvas;
  if(canvas!=null)add(canvas);
  }
 }

test/InputProcessor.java

package test;
import com.jme3.input.InputManager;
import com.jme3.input.RawInputListener;
import com.jme3.input.event.JoyAxisEvent;
import com.jme3.input.event.JoyButtonEvent;
import com.jme3.input.event.KeyInputEvent;
import com.jme3.input.event.MouseButtonEvent;
import com.jme3.input.event.MouseMotionEvent;
import com.jme3.input.event.TouchEvent;
public class InputProcessor implements RawInputListener
 {
 private Test test;
 public InputProcessor(Test _test)
  {
  test=_test;
  }
 public void beginInput()
  {}
 public void endInput()
  {}
 public void onJoyAxisEvent(JoyAxisEvent _e)
  {}
 public void onJoyButtonEvent(JoyButtonEvent _e)
  {}
 public void onKeyEvent(KeyInputEvent _e)
  {}
 public void onMouseButtonEvent(MouseButtonEvent _e)
  {
  if(_e.getButtonIndex()==0&&_e.isReleased())test.setFullscreen(!test.getFullscreen());
  }
 public void onMouseMotionEvent(MouseMotionEvent _e)
  {}
 public void onTouchEvent(TouchEvent _e)
  {}
 }

test/CanvasApplet.java

package test;
import com.jme3.app.SimpleApplication;
import com.jme3.app.StatsAppState;
import com.jme3.app.FlyCamAppState;
import com.jme3.input.InputManager;
import com.jme3.system.AppSettings;
import com.jme3.system.JmeContext;
import com.jme3.system.JmeCanvasContext;
import java.awt.Canvas;
public class CanvasApplet extends SimpleApplication
 {
 private Test test;
 public CanvasApplet(Test _test)
  {
  super(new StatsAppState());
  test=_test;
  setTimer(test.getTimer());
  AppSettings settings=new AppSettings(true);
  settings.setFullscreen(false);
  setSettings(settings);
  setShowSettings(false);
  }
 public void simpleInitApp()
  {
  viewPort.detachScene(rootNode);
  rootNode=test.getRoot();
  viewPort.attachScene(rootNode);
  guiViewPort.detachScene(guiNode);
  guiNode=test.getGUI();
  guiViewPort.attachScene(guiNode);
  InputManager inputManager=getInputManager();
  inputManager.clearMappings();
  inputManager.clearRawInputListeners();
  inputManager.addRawInputListener(test.getInputProcessor());
  inputManager.setCursorVisible(true);
  stateManager.detach(stateManager.getState(FlyCamAppState.class));
  test.simpleInitApp();
  }
 public void start()
  {
  start(JmeContext.Type.Canvas);
  }
 public Canvas getCanvas()
  {
  return ((JmeCanvasContext)getContext()).getCanvas();
  }
 public void destroy()
  {
  super.destroy();
  test.destroyed();
  }
 }

test/CanvasScreen.java

package test;
import com.jme3.app.SimpleApplication;
import com.jme3.app.StatsAppState;
import com.jme3.app.FlyCamAppState;
import com.jme3.input.InputManager;
import com.jme3.system.AppSettings;
import com.jme3.system.JmeContext;
public class CanvasScreen extends SimpleApplication
 {
 private Test test;
 public CanvasScreen(Test _test)
  {
  super(new StatsAppState());
  test=_test;
  setTimer(test.getTimer());
  AppSettings settings=new AppSettings(true);
  settings.setFullscreen(true);
  setSettings(settings);
  setShowSettings(false);
  }
 public void simpleInitApp()
  {
  viewPort.detachScene(rootNode);
  rootNode=test.getRoot();
  viewPort.attachScene(rootNode);
  guiViewPort.detachScene(guiNode);
  guiNode=test.getGUI();
  guiViewPort.attachScene(guiNode);
  InputManager inputManager=getInputManager();
  inputManager.clearMappings();
  inputManager.clearRawInputListeners();
  inputManager.addRawInputListener(test.getInputProcessor());
  inputManager.setCursorVisible(true);
  stateManager.detach(stateManager.getState(FlyCamAppState.class));
  test.simpleInitApp();
  }
 public void start()
  {
  start(JmeContext.Type.Display);
  }
 public void destroy()
  {
  super.destroy();
  test.destroyed();
  }
 }

Regards

Have you tried what I mentioned in my earlier post?

Just in general,
if you actually want users to play your game an applet is in theory a nice choice,
in practice most users current days have hopefully their java plug-ins at least on click to play if not completely disabled.

As for getdown or similar solutions. They can be build as a fat jar, so they only require an installed java. similar to the applet which needs one as well.

I would at least provide a alternative way as there are often random problems with applets and webstart.
Eg on my system there simply is no java plugin for my browser at all.

Momoko_Fan - That worked, thank you very much and I dont even have to do any fandangery with SimpleApplication. Of course I note your comment about “its likely to blow up” and use at your own risk but it is the first method to work for me. I will just have to see how stable it is as time goes by. many thanks!!

Empire_Phoenix - I agree with your statements. The challenge for me is to ensure my project runs without being interfered with, to which I have configured applet to work as a very nice answer. If I were to deploy an exe to circumvent the issues with applet, it would then be subject to hacking unless a new copy of the exe was installed every time and that seems too clunky and unacceptable for the user. I will have to think about this to see if there are any viable options. If you have any suggestions on how I can answer my requirements with alternatives to applet I am very interested to listen :smile:

Regards

To protect the user or to protect yourself? The former is ok because even imperfect solutions have some effect. The latter is impossible and so expending too much effort on it seems unwise… if it’s a client-server app and you are trying to prevent cheating, for example, it cannot be controlled at the client.

If your protecting the user… ok, I guess… though if hackers are modifying exe’s on that user’s system then they have worse problems than your game.

If you are protecting yourself from the user then that’s virtually impossible. Applet or not, they have the jars and they can potentially run them as non-applet… not to mention a whole host of other more nefarious methods.

I agree with your comments. However, I believe making it as difficult as possible limits vulnerabilities to the most skilled and the most determined.

Without giving too much away, they do not have access to my jars because they are encrypted.

The only unencrypted jar the user receives is the startup applet which a fresh copy is provided everytime ensuring it is not interfered with. The startup applet does not contain the details on how to decrypt the additional jars.

To access this encrypting method someone would be required to hack the JVM to which I believe oracle has made this extremely challenging.

It is my belief that someone with the time and the skill to meet these challenges would have far better things to do with their time than to hack my project.

I’m not saying it is full proof, I am saying it is as challenging as possible.

I agree that the only sure way to limit interference is to ensure any messages received by the server are within expected tolerances.

Regards

So your jars are encrypted in a way that not even your application can decrypt them? Because if it can then somebody who can modify exe files on the users computer can, too. Or anyone who gets its hands on the jars for that matter. I think if it would be even easier to access your code then you’d get a better idea of what the actual “vulnerabilities” are and put countermeasures that actually work. If you just think that your stuff is “below the radar” then why worry at all?

Speaking from expirience in bot programming (yeah I found that i prefer to program bots than play mmos)

The process is fucking simple.

Step one obtain the applets jar
Step to wrap a own java programm around that is calling the programms main/applets init.
Inject a custom class loader in bootstrap that simple writes all loaded classes out in plaintext.

Play the game a bit and you have 90% of all code without further work.

My suggestion for this is, to make taks/problems that are impossible for bots to solve in an efficient way. Speech&image recognition as well as interpreting natural language are good choices. Anything with fuzzy input works usually.

Hint of warning, make sure your challenge for protections is not seen as one, else you will get people doing it just for th challenge. Make it boring so that the people with enough knowledge have no motivation to do it.

Ps. Professional version: Get openjdk source add writing out of encrypted classes compile and run. (aka why hack oracles if you have compatible source?)

Pss: The most working thing so far is simple obfuscation. It just makes it annoying to work with your code, without making it a real challenge, causing many people to loose interest.