Thread: Buy-X needs less looping.

Page 1 of 2 12 LastLast
Results 1 to 10 of 14
  1. #1 Buy-X needs less looping. 
    Donator

    Join Date
    Jul 2009
    Posts
    1,452
    Thanks given
    27
    Thanks received
    13
    Rep Power
    69
    Hey folks.

    I'm trying to get the buy-X on my server to work right.
    Right now my buy-item looks like this:
    Code:
    	public boolean buyItem(int itemID, int fromSlot, int amount) {
    		if ((amount > 0) && (itemID == (server.shopHandler.ShopItems[MyShopID][fromSlot] - 1))) {
    			if (amount > server.shopHandler.ShopItemsN[MyShopID][fromSlot]) {
    				amount = server.shopHandler.ShopItemsN[MyShopID][fromSlot];
    			}
    			if (QH().q1 == 9) {
    				QH().q1 = 10;
    				CAM().sendMessage("You found the herb!");
    			}
    			double ShopValue;
    			double TotPrice;
    			int TotPrice2;
    			int Overstock;
    			int Slot = 0;
    			for (int i = amount; i > 0; i--) {
    				TotPrice2 = (int) Math.floor(GetItemShopValue(itemID, 0,
    				fromSlot));
    				Slot = GetItemSlot(995);
    				if (Slot == -1) {
    					CAM().sendMessage("You don't have enough coins.");
    					break;
    				}
    				if (playerItemsN[Slot] >= TotPrice2) {
    					if (freeSlots() > 0) {
    						deleteItem(995, GetItemSlot(995), TotPrice2);
    						addItem(itemID, 1);
    						server.shopHandler.ShopItemsN[MyShopID][fromSlot] -= 1;
    						server.shopHandler.ShopItemsDelay[MyShopID][fromSlot] = 0;
    						if ((fromSlot + 1) > server.shopHandler.ShopItemsStandard[MyShopID]) {
    							server.shopHandler.ShopItems[MyShopID][fromSlot] = 0;
    						}
    					} else {
    						CAM().sendMessage("Not enough space in your inventory.");
    						break;
    					}
    				} else {
    					CAM().sendMessage("You don't have enough coins.");
    					break;
    				}
    			}
    		}
    			resetItems(3823);
    			resetShop(MyShopID);
    			UpdatePlayerShop();
    			return true;
    		}
    		return false;
    	}
    and the number specified to buy, it will buy (loop though this code alot of times).

    But when i buy more than 300 items, i get an error for the code not being able to loop that much

    How do i enhance this code to just loop through a method buying 10 at a time, so it doesn't need to loop that much.

    How do i do that - i tried a number of times but didn't succeed


    Rep given!
    Reply With Quote  
     

  2. #2  
    Registered Member
    Whired's Avatar
    Join Date
    Aug 2007
    Posts
    2,126
    Thanks given
    238
    Thanks received
    500
    Rep Power
    822
    The problem isn't really inside of that block, but the problem needs to be fixed inside that block. Merely breaking from a loop will still cause that boolean to return true. Now, if you have some code that is using this boolean in a loop, such as:

    Code:
    while(buyItem(itemID, fromSlot, amount))
    {
    //do stuff
    }
    This will cause some problems. I have cleaned up your code and modified it to return false when it should. I have also added a new method because I'm guessing the reason for the breaks were to reach that code.

    Note that there may be syntax/other small errors.

    Code:
    public boolean buyItem(int itemID, int fromSlot, int amount)
    {
    	if ((amount > 0) && (itemID == (server.shopHandler.ShopItems[MyShopID][fromSlot] - 1)))	
    	{
    		//Ensure that user only buys less than or equal to the current stock
    		if (amount > server.shopHandler.ShopItemsN[MyShopID][fromSlot])
    			amount = server.shopHandler.ShopItemsN[MyShopID][fromSlot];
    		
    		//Some quest/game? If this isn't necessary, remove it
    		if (QH().q1 == 9) 
    		{
    			QH().q1 = 10;
    			CAM().sendMessage("You found the herb!");
    		}
    		
    		//Initialize some vars for initial checks
    		int totPrice = (int) Math.floor(GetItemShopValue(itemID, 0, fromSlot));
    		int Slot = GetItemSlot(995);
    		
    		//Check to see if user has enough money
    		if(Slot == -1 || playerItemsN[Slot] < totPrice)
    		{
    			CAM().sendMessage("You don't have enough coins.");
    			resetShopVars();
    			return false;
    		}
    		
    		//Buy item until amount has been reached or money is gone
    		for (int i = amount; i > 0; i--)
    		{
    			Slot = GetItemSlot(995);
    			totPrice = (int) Math.floor(GetItemShopValue(itemID, 0, fromSlot));
    			
    			//We have to check to see if user has money each run through
    			if (Slot == -1)
    			{
    				CAM().sendMessage("You don't have enough coins.");
    				resetShopVars();
    				return false;
    			}
    			if (playerItemsN[Slot] >= totPrice)
    			{
    				//Ensure that user has space for the transaction
    				if (freeSlots() > 0)
    				{
    					//Delete money
    					deleteItem(995, Slot, totPrice);
    					
    					//Add item
    					addItem(itemID, 1);
    					
    					//Remove 1 item from stock of store
    					server.shopHandler.ShopItemsN[MyShopID][fromSlot]--;
    					
    					server.shopHandler.ShopItemsDelay[MyShopID][fromSlot] = 0;
    					if ((fromSlot + 1) > server.shopHandler.ShopItemsStandard[MyShopID])
    						server.shopHandler.ShopItems[MyShopID][fromSlot] = 0;
    				}
    				else
    				{
    					CAM().sendMessage("Not enough space in your inventory.");
    					resetShopVars();
    					return false;
    				}
    			}
    			else
    			{
    				CAM().sendMessage("You don't have enough coins.");
    				resetShopVars();
    				return false;
    			}
    		}
    	}
    	resetShopVars();
    	return true;
    }
    
    private void resetShopVars()
    {
    	//Ideally these 3 method calls would be grouped somehow
    	//but I don't know your code
    	resetItems(3823);
    	resetShop(MyShopID);
    	UpdatePlayerShop();
    }
    I'd also just like to say that if this method isn't ever used to determine if a transaction is fully successful (because I don't see a practical application of this), I suggest changing the method to a void. There isn't really any sense in determining if a user ran out of money while buying shop items, and this method should never be used in a loop.
    Reply With Quote  
     

  3. #3  
    Donator

    Join Date
    Jul 2009
    Posts
    1,452
    Thanks given
    27
    Thanks received
    13
    Rep Power
    69
    Quote Originally Posted by Illuminate View Post
    The problem isn't really inside of that block, but the problem needs to be fixed inside that block. Merely breaking from a loop will still cause that boolean to return true. Now, if you have some code that is using this boolean in a loop, such as:

    Code:
    while(buyItem(itemID, fromSlot, amount))
    {
    //do stuff
    }
    This will cause some problems. I have cleaned up your code and modified it to return false when it should. I have also added a new method because I'm guessing the reason for the breaks were to reach that code.

    Note that there may be syntax/other small errors.

    Code:
    public boolean buyItem(int itemID, int fromSlot, int amount)
    {
    	if ((amount > 0) && (itemID == (server.shopHandler.ShopItems[MyShopID][fromSlot] - 1)))	
    	{
    		//Ensure that user only buys less than or equal to the current stock
    		if (amount > server.shopHandler.ShopItemsN[MyShopID][fromSlot])
    			amount = server.shopHandler.ShopItemsN[MyShopID][fromSlot];
    		
    		//Some quest/game? If this isn't necessary, remove it
    		if (QH().q1 == 9) 
    		{
    			QH().q1 = 10;
    			CAM().sendMessage("You found the herb!");
    		}
    		
    		//Initialize some vars for initial checks
    		int totPrice = (int) Math.floor(GetItemShopValue(itemID, 0, fromSlot));
    		int Slot = GetItemSlot(995);
    		
    		//Check to see if user has enough money
    		if(Slot == -1 || playerItemsN[Slot] < totPrice)
    		{
    			CAM().sendMessage("You don't have enough coins.");
    			resetShopVars();
    			return false;
    		}
    		
    		//Buy item until amount has been reached or money is gone
    		for (int i = amount; i > 0; i--)
    		{
    			Slot = GetItemSlot(995);
    			totPrice = (int) Math.floor(GetItemShopValue(itemID, 0, fromSlot));
    			
    			//We have to check to see if user has money each run through
    			if (Slot == -1)
    			{
    				CAM().sendMessage("You don't have enough coins.");
    				resetShopVars();
    				return false;
    			}
    			if (playerItemsN[Slot] >= totPrice)
    			{
    				//Ensure that user has space for the transaction
    				if (freeSlots() > 0)
    				{
    					//Delete money
    					deleteItem(995, Slot, totPrice);
    					
    					//Add item
    					addItem(itemID, 1);
    					
    					//Remove 1 item from stock of store
    					server.shopHandler.ShopItemsN[MyShopID][fromSlot]--;
    					
    					server.shopHandler.ShopItemsDelay[MyShopID][fromSlot] = 0;
    					if ((fromSlot + 1) > server.shopHandler.ShopItemsStandard[MyShopID])
    						server.shopHandler.ShopItems[MyShopID][fromSlot] = 0;
    				}
    				else
    				{
    					CAM().sendMessage("Not enough space in your inventory.");
    					resetShopVars();
    					return false;
    				}
    			}
    			else
    			{
    				CAM().sendMessage("You don't have enough coins.");
    				resetShopVars();
    				return false;
    			}
    		}
    	}
    	resetShopVars();
    	return true;
    }
    
    private void resetShopVars()
    {
    	//Ideally these 3 method calls would be grouped somehow
    	//but I don't know your code
    	resetItems(3823);
    	resetShop(MyShopID);
    	UpdatePlayerShop();
    }
    I'd also just like to say that if this method isn't ever used to determine if a transaction is fully successful (because I don't see a practical application of this), I suggest changing the method to a void. There isn't really any sense in determining if a user ran out of money while buying shop items, and this method should never be used in a loop.

    The code you posted caused nil problems, but it didn't seem to work any greater than my old code :/

    I am having this class:
    Code:
    package server.players.Packets;
    
    import server.players.client;
    
    public class EnterXAmount {
    	
    	public void parseUsage(client player, int interfaceRoot, int amount) {
    		switch (interfaceRoot) {
    		
    			case 5064:
    				deposit(player, amount);
    			break;	
    			
    			case 5382:
    				withdraw(player, amount);
    			break;
    
    			case 3322:
    				offer(player, amount);
    			break;
    
    			case 3415:
    				remove(player, amount);
    			break;
    			
    			case 3900:
    				buy(player, amount);
    			break;	
    		
    		}
    	}
    
    	private void deposit(client c, int amount) {	
    		c.bankItem(c.playerItems[c.XremoveSlot], c.XremoveSlot, amount);
    	}
    
    	private void withdraw(client c, int amount) {	
    		c.fromBank(c.bankItems[c.XremoveSlot], c.XremoveSlot, amount);
    	}
    
    	private void offer(client c, int amount) {	
    		c.getTrade().tradeItem(c.XremoveID, c.XremoveSlot, amount);
    	}
    
    	private void remove(client c, int amount) {	
    		c.getTrade().fromTrade(c.XremoveID, c.XremoveSlot, amount);
    	}
    
    	private void buy(client c, int amount) {
    		c.buyItem(c.XremoveID, c.XremoveSlot, amount);
    	}	
    	/*private void sell(client c, int amount) {
    		c.sellItem(c.XremoveID, c.XremoveSlot, amount);
    	}*/	//Failed attemp of create X-selling .. meh.
    }
    Think that'll help at all?

    I'm really glad for any help here
    Reply With Quote  
     

  4. #4  
    Banned

    Join Date
    Mar 2008
    Posts
    2,595
    Thanks given
    128
    Thanks received
    191
    Rep Power
    0
    Post errors?? More in-depth explanation of what is wrong?
    Reply With Quote  
     

  5. #5  
    Donator

    Join Date
    Jul 2009
    Posts
    1,452
    Thanks given
    27
    Thanks received
    13
    Rep Power
    69
    Quote Originally Posted by filth View Post
    Post errors?? More in-depth explanation of what is wrong?
    I simply disconnect when i try to buy more than like 120 items using buy-X.
    And i get this error in the server cmd:
    Code:
    null
    java.lang.ArrayIndexOutOfBoundsException
            at java.lang.System.arraycopy(Native Method)
            at server.world.stream.writeString(stream.java:291)
            at server.players.MiscHandlers.Manager.sendFrame126(Manager.java:66)
            at server.players.client.WriteEnergy(client.java:10117)
            at server.players.client.runEnergy(client.java:9548)
            at server.players.client.playerProcess(client.java:10491)
            at server.players.PlayerHandler.process(PlayerHandler.java:241)
            at server.world.process.run(process.java:24)
            at java.lang.Thread.run(Thread.java:619)
    null
    Game saved for player Mads
    [Mads]: <STAFF> Connection closed by user.
    [Mads]: <STAFF> Connection accepted, Process time: 1ms.
    Reply With Quote  
     

  6. #6  
    Banned

    Join Date
    Mar 2008
    Posts
    2,595
    Thanks given
    128
    Thanks received
    191
    Rep Power
    0
    Quote Originally Posted by Masochist View Post
    I simply disconnect when i try to buy more than like 120 items using buy-X.
    And i get this error in the server cmd:
    Code:
    null
    java.lang.ArrayIndexOutOfBoundsException
            at java.lang.System.arraycopy(Native Method)
            at server.world.stream.writeString(stream.java:291)
            at server.players.MiscHandlers.Manager.sendFrame126(Manager.java:66)
            at server.players.client.WriteEnergy(client.java:10117)
            at server.players.client.runEnergy(client.java:9548)
            at server.players.client.playerProcess(client.java:10491)
            at server.players.PlayerHandler.process(PlayerHandler.java:241)
            at server.world.process.run(process.java:24)
            at java.lang.Thread.run(Thread.java:619)
    null
    Game saved for player Mads
    [Mads]: <STAFF> Connection closed by user.
    [Mads]: <STAFF> Connection accepted, Process time: 1ms.
    Flush the stream after EACH packet sent.
    Reply With Quote  
     

  7. #7  
    Donator

    Join Date
    Jul 2009
    Posts
    1,452
    Thanks given
    27
    Thanks received
    13
    Rep Power
    69
    Quote Originally Posted by filth View Post
    Flush the stream after EACH packet sent.
    *Cough* Uhmm - come again? please explain this >.<
    Reply With Quote  
     

  8. #8  
    Banned

    Join Date
    Mar 2008
    Posts
    2,595
    Thanks given
    128
    Thanks received
    191
    Rep Power
    0
    You might see something like this:

    Code:
    public void showItem(int interface, int id, int amount) {
    outStream.createFrame(itemOp);
    outStream.writeInt(interface);
    outStream.writeInt(id);
    outStream.writeInt(amount);
    }
    (Obviously not that exact thing, but I haven't touched winterLove in a while and well that should give you the gist of what I'm saying anyways.)

    What you want to do is flush the outstream so that the number of bytes you're writing doesn't exceed the buffer limit. Simply do:

    Code:
    public void showItem(int interface, int id, int amount) {
    outStream.createFrame(itemOp);
    outStream.writeInt(interface);
    outStream.writeInt(id);
    outStream.writeInt(amount);
    flushOutStream();
    }
    Well, whatever your method is, might not be flushOutStream.
    Reply With Quote  
     

  9. #9  
    Donator

    Join Date
    Jul 2009
    Posts
    1,452
    Thanks given
    27
    Thanks received
    13
    Rep Power
    69
    Quote Originally Posted by filth View Post
    You might see something like this:

    Code:
    public void showItem(int interface, int id, int amount) {
    outStream.createFrame(itemOp);
    outStream.writeInt(interface);
    outStream.writeInt(id);
    outStream.writeInt(amount);
    }
    (Obviously not that exact thing, but I haven't touched winterLove in a while and well that should give you the gist of what I'm saying anyways.)

    What you want to do is flush the outstream so that the number of bytes you're writing doesn't exceed the buffer limit. Simply do:

    Code:
    public void showItem(int interface, int id, int amount) {
    outStream.createFrame(itemOp);
    outStream.writeInt(interface);
    outStream.writeInt(id);
    outStream.writeInt(amount);
    flushOutStream();
    }
    Well, whatever your method is, might not be flushOutStream.
    Didn't work im still getting the excact same error
    Reply With Quote  
     

  10. #10  
    Banned

    Join Date
    Mar 2008
    Posts
    2,595
    Thanks given
    128
    Thanks received
    191
    Rep Power
    0
    Oops didn't look at beginning of error.

    Native method System.arraycopy

    Problem is probably in your stream class in ensureCapacity method (or whatever it is called, or any methods that use System.arraycopy look at them). It's on line 291 of stream class.
    Reply With Quote  
     

Page 1 of 2 12 LastLast

Thread Information
Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)


User Tag List

Posting Permissions
  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •