Merged in Milie95/holocore/feature/stacking (pull request #566)

Added item stacking and splitting
This commit is contained in:
Emilie Jørgensen
2018-03-31 15:50:05 +00:00
committed by Obique PSWG
9 changed files with 159 additions and 21 deletions
@@ -34,7 +34,7 @@ import com.projectswg.holocore.resources.objects.SWGObject
import com.projectswg.holocore.resources.player.Player
import com.projectswg.holocore.scripts.radial.RadialHandlerInterface
class CreditObjectRadial extends SWGObjectRadial implements RadialHandlerInterface {
class CreditObjectRadial extends SWGObjectRadial {
def getOptions(List<RadialOption> options, Player player, SWGObject target) {
options.add(new RadialOption(RadialItem.TRANSFER_CREDITS_TO_BANK_ACCOUNT))
@@ -29,18 +29,116 @@ package com.projectswg.holocore.scripts.radial.object
import com.projectswg.common.data.radial.RadialItem
import com.projectswg.common.data.radial.RadialOption
import com.projectswg.holocore.intents.chat.SystemMessageIntent
import com.projectswg.holocore.intents.object.ContainerTransferIntent
import com.projectswg.holocore.intents.object.ObjectCreatedIntent
import com.projectswg.holocore.resources.objects.SWGObject
import com.projectswg.holocore.resources.objects.tangible.TangibleObject
import com.projectswg.holocore.resources.player.Player
import com.projectswg.holocore.resources.sui.SuiInputBox
import com.projectswg.holocore.scripts.radial.RadialHandlerInterface
import com.projectswg.holocore.services.objects.ObjectCreator
class SWGObjectRadial implements RadialHandlerInterface {
def getOptions(List<RadialOption> options, Player player, SWGObject target) {
stackOptions(options, target)
}
def stackOptions(List<RadialOption> options, SWGObject target) {
// Verify that target is a tangible
if (target == null || target.getClass() != TangibleObject.class)
return
// Check if the target is not in a container then show no radial options
SWGObject container = target.getParent()
if (container == null) {
return
}
def tangibleTarget = (TangibleObject) target
if (tangibleTarget.getCounter() < 1) {
return
}
def splitOption = new RadialOption(RadialItem.SERVER_MENU49)
def stackOption = new RadialOption(RadialItem.SERVER_MENU50)
splitOption.setOverriddenText("@autostack:unstack")
stackOption.setOverriddenText("@autostack:stack")
options.add(splitOption)
options.add(stackOption)
}
def split(Player player, SWGObject target) {
// Create input-window
def window = new SuiInputBox("@autostack:unstack", "@autostack:stacksize")
// Handle button selection
window.addOkButtonCallback("split", {event, parameters ->
String input = SuiInputBox.getEnteredText(parameters)
TangibleObject originalStack = (TangibleObject) target
try {
int newStackSize = Integer.parseInt(input)
int counter = originalStack.getCounter()
int oldStackSize = counter - newStackSize
if (oldStackSize < 1) {
SystemMessageIntent.broadcastPersonal(player, "@autostack:zero_size")
return
} else if (oldStackSize >= counter) {
SystemMessageIntent.broadcastPersonal(player, "@autostack:too_big")
return
}
// Check inventory volume
SWGObject container = target.getParent()
if (container.getVolume() + 1 > container.getMaxContainerSize()) {
SystemMessageIntent.broadcastPersonal(player, "@autostack:full_container")
return
}
// Create new object using same template
// TODO needs to copy other stuff as well, such as customization variables and object attributes
String template = originalStack.getTemplate()
TangibleObject newStack = (TangibleObject) ObjectCreator.createObjectFromTemplate(template)
// Adjust stack sizes
originalStack.setCounter(oldStackSize)
newStack.setCounter(newStackSize)
// We don't use moveToContainer, because that would trigger auto-stacking.
newStack.systemMove(container)
ContainerTransferIntent.broadcast(newStack, null, container)
ObjectCreatedIntent.broadcast(newStack)
} catch (NumberFormatException e) {
SystemMessageIntent.broadcastPersonal(player, "@autostack:number_format_wrong")
}
})
// Display the window
window.display(player)
}
def stack(SWGObject target) {
target.moveToContainer(target.getParent()) // Triggers stacking, if applicable
}
def handleSelection(Player player, SWGObject target, RadialItem selection) {
switch (selection) {
case RadialItem.SERVER_MENU49:
split(player, target)
break
case RadialItem.SERVER_MENU50:
stack(target)
break
}
}
}
@@ -35,6 +35,7 @@ import com.projectswg.holocore.resources.player.Player
class UsableObjectRadial extends SWGObjectRadial {
def getOptions(List<RadialOption> options, Player player, SWGObject target) {
super.getOptions(options, player, target)
options.add(new RadialOption(RadialItem.ITEM_USE))
options.add(new RadialOption(RadialItem.EXAMINE))
}
@@ -33,15 +33,15 @@ import com.projectswg.holocore.intents.crafting.survey.StartSurveyToolIntent
import com.projectswg.holocore.resources.objects.SWGObject
import com.projectswg.holocore.resources.player.Player
import com.projectswg.holocore.scripts.radial.RadialHandlerInterface
import com.projectswg.holocore.scripts.radial.object.UsableObjectRadial
class ObjectSurveyToolRadial implements RadialHandlerInterface {
def getOptions(List<RadialOption> options, Player player, SWGObject target) {
options.add(new RadialOption(RadialItem.ITEM_USE))
options.add(new RadialOption(RadialItem.EXAMINE))
}
class ObjectSurveyToolRadial extends UsableObjectRadial {
def handleSelection(Player player, SWGObject target, RadialItem selection) {
if (selection != RadialItem.ITEM_USE) {
return
}
new StartSurveyToolIntent(player.getCreatureObject(), target).broadcast()
}
@@ -35,7 +35,7 @@ import com.projectswg.holocore.resources.player.Player
import com.projectswg.holocore.scripts.radial.RadialHandlerInterface
import com.projectswg.holocore.scripts.radial.object.SWGObjectRadial
class ObjectUniformBoxRadial extends SWGObjectRadial implements RadialHandlerInterface {
class ObjectUniformBoxRadial extends SWGObjectRadial {
def handleSelection(Player player, SWGObject target, RadialItem selection) {
DestroyObjectIntent.broadcast(target)
@@ -33,13 +33,16 @@ import com.projectswg.common.data.radial.RadialItem
import com.projectswg.common.data.radial.RadialOption
import com.projectswg.common.data.sui.SuiEvent
import com.projectswg.holocore.intents.object.CreateStaticItemIntent
import com.projectswg.holocore.intents.object.ObjectCreatedIntent
import com.projectswg.holocore.intents.object.ObjectTeleportIntent
import com.projectswg.holocore.resources.containers.ContainerPermissionsType
import com.projectswg.holocore.resources.objects.SWGObject
import com.projectswg.holocore.resources.objects.tangible.TangibleObject
import com.projectswg.holocore.resources.player.Player
import com.projectswg.holocore.resources.sui.SuiButtons
import com.projectswg.holocore.resources.sui.SuiListBox
import com.projectswg.holocore.scripts.radial.RadialHandlerInterface
import com.projectswg.holocore.services.objects.ObjectCreator
import com.projectswg.holocore.services.objects.StaticItemService
class TerminalCharacterBuilderRadial implements RadialHandlerInterface {
@@ -59,6 +62,7 @@ class TerminalCharacterBuilderRadial implements RadialHandlerInterface {
listBox.addListItem("Wearables")
listBox.addListItem("Tools")
listBox.addListItem("Travel")
listBox.addListItem("Stack test")
listBox.addCallback(SuiEvent.OK_PRESSED, "handleCategorySelection", { event, parameters -> handleCategorySelection(player, parameters) })
listBox.display(player)
@@ -76,6 +80,7 @@ class TerminalCharacterBuilderRadial implements RadialHandlerInterface {
case 2: handleWearables(player); break
case 3: handleTools(player); break
case 4: handleTravel(player); break
case 5: handleStackTest(player); break
}
}
@@ -1387,4 +1392,15 @@ class TerminalCharacterBuilderRadial implements RadialHandlerInterface {
static def handleYavGeoCave(Player player) {
new ObjectTeleportIntent(player.getCreatureObject(), new Location(-6485d, 83d, -446d, Terrain.YAVIN4)).broadcast()
}
static def handleStackTest(Player player) {
def stackObject = ObjectCreator.createObjectFromTemplate("object/tangible/dice/shared_eqp_chance_cube.iff", TangibleObject.class)
def creature = player.getCreatureObject()
def inventory = creature.getSlottedObject("inventory")
stackObject.setCounter(6)
stackObject.moveToContainer(inventory)
ObjectCreatedIntent.broadcast(stackObject)
}
}
@@ -26,8 +26,6 @@
***********************************************************************************/
package com.projectswg.holocore.resources.commands.callbacks;
import java.util.Map;
import com.projectswg.common.network.packets.swg.zone.spatial.AttributeListMessage;
import com.projectswg.holocore.resources.commands.ICmdCallback;
@@ -52,11 +50,6 @@ public class AttributesCmdCallback implements ICmdCallback {
}
private void handleSendItemAttributes(SWGObject object, Player player) {
Map<String, String> attributes = object.getAttributes();
if (attributes.size() == 0)
attributes.put("", "");
AttributeListMessage message = new AttributeListMessage(object.getObjectId(), attributes);
player.sendPacket(message);
player.sendPacket(new AttributeListMessage(object.getObjectId(), object.getAttributes()));
}
}
@@ -546,7 +546,7 @@ public abstract class SWGObject extends BaselineObject implements Comparable<SWG
}
public Map<String, String> getAttributes() {
return attributes;
return Collections.unmodifiableMap(attributes);
}
public int getContainerType() {
@@ -26,6 +26,9 @@
***********************************************************************************/
package com.projectswg.holocore.resources.objects.tangible;
import java.util.Map;
import java.util.Set;
import com.projectswg.common.data.customization.CustomizationString;
import com.projectswg.common.data.customization.CustomizationVariable;
import com.projectswg.common.data.encodables.tangible.PvpFaction;
@@ -37,6 +40,7 @@ import com.projectswg.common.network.NetBufferStream;
import com.projectswg.common.network.packets.swg.zone.baselines.Baseline.BaselineType;
import com.projectswg.holocore.intents.FactionIntent;
import com.projectswg.holocore.intents.FactionIntent.FactionIntentType;
import com.projectswg.holocore.intents.object.DestroyObjectIntent;
import com.projectswg.holocore.resources.collections.SWGMap;
import com.projectswg.holocore.resources.collections.SWGSet;
import com.projectswg.holocore.resources.network.BaselineBuilder;
@@ -44,8 +48,6 @@ import com.projectswg.holocore.resources.objects.SWGObject;
import com.projectswg.holocore.resources.objects.creature.CreatureObject;
import com.projectswg.holocore.resources.player.Player;
import java.util.Set;
public class TangibleObject extends SWGObject {
private CustomizationString appearanceData = new CustomizationString();
@@ -75,6 +77,34 @@ public class TangibleObject extends SWGObject {
super(objectId, objectType);
}
@Override
public void moveToContainer(SWGObject newParent) {
// Check if object is stackable
if (newParent != null && counter > 0) {
// Scan container for matching stackable item
String ourTemplate = getTemplate();
Map<String, String> ourAttributes = getAttributes();
for (SWGObject candidate : newParent.getContainedObjects()) {
String theirTemplate = candidate.getTemplate();
Map<String, String> theirAttributes = candidate.getAttributes();
if (this != candidate && candidate instanceof TangibleObject && ourTemplate.equals(theirTemplate) && ourAttributes.equals(theirAttributes)) {
DestroyObjectIntent.broadcast(this);
// Increase stack count on matching stackable item
TangibleObject tangibleMatch = (TangibleObject) candidate;
int theirCounter = tangibleMatch.getCounter();
tangibleMatch.setCounter(theirCounter + counter);
return; // Stackable and matching item was found
}
}
}
super.moveToContainer(newParent); // Not stackable, use default behavior
}
public int getMaxHitPoints() {
return maxHitPoints;
}