So I'm trying to make a billing system in which I want to print a receipt.I was able to do it with some code that I found online,but the font size is too big to print in the 58mm wide paper.I'm not able to adjust the font size.Any kind of help with this issue will be highly appreciated.Thank You.
Here is The Code :
public class PrinterService implements Printable {
public List<String> getPrinters(){
DocFlavor flavor = DocFlavor.BYTE_ARRAY.AUTOSENSE;
PrintRequestAttributeSet pras = new HashPrintRequestAttributeSet();
PrintService printServices[] = PrintServiceLookup.lookupPrintServices(
flavor, pras);
List<String> printerList = new ArrayList<String>();
for(PrintService printerService: printServices){
printerList.add( printerService.getName());
}
return printerList;
}
#Override
public int print(Graphics g, PageFormat pf, int page)
throws PrinterException {
if (page > 0) { /* We have only one page, and 'page' is zero-based */
return NO_SUCH_PAGE;
}
/*
* User (0,0) is typically outside the imageable area, so we must
* translate by the X and Y values in the PageFormat to avoid clipping
*/
Graphics2D g2d = (Graphics2D) g;
g2d.translate(pf.getImageableX(), pf.getImageableY());
/* Now we perform our rendering */
g.setFont(new Font("Roman", 0, 8));
g.drawString("Hello world !", 0, 10);
return PAGE_EXISTS;
}
public void printString(String printerName, String text) {
// find the printService of name printerName
DocFlavor flavor = DocFlavor.BYTE_ARRAY.AUTOSENSE;
PrintRequestAttributeSet pras = new HashPrintRequestAttributeSet();
PrintService printService[] = PrintServiceLookup.lookupPrintServices(
flavor, pras);
PrintService service = findPrintService(printerName, printService);
DocPrintJob job = service.createPrintJob();
try {
byte[] bytes;
// important for umlaut chars
bytes = text.getBytes("CP437");
Doc doc = new SimpleDoc(bytes, flavor, null);
job.print(doc, null);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void printBytes(String printerName, byte[] bytes) {
DocFlavor flavor = DocFlavor.BYTE_ARRAY.AUTOSENSE;
PrintRequestAttributeSet pras = new HashPrintRequestAttributeSet();
PrintService printService[] = PrintServiceLookup.lookupPrintServices(
flavor, pras);
PrintService service = findPrintService(printerName, printService);
DocPrintJob job = service.createPrintJob();
try {
Doc doc = new SimpleDoc(bytes, flavor, null);
job.print(doc, null);
} catch (Exception e) {
e.printStackTrace();
}
}
private PrintService findPrintService(String printerName,
PrintService[] services) {
for (PrintService service : services) {
if (service.getName().equalsIgnoreCase(printerName)) {
return service;
}
}
return null;
}
}
#FXML
public void printit(ActionEvent actionEvent)
{
PrinterService printerService = new PrinterService();
System.out.println(printerService.getPrinters());
//print some stuff
printerService.printString("POS-58-Series", area.getText());
}
I have a desktop app which is downloading 1 or more small files (jpg with less than 400KB in size and no more than 20 at a time) simultaneously using a CustomWebClient object and calling OpenReadAsync(). The download process is working just fine if there is no problem in the process. I want to limit the response to a certain time (15 sec) so I have introduced a timeOut handling which is Aborting the request. Even the timeout is working and after that my “OpenReadCompletedEventHandler” method is receiving System.Net.WebException: The request was aborted: The request was canceled (which is the right behaviour).
Now, my problem is that I want to allow the user to try re-loading the picture(s). So the next webClient request(s) are failing with the same WebException. Below is my code.
Here is my Custom WebClient class (used in order to have more than 2 async connections at a time):
internal class ExtendedWebClient : WebClient
{
private Timer _timer;
public int ConnectionLimit { get; set; }
public int ConnectionTimeout { get; set; }
public ExtendedWebClient()
{
this.ConnectionLimit = 2;
}
protected override WebRequest GetWebRequest(Uri address)
{
var request = base.GetWebRequest(address) as HttpWebRequest;
if (request != null){_timer = new Timer(TimeoutRequest, request, ConnectionTimeout, Timeout.Infinite);
request.ServicePoint.ConnectionLimit = this.ConnectionLimit;
request.ServicePoint.MaxIdleTime = 5000;
request.ServicePoint.ConnectionLeaseTimeout = 5000;
}
return request;
}
private void TimeoutRequest(object state)
{
_timer.Dispose();
_timer = null;
((WebRequest)state).Abort();
}
protected override void Dispose(bool disposing)
{
if (_timer != null)
{
_timer.Dispose();
_timer = null;
}
base.Dispose(disposing);
}
}
Here is the code to download the files using my custom WebClient class:
internal struct PageWaitHandleState
{
public int WaitHandleIndexInPage;
public bool ImageIsLoaded;
public string ErrMessage;
}
public Image[] downloadedImages;
private PageWaitHandleState[] waitHandlesInPage;
private OpenReadCompletedEventHandler[] downloadComplete;
private EventWaitHandle[] pagesEWH = null;
private EventWaitHandle[] downloadImageEvent;
private int availableImages = 1; // Set here to simplify, but as I stated in my description, it may be more than 1.
int downloadTimeOut = 15000;
int maxSimultaneousDownloads = 20;
private void DownloadImages(int pageIndex = 0, string[] imageUrl)
{
if (pagesEWH[pageIndex] != null)
{
ReloadImages(pageIndex, imageUrl); // Executed in the second request
return;
else
{
pagesEWH[pageIndex] = new EventWaitHandle[availableImages];
downloadedImages = new Image[availableImages];
downloadComplete = new OpenReadCompletedEventHandler[availableImages];
downloadImageEvent = new EventWaitHandle[availableImages];
waitHandlesInPage = new PageWaitHandleState[availableImages];
// Set the downloadComplete deletages
for (int i = 0; i < availableImages; i++)
{
downloadComplete[i] = ProcessImage;
}
}
for (int imgCounter = 0; i < availableImages; i++)
{
waitHandlesInPage[imgCounter] = new PageWaitHandleState() { ImageIsLoaded = false, WaitHandleIndexInPage = imgCounter, ErrMessage = null };
downloadImageEvent[imgCounter] = GrabImageAsync(imageUrl[imgCounter], downloadComplete[imgCounter], imgCounter, downloadTimeOut, maxSimultaneousDownloads);
pagesEWH[imgCounter] = downloadImageEvent[imgCounter];
}
offenderIndex++;
}
}
private static EventWaitHandle GrabImageAsync(string url, OpenReadCompletedEventHandler openReadCompletedEventHandler, int imgCounter, int downloadTimeOut, int maxSimultaneousDownloads)
{
var myClient = new ExtendedWebClient();
myClient.ConnectionLimit = maxSimultaneousDownloads;
myClient.ConnectionTimeout = downloadTimeOut;
myClient.OpenReadCompleted += openReadCompletedEventHandler;
var iewh = new ImageEventWaitHandle() { ewh = new EventWaitHandle(false, EventResetMode.ManualReset), ImageIndex = imgCounter };
myClient.OpenReadAsync(new Uri(url), iewh);
return iewh.ewh;
}
internal void ProcessImage(object sender, OpenReadCompletedEventArgs e)
{
ImageEventWaitHandle iewh = (ImageEventWaitHandle)e.UserState;
bool disposeObject = false;
try
{
if (e.Cancelled)
{
this.waitHandlesInPage[iewh.ImageIndex].ImageIsLoaded = false;
this.waitHandlesInPage[iewh.ImageIndex].ErrMessage = "WebClient request was cancelled";
}
else if (e.Error != null)
{
this.waitHandlesInPage[iewh.ImageIndex].ImageIsLoaded = false;
this.waitHandlesInPage[iewh.ImageIndex].ErrMessage = e.Error.Message;
iewh.ewh.Set();
this.downloadImageEvent[iewh.ImageIndex].Close();
}
else
{
using (Stream inputStream = e.Result)
using (MemoryStream ms = new MemoryStream())
{
byte[] buffer = new byte[4096];
int bytesRead;
int totalReadBytes = 0;
do
{
bytesRead = inputStream.Read(buffer, 0, buffer.Length); // Exception fired here with the second request
ms.Write(buffer, 0, bytesRead);
totalReadBytes += bytesRead;
} while (inputStream.CanRead && bytesRead > 0);
this.downloadedImages[iewh.ImageIndex] = Image.FromStream(ms);
this.waitHandlesInPage[iewh.ImageIndex].ImageIsLoaded = true;
this.waitHandlesInPage[iewh.ImageIndex].ErrMessage = null;
}
disposeObject = true;
}
}
catch (Exception exc)
{
this.downloadedImages[iewh.ImageIndex] = null;
}
finally
{
// Signal the wait handle
if (disposeObject)
{
iewh.ewh.Set();
((WebClient)sender).Dispose();
}
}
}
private void ReloadImages(int pageIndex, string[] imageUrl)
{
for (int imgCounter = 0; imgCounter < availableImages; imgCounter++)
{
this.downloadComplete[imgCounter] = this.ProcessImage;
this.waitHandlesInPage[imgCounter] = new PageWaitHandleState() { ImageIsLoaded = false, WaitHandleIndexInPage = imgCounter, ErrMessage = null };
this.downloadImageEvent[imgCounter] = GrabImageAsync(ImageUrl[imgCounter],this.downloadComplete[imgCounter], imgCounter, downloadTimeOut, maxSimultaneousDownloads);
this.pagesEWH[imgCounter] = this.downloadImageEvent[imgCounter];
}
}
Finally, when I want to access the images I check if they are ready by using:
private bool ImagesInPageReady(int pageIndex, int recordsInCurrentPage)
{
if (_PagesEWH[pageIndex] != null)
{
int completedDownloadsCount = 0;
bool waitHandleSet;
// Wait for the default images first (imgCounter = 0). When moving page or asking for more pictures, then wait for the others.
for (int ewhIndexInPage = 0; ewhIndexInPage < recordsInCurrentPage; ewhIndexInPage++)
{
if (this.pagesEWH[ewhIndexInPage].WaitOne(this.downloadTimeOut))
{
if (this.WaitHandlesInPage[ewhIndexInPage].ImageIsLoaded)
{
completedDownloadsCount++;
}
}
else
{
this.pagesEWH[ewhIndexInPage].Set();
}
}
return (completedDownloadsCount > 0);
}
return false;
}
#usr, thanks for pointing me in the right direction. HttpClient was the solution. So I basically encapsulated my HttpClient object in a new class, together with the ProcessImage() method and exposing and event fired by the same method.
import java.util.*;
import java.io.*;
import java.text.DecimalFormat;
My problem is that once it starts the loop it just reads the first line on the file and writes it infinitely amount of times.
What I want is for it to go to the next line and so on
(The code is basically what I want but it is not finished)
public class Lab0234
{
public static void main(String [] args) throws FileNotFoundException
{
DecimalFormat two = new DecimalFormat("00.00");
Scanner keyboard = new Scanner(System.in);
Scanner inputFile = new Scanner(new FileReader("Lab02Input.txt"));
double sPrice = inputFile.nextDouble();
double sOwned = inputFile.nextDouble();
double aDiv = inputFile.nextDouble();
double mValue;
double mYield;
mValue = getValue(sPrice, sOwned);
mYield = getYield(sPrice, aDiv);
PrintWriter reportFile = new PrintWriter("Lab02Report.txt");
reportFile.println("Stock Value and Yield Report");
reportFile.println("");
reportFile.print("Stock ");
reportFile.print("Price ");
reportFile.print("Shares ");
reportFile.print("Value ");
reportFile.print("Dividend ");
reportFile.println("Yield");
while(inputFile.hasNext())
{
if (inputFile.hasNext())
{
reportFile.print(" ");
reportFile.print(sPrice+" ");
reportFile.print(sOwned+" ");
getValue(sPrice, sOwned);
reportFile.print(two.format(mValue)+" ");
reportFile.print(aDiv+" ");
getYield(sPrice, aDiv);
reportFile.println(two.format(mYield)+" ");
inputFile.close();
reportFile.close();
}
/*else
{
inputFile.close();
reportFile.close();
}*/
}
//inputFile.close();
//reportFile.close();
}
public static double getValue(double sPrice, double sOwned)
{
//DecimalFormat two = new DecimalFormat("00.00"); //Decimal format
double mValue;
mValue = (sPrice * sOwned);
//System.out.printf("Stock Value is " + mValue);
return mValue;
}
public static double getYield(double sPrice, double aDiv)
{
//DecimalFormat two = new DecimalFormat("00.00"); //Decimal format
double mYield;
mYield = (aDiv * sPrice);
//System.out.printf("\nDividend Yield is " + two.format(mYield));
return mYield;
}
}
You never call next() on your inputFile:
while(inputFile.hasNext())
{
String x = inputFile.next();
if (inputFile.hasNext())
Try do it like this
try {
BufferedReader br = new BufferedReader(new FileReader(filePath));
String line;
while ((line = br.readLine()) != null) {
// do somthing
}
br.close();
} catch (Exception e) {
System.out.print("Problem!");
}
Today I was going to pack my game into a Jar to provide to a friend who codes and wanted to see a nice glitch I managed to create. When I went to make it a Runnable jar it would load up in the Command Prompt but throw Resource Not Found errors for Sounds (.ogg's), which was fine because they werent going to be used in the Debug mode it was set to. Then it threw a NullPointerException in TileHanlder.class at initTileMap() line 137.
I am at a loss so I came to StackOverflow because I have spent nearly my entire day on getting a working Jar. I have also tried JarSplice.
My main question is if there is any anomalies you notice or something I didnt do that is leading to resources not being found in the .jar.
ALL CODE AND RESOURCES WERE IN THE SAME JAR, ONE JAR FOR EVERYTHING there were not multiple jars
For ALL my code (it is OpenSource after all: Game Source Code)
Level.java (The class calling AssetHandler and TileHandler)
public class Level extends BasicGameState {
public MapHandler map = new MapHandler();
public AssetHandler asset = new AssetHandler();
static OutputHandler out = new OutputHandler();
public GameContainer container;
public StateBasedGame game;
public static float MouseX = 0;
public static float MouseY = 0;
public float RectX = 0;
public float RectY = 0;
public int tileAmount = 0;
public static int mapID = 1;
public static int delta;
public static int score = 0;
private static int EntityAmount = 0;
private static int ActiveEntityAmount = 0;
private int FPS = 0;
public static Image mapImage;
public static TileHandler Tile = new TileHandler();
public Point mousePoint;
public Circle mouseCirc;
public static Player p;
public static Enemy Blinky, Pinky, Inky, Clyde;
public static EntityAI AGGRESSIVE, AMBUSH, HIT_RUN, SORTOFRANDOM;
public Level(int id) {
}
#Override
public void init(GameContainer container, StateBasedGame game) throws SlickException {
MapHandler.mapRect();
mapID = MapHandler.getMapID();
MapHandler.deployMap(mapID);
try {
asset.initAssets();
OutputHandler.initFont();
} catch (AssetException e) {
e.printStackTrace();
}
TileHandler.initTileMap();
container.setUpdateOnlyWhenVisible(true);
container.setShowFPS(false);
container.setSmoothDeltas(false);
container.setVerbose(true);
this.container = container;
this.game = game;
AGGRESSIVE = new RedAI();
AMBUSH = new PinkAI();
HIT_RUN = new BlueAI();
SORTOFRANDOM = new OrangeAI();
p = new Player("Player1");
Blinky = new Enemy("Shadow", AGGRESSIVE);
Pinky = new Enemy("Speedy", AMBUSH);
Inky = new Enemy("Bashful", HIT_RUN);
Clyde = new Enemy("Pokey", SORTOFRANDOM);
}
#Override
public void render(GameContainer container, StateBasedGame game, Graphics g) throws SlickException {
Tile.drawTileMap(TileHandler.tileLayer, TileHandler.tMapTiles, g);
if (Reference.debug) {
displayTileBounds(TileHandler.tileLayer, g);
}
drawEntities();
drawStrings(g);
}
#Override
public void update(GameContainer container, StateBasedGame game, int delta) throws SlickException {
Input in = container.getInput();
MouseX = in.getMouseX();
MouseY = in.getMouseY();
RectX = MapHandler.Map32.getX();
RectY = MapHandler.Map32.getY();
EntityAmount = Entity.entityList.size();
ActiveEntityAmount = Enemy.enemyList.size() + Projectile.activeProjectiles.size() + 1;
Level.delta = delta;
Reference.defProjectileVelocity = .13f * Level.delta;
p.update(in);
updateNonPlayerEntities();
FPS = container.getFPS();
}
#Override
public int getID() {
return 2;
}
/** #deprecated **/
#Deprecated
protected void drawMap(Graphics g) {
g.drawImage(mapImage, Reference.MAP_X, Reference.MAP_Y);
}
protected void drawStrings(Graphics g) {
if (Reference.debug) {
OutputHandler.write("FPS: " + Integer.toString(FPS), 11, 10);
OutputHandler.write(String.format("Mouse X: %s, Mouse Y: %s", MouseX, MouseY), 11, 30);
OutputHandler.write(String.format("Rect X: %s, Y: %s", RectX, RectY), 11, 50);
OutputHandler.write("Amount of Tiles: " + (TileHandler.tileLayer.length * TileHandler.tileLayer[0].length), 11, 70);
OutputHandler.write(String.format("Amount of Entities = %s", Integer.toString(EntityAmount)), 11, 90);
OutputHandler.write(String.format("Active Entities = %s", Integer.toString(ActiveEntityAmount)), 11, 110);
out.write("Currently Loaded: " + p.isReloaded(), 11, 130);
OutputHandler.write("Amount of Entities is Accumulative", 11, 666);
} else {
String curTime = Reference.getTime();
String scoreStr = Reference.convertScore(score);
OutputHandler.write("Time: " + curTime, 11, 10);
OutputHandler.write("Score: " + scoreStr, 550, 10);
}
}
protected void displayTileBounds(Rectangle[][] tileLayer, Graphics g) {
g.setColor(Color.white);
for (int x = 0; x < tileLayer.length; x++) {
for (int y = 0; y < tileLayer[0].length; y++) {
g.fill(tileLayer[x][y]);
}
}
g.setColor(Color.magenta);
for (int s = 0; s < TileHandler.collisionTiles.size(); s++) {
Rectangle r = TileHandler.collisionTiles.get(s);
g.fill(r);
}
g.setColor(Color.orange);
g.fill(p.boundingBox);
for (int z = 0; z < Entity.teleportingTiles.length; z++) {
Rectangle r = Entity.teleportingTiles[z];
g.fill(r);
}
}
protected void drawEntities() {
ArrayList<Entity> list = Entity.entityList;
for (int i = 0; i < list.size(); i++) {
list.get(i).drawEntity(list.get(i));
}
}
protected void updateNonPlayerEntities() {
ArrayList<Enemy> list = Enemy.enemyList;
for (int i = 0; i < list.size(); i++) {
list.get(i).update();
}
ArrayList<Projectile> pList = Projectile.activeProjectiles;
for (int p = 0; p < pList.size(); p++) {
pList.get(p).update();
}
}
}
The AssetHandler (Game-Handlers-AssetHandler.java) Sounds are the THIRD TO LAST METHOD
public class AssetHandler {
public static boolean isComplete = false;
private static String musPath = "res/Sounds/";
static TileHandler tile;
private static int tsize = 32;
private static String spritesPath = "res/GameSprites/Maze Game/sprites.png";
private static String terrainPath = "res/GameSprites/Maze Game/terrain.png";
private static String twPath = "res/GameSprites/Maze Game/animation/tankToWest.png";
private static String tePath = "res/GameSprites/Maze Game/animation/tankToEast.png";
private static String tnPath = "res/GameSprites/Maze Game/animation/tankToNorth.png";
private static String tsPath = "res/GameSprites/Maze Game/animation/tankToSouth.png";
private static String bwPath = "res/GameSprites/Maze Game/animation/blueToWest.png";
private static String bePath = "res/GameSprites/Maze Game/animation/blueToEast.png";
private static String bnPath = "res/GameSprites/Maze Game/animation/blueToNorth.png";
private static String bsPath = "res/GameSprites/Maze Game/animation/blueToSouth.png";
private static String rePath, rwPath, rsPath, rnPath;
private static String pePath, pwPath, psPath, pnPath;
private static String oePath, owPath, osPath, onPath;
public static Music titleMus1, titleMus2, titleMus3, loadingScreenMus1, loadingScreenMus2, loadingScreenMus3;
public static Sound tankMove, tankFire, tankExplode, tankSurrender, tankRetreat;
public static void initSounds() {
System.out.println("Initializing Main Menu Music...");
try {
titleMus1 = new Music(musPath + "title/titlefirst.ogg");
titleMus2 = new Music(musPath + "title/titlesecond.ogg");
titleMus3 = new Music(musPath + "title/titlethird.ogg");
System.out.println("Initialized Main Menu Music!...");
} catch (SlickException e) {
e.printStackTrace();
System.out.println("ERROR: Initializing Main Menu Sounds at " + "com.treehouseelite.tank.game.handlers.AssetHandler" + " : initSounds() Method, First Try/Catch");
}
System.out.println("Initializing Loading Screen Music...");
try {
loadingScreenMus1 = new Music(musPath + "levels or loading screens/ActionBuilder.ogg");
loadingScreenMus2 = new Music(musPath + "levels or loading screens/StruggleforSurvival.ogg");
loadingScreenMus3 = new Music(musPath + "levels or loading screens/SurrealSomber.ogg");
} catch (SlickException e) {
e.printStackTrace();
System.out.println("ERROR: Initializing Loading Screen Sounds at " + "com.treehouseelite.tank.game.handlers.AssetHandler" + " : initSounds() Method, Second Try/Catch");
}
initSFX();
initsComplete();
}
private static void initsComplete() {
System.out.println("========================ALL ASSETS INITIALIZED========================");
}
public static void initSFX() {
try {
tankMove = new Sound("res/Sounds/SFX/tankMove.wav");
} catch (SlickException e) {
e.printStackTrace();
} finally {
System.out.println("All Sound Effects Initialized...");
}
}
}
TileHandler.java (Game-Handlers-TileHandler.java)
public class TileHandler {
public static String mapPath = "res/World/level_";
public static int bg, paths, collision;
public static Image[][] tMapTiles = new Image[25][20];
public static boolean[][] collidableTile = new boolean[25][20];
static Graphics g = new Graphics();
static AssetHandler asset = new AssetHandler();
// The Amount of Image is too damn high!
static TiledMap tMap;
public static int wFrame = 0;
private static int id;
public static Rectangle[][] tileLayer = new Rectangle[25][20];
public static ArrayList<Rectangle> collisionTiles = new ArrayList<Rectangle>(500);
public TileHandler() {
}
public TileHandler(int id, Rectangle rect) {
TileHandler.id = id;
try {
createTiles(id, rect);
} catch (SlickException e) {
e.printStackTrace();
}
}
protected void createTiles(int id, Rectangle layer) throws SlickException {
// Scans 0,0 to 0,20 of the tiles and then moves down the x line
// gettings tiles
// 0,0 = tileLayer[0][0]
mapPath = String.format("res/World/level_%s.tmx", id);
tMap = new TiledMap(mapPath);
bg = tMap.getLayerIndex("background");
paths = tMap.getLayerIndex("paths");
collision = tMap.getLayerIndex("collision");
// Constructs a Grid of Rectangles based on the Map's Top Left point
for (int i = 0; i < tileLayer.length; i++) {
for (int y = 0; y < tileLayer[0].length; y++) {
Rectangle tile = new Rectangle((i + Reference.MAP_X) + (i * Reference.TILE_SIZE), (y + Reference.MAP_Y) + (y * Reference.TILE_SIZE), 32, 32);
tileLayer[i][y] = tile;
}
}
/*
* for(int x = 0; x<collisionTiles.length; x++){ for(int y = 0;
* y<collisionTiles[0].length; y++){ Rectangle tile = new
* Rectangle((x+Reference.MAP_X) + (x*31),
* (y+Reference.MAP_Y+14)+(y*31),32,32); collisionTiles[x][y] = tile; }
* }
*/
}
/** #deprecated */
#Deprecated
public static void initSprites(Rectangle[][] layer) {
bg = tMap.getLayerIndex("background");
paths = tMap.getLayerIndex("paths");
collision = tMap.getLayerIndex("collision");
System.out.println("Initialized Sprites!");
}
// Initializes all tiles and put them into Image and Boolean Arrays
// Boolean Array for later use with determining whether the player or entity
// can be there. (collidableTile)
// Image array holds the tiles (tMapTiles)
public static void initTileMap() {
new Graphics();
// Getting Tiles based off Tile ID's
/** DIRT PATH MAPS (Dev Map, Level 1) **/
if ((id == 0) || (id == 1)) {
for (int x = 0; x < tileLayer.length; x++) {
for (int y = 0; y < tileLayer[0].length; y++) {
Rectangle r = new Rectangle(tileLayer[x][y].getX(), tileLayer[x][y].getY(), 32, 32);
if (tMap.getTileId(x, y, bg) == 1) {
tMapTiles[x][y] = AssetHandler.sparseGrass;
}
if (tMap.getTileId(x, y, collision) == 2) {
tMapTiles[x][y] = AssetHandler.water11;
collisionTiles.add(r);
}
if (tMap.getTileId(x, y, collision) == 57) {
tMapTiles[x][y] = AssetHandler.concrete1;
collisionTiles.add(r);
}
if (tMap.getTileId(x, y, collision) == 71) {
tMapTiles[x][y] = AssetHandler.concrete2;
// collisionTiles.add(new
// Rectangle(tileLayer[x][y].getX(),
// tileLayer[x][y].getY()+14, 32, 32)) ;
collisionTiles.add(r);
}
if (tMap.getTileId(x, y, collision) == 85) {
tMapTiles[x][y] = AssetHandler.concrete3;
collisionTiles.add(r);
}
if (tMap.getTileId(x, y, collision) == 72) {
tMapTiles[x][y] = AssetHandler.metal1;
collisionTiles.add(r);
}
if (tMap.getTileId(x, y, collision) == 58) {
tMapTiles[x][y] = AssetHandler.metal2;
collisionTiles.add(r);
}
if (tMap.getTileId(x, y, paths) == 50) {
tMapTiles[x][y] = AssetHandler.hDirtPath;
}
if (tMap.getTileId(x, y, paths) == 60) {
tMapTiles[x][y] = AssetHandler.dirtPath;
}
if (tMap.getTileId(x, y, paths) == 59) {
tMapTiles[x][y] = AssetHandler.dirtPathTurn4;
}
if (tMap.getTileId(x, y, paths) == 73) {
tMapTiles[x][y] = AssetHandler.dirtPathTurn3;
}
if (tMap.getTileId(x, y, paths) == 79) {
tMapTiles[x][y] = AssetHandler.dirtThreewayRight;
}
if (tMap.getTileId(x, y, paths) == 46) {
tMapTiles[x][y] = AssetHandler.dirtPathTurn1;
}
if (tMap.getTileId(x, y, paths) == 37) {
tMapTiles[x][y] = AssetHandler.hDirtCrossing1;
}
if ((tMap.getTileId(x, y, paths) == 80) || (tMap.getTileId(x, y, paths) == 88)) {
tMapTiles[x][y] = AssetHandler.dirtThreewayLeft;
}
if (tMap.getTileId(x, y, paths) == 102) {
tMapTiles[x][y] = AssetHandler.dirtThreewayDown;
}
if (tMap.getTileId(x, y, paths) == 74) {
tMapTiles[x][y] = AssetHandler.dirtPathTurn2;
}
if (tMap.getTileId(x, y, paths) == 107) {
tMapTiles[x][y] = AssetHandler.dirtThreewayUp;
}
if (tMap.getTileId(x, y, paths) == 88) {
tMapTiles[x][y] = AssetHandler.dirtCrossroads;
}
}
}
}
}
public void drawTileMap(Rectangle[][] layer, Image[][] tiles, Graphics g) {
// Loops through the Image array and places tile based on the Top Left
// corner of the Rectangle in the rectangle array
// Rectangle Array = layer (tileLayer was passed)
// Image Array = tiles (tMapTiles was passed)
// Asset Refers to Asset Handler
for (int x = 0; x < layer.length; x++) {
for (int y = 0; y < layer[0].length; y++) {
g.drawImage(tiles[x][y], layer[x][y].getX(), layer[x][y].getY());
// Below here is image detection for the placement of Animations
if (tiles[x][y] == AssetHandler.water11) {
AssetHandler.vRiver1.draw(layer[x][y].getX(), layer[x][y].getY());
AssetHandler.vRiver1.start();
AssetHandler.vRiver1.update(Level.delta);
} else if (tiles[x][y] == AssetHandler.hDirtCrossing1) {
AssetHandler.hDirtCrossing.draw(layer[x][y].getX(), layer[x][y].getY());
AssetHandler.hDirtCrossing.start();
AssetHandler.hDirtCrossing.update(Level.delta);
}
}
}
}
}
Finally, MapHandler.java -- Very Sparsely used, Main goal is to intialize a TileHandler object to construct the tile grid for constructing the TiledMap.
public class MapHandler {
public static AssetHandler asset = new AssetHandler();
static Image devMap;
Image map_1;
Image map_2;
Image map_3;
public static Rectangle Map32;
public MapHandler() {
}
// Sends a Rectangle set Around the Map Image to TileHandler
// to construct a grid of 32x32 Rectangles inside the Map's Rectangle
public static void deployMap(int id) {
if (id == 0) {
new TileHandler(id, Map32);
}
}
// Randomly Generates a Map ID corresponding to a Level_X.tmx
// Currently set to 0 for development purposes
public static int getMapID() {
new Random();
return 0;
// return id;
}
/* Create the Rectangle and Grid */
public static void mapRect() throws SlickException {
System.out.println("Initializing Rectangular Plane...");
Map32 = new Rectangle(Reference.GUI_WIDTH / 24, Reference.GUI_HEIGHT / 24, 800, 640);
System.out.println("Map32 Initialized!...");
}
}
If You need ANY other resources or information than please let me know and I will be happy to provide so I can get over this. I will also be thinking of other ways, Thank you for any responses!
THINGS WERE CUT OUT DUE TO THE 30k Char Limit on the question text box. Mostly in the insanely crowded AssetHandler.java, it is still there in the git repository though.
I had the very same problem. After searching for a while, I came across this neat solution. See this LWJGL forum post.
public static void main(String[] args) throws SlickException {
/* Set lwjgl library path so that LWJGL finds the natives depending on the OS. */
String osName = System.getProperty("os.name");
// Get .jar dir. new File(".") and property "user.dir" will not work if .jar is called from
// a different directory, e.g. java -jar /someOtherDirectory/myApp.jar
String nativeDir = "";
try {
nativeDir = new File(GameMain.class.getProtectionDomain().getCodeSource().getLocation().toURI()).getParent();
} catch (URISyntaxException uriEx) {
try {
// Try to resort to current dir. May still fail later due to bad start dir.
uriEx.printStackTrace();
nativeDir = new File(".").getCanonicalPath();
} catch (IOException ioEx) {
// Completely failed
ioEx.printStackTrace();
JOptionPane.showMessageDialog(new JFrame(), "Failed to locate native library directory. " +
"Error:\n" + ioEx.toString(), "Error", JOptionPane.ERROR_MESSAGE);
System.exit(-1);
}
}
// Append library subdir
nativeDir += File.separator + "lib" + File.separator + "native" + File.separator;
if (osName.startsWith("Windows")) {
nativeDir += "windows";
} else if (osName.startsWith("Linux") || osName.startsWith("FreeBSD")) {
nativeDir += "linux";
} else if (osName.startsWith("Mac OS X")) {
nativeDir += "macosx";
} else if (osName.startsWith("Solaris") || osName.startsWith("SunOS")) {
nativeDir += "solaris";
} else {
JOptionPane.showMessageDialog(new JFrame(), "Unsupported OS: " + osName + ". Exiting.",
"Error", JOptionPane.ERROR_MESSAGE);
System.exit(-1);
}
System.setProperty("org.lwjgl.librarypath", nativeDir);
}
Bear in mind that you need a lib folder in the same directory. I have mine stored outside of the .jar, but it may be possible to have it inside as well. Also note that it needs to happen before you do any LWJGL stuff, so the main method is a good place.
I am using netty 3.5.11 with Jdk 1.7 on Ubuntu to receive a large amount of updates of stocks rates at a very high frequency. The message format being sent is JSON. The data is subscribed from topic on a redis server. There is a Subscriber for each symbol. The channel object is passed to multiple Subscribers and on receiving the data it is written to the client.
Now the amount of data received is around 25,000 records in 2 minutes. Each record size is on an average around 500 bytes long.
During test runs around 7500/8000 records were dropped because the channel was not writable.
How do i avoid this. ?
I also noticed that the latency increases systematically leading to updates being received after a long period. This happened when i I used Bufferedwritehandler to avoid packet drops.
Here are the options that i set on bootstrap.
executionHandler = new ExecutionHandler(
new OrderedMemoryAwareThreadPoolExecutor(Runtime.getRuntime().availableProcessors() * 2, 1000000, 10000000, 100,
TimeUnit.MILLISECONDS));
serverBootStrap.setPipelineFactory(new ChannelPipelineFactory()
{
#Override
public ChannelPipeline getPipeline() throws Exception
{
return Channels.pipeline(new PortUnificationServerHandler(getConfiguration(), executionHandler));
}
});
serverBootStrap.setOption("child.tcpNoDelay", true);
serverBootStrap.setOption("tcpNoDelay", true);
serverBootStrap.setOption("child.keepAlive", true);
serverBootStrap.setOption("child.reuseAddress", true);
//setting buffer size can improve I/O
serverBootStrap.setOption("child.sendBufferSize", 16777216);
serverBootStrap.setOption("receiveBufferSize", 16777216);//1048576);
// better to have an receive buffer predictor
serverBootStrap.setOption("receiveBufferSizePredictorFactory", new AdaptiveReceiveBufferSizePredictorFactory(1024, 1024 * 16, 16777216));//1048576));
//if the server is sending 1000 messages per sec, optimum write buffer water marks will
//prevent unnecessary throttling, Check NioSocketChannelConfig doc
serverBootStrap.setOption("backlog", 1000);
serverBootStrap.setOption("sendBufferSize", 16777216);//1048576);
serverBootStrap.setOption("writeBufferLowWaterMark", 1024 * 1024 * 25);
serverBootStrap.setOption("writeBufferHighWaterMark", 1024 * 1024 * 50);
The pipeline and handlers class
public class PortUnificationServerHandler extends FrameDecoder
{
private AppConfiguration appConfiguration;
private final ExecutionHandler executionHandler;
public PortUnificationServerHandler(AppConfiguration pAppConfiguration, ExecutionHandler pExecutionHandler)
{
appConfiguration = pAppConfiguration;
this.executionHandler = pExecutionHandler;
}
#Override
protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception
{
String lRequest = buffer.toString(CharsetUtil.UTF_8);
if (ConnectionServiceHelper.isValidJSON(lRequest))
{
ObjectMapper lObjectMapper = new ObjectMapper();
StringReader lStringReader = new StringReader(lRequest);
JsonNode lNode = lObjectMapper.readTree(lStringReader);
if (lNode.get(Constants.REQUEST_TYPE).asText().trim().equalsIgnoreCase(Constants.LOGIN_REQUEST))
{
JsonNode lDataNode1 = lNode.get(Constants.REQUEST_DATA);
LoginRequest lLogin = lObjectMapper.treeToValue(lDataNode1, LoginRequest.class);
if (lLogin.getCompress() != null)
{
if (lLogin.getCompress().trim().equalsIgnoreCase(Constants.COMPRESS_FLAG_TRUE))
{
enableJSON(ctx);
enableGzip(ctx);
ctx.getPipeline().remove(this);
}
else
{
enableJSON(ctx);
ctx.getPipeline().remove(this);
}
}
else
{
enableJSON(ctx);
ctx.getPipeline().remove(this);
}
}
}
// Forward the current read buffer as is to the new handlers.
return buffer.readBytes(buffer.readableBytes());
}
private void enableJSON(ChannelHandlerContext ctx)
{
ChannelPipeline pipeline = ctx.getPipeline();
boolean lHandlerExists = pipeline.getContext("bufferedwriter") != null;
if (!lHandlerExists)
{
pipeline.addFirst("bufferedwriter", new MyBufferedWriteHandler()); // 80960
}
boolean lHandlerExists = pipeline.getContext("framer") != null;
if (!lHandlerExists)
{
pipeline.addLast("framer", new DelimiterBasedFrameDecoder(65535,
new ChannelBuffer[]
{
ChannelBuffers.wrappedBuffer(
new byte[]
{
'\n'
})
}));
}
lHandlerExists = pipeline.getContext("decoder") != null;
if (!lHandlerExists)
{
pipeline.addLast("decoder", new StringDecoder(CharsetUtil.UTF_8));
}
lHandlerExists = pipeline.getContext("encoder") != null;
if (!lHandlerExists)
{
pipeline.addLast("encoder", new StringEncoder(CharsetUtil.UTF_8));
}
lHandlerExists = pipeline.getContext("executor") != null;
if (!lHandlerExists)
{
pipeline.addLast("executor", executionHandler);
}
lHandlerExists = pipeline.getContext("handler") != null;
if (!lHandlerExists)
{
pipeline.addLast("handler", new ConnectionServiceUpStreamHandler(appConfiguration));
}
lHandlerExists = pipeline.getContext("unite") != null;
if (!lHandlerExists)
{
pipeline.addLast("unite", new PortUnificationServerHandler(appConfiguration, executionHandler));
}
}
private void enableGzip(ChannelHandlerContext ctx)
{
ChannelPipeline pipeline = ctx.getPipeline();
//pipeline.remove("decoder");
//pipeline.addLast("decoder", new MyStringDecoder(CharsetUtil.UTF_8, true));
//pipeline.addLast("compress", new CompressionHandler(80, "gzipdeflater"));
boolean lHandlerExists = pipeline.getContext("encoder") != null;
if (lHandlerExists)
{
pipeline.remove("encoder");
}
lHandlerExists = pipeline.getContext("gzipdeflater") != null;
if (!lHandlerExists)
{
pipeline.addBefore("executor", "gzipdeflater", new ZlibEncoder(ZlibWrapper.GZIP));
}
lHandlerExists = pipeline.getContext("lengthprepender") != null;
if (!lHandlerExists)
{
pipeline.addAfter("gzipdeflater", "lengthprepender", new LengthFieldPrepender(4));
}
}
}
The BufferedWriterHandler
public class MyBufferedWriteHandler extends BufferedWriteHandler
{
private final AtomicLong bufferSize = new AtomicLong();
final Logger logger = LoggerFactory.getLogger(getClass());
public MyBufferedWriteHandler() {
// Enable consolidation by default.
super(true);
}
#Override
public void writeRequested(ChannelHandlerContext ctx, MessageEvent e) throws Exception
{
ChannelBuffer data = (ChannelBuffer) e.getMessage();
if (e.getChannel().isWritable())
{
long newBufferSize = bufferSize.get();
// Flush the queue if it gets larger than 8KiB.
if (newBufferSize > 0)
{
flush();
bufferSize.set(0);
}
ctx.sendDownstream(e);
}
else
{
logger.warn( "Buffering data for : " + e.getChannel().getRemoteAddress() );
super.writeRequested(ctx, e);
bufferSize.addAndGet(data.readableBytes());
}
}
#Override
public void channelInterestChanged(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception
{
if (e.getChannel().isWritable())
{
flush();
}
}
The function used in the Subscriber class to write data
public void writeToClient(Channel pClientChannel, String pMessage) throws IOException
{
String lMessage = pMessage;
if (pClientChannel.isWritable())
{
lMessage += Constants.RESPONSE_DELIMITER;
pClientChannel.write(lMessage);
}
else
{
logger.warn(DroppedCounter++ + " droppped : " + pMessage);
}
}
I have implemented some of the suggestions that i read on stackoverflow and other sites. But i have not been successfull in resolving this issue.
Kindly suggest or advice as to what am i missing ?
Thanks