package com.planet_ink.coffee_mud.Items.Basic;
import com.planet_ink.coffee_mud.core.interfaces.*;
import com.planet_ink.coffee_mud.core.*;
import com.planet_ink.coffee_mud.core.collections.*;
import com.planet_ink.coffee_mud.Abilities.interfaces.*;
import com.planet_ink.coffee_mud.Areas.interfaces.*;
import com.planet_ink.coffee_mud.Behaviors.interfaces.*;
import com.planet_ink.coffee_mud.CharClasses.interfaces.*;
import com.planet_ink.coffee_mud.Commands.interfaces.*;
import com.planet_ink.coffee_mud.Common.interfaces.*;
import com.planet_ink.coffee_mud.Exits.interfaces.*;
import com.planet_ink.coffee_mud.Items.interfaces.*;
import com.planet_ink.coffee_mud.Libraries.interfaces.*;
import com.planet_ink.coffee_mud.Locales.interfaces.*;
import com.planet_ink.coffee_mud.MOBS.interfaces.*;
import com.planet_ink.coffee_mud.Races.interfaces.*;
import java.util.*;
/*
Copyright 2001-2019 Bo Zimmerman
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
public class StdContainer extends StdItem implements Container
{
@Override
public String ID()
{
return "StdContainer";
}
protected boolean isLocked = false;
protected boolean hasALock = false;
protected boolean isOpen = true;
protected boolean hasALid = false;
protected boolean defaultsClosed = false;
protected boolean defaultsLocked = false;
protected int capacity = 0;
protected long containType = 0;
protected int openDelayTicks = 30;
public StdContainer()
{
super();
setName("a container");
setDisplayText("a nondescript container sits here.");
setDescription("I`ll bet you could put stuff in it!");
capacity=25;
baseGoldValue=10;
recoverPhyStats();
material=RawMaterial.RESOURCE_COTTON;
}
@Override
public int capacity()
{
return capacity;
}
@Override
public void setCapacity(final int newValue)
{
capacity=newValue;
}
@Override
public int openDelayTicks()
{
return openDelayTicks;
}
@Override
public void setOpenDelayTicks(final int ticksToReset)
{
openDelayTicks = ticksToReset;
}
@Override
public boolean okMessage(final Environmental myHost, final CMMsg msg)
{
if(!super.okMessage(myHost,msg))
return false;
if(msg.amITarget(this))
{
final MOB mob=msg.source();
switch(msg.targetMinor())
{
case CMMsg.TYP_INSTALL:
if((!(this instanceof Technical))||(!(msg.tool() instanceof Technical)))
{
mob.tell(L("@x1 cannot be installed.",name()));
return false;
}
//$FALL-THROUGH$
case CMMsg.TYP_PUT:
if(msg.tool() instanceof Item)
{
if(!CMLib.flags().isDroppable((Item)msg.tool()))
{
mob.tell(L("You can't seem to let go of @x1.",msg.tool().name()));
return false;
}
final Item newitem=(Item)msg.tool();
if(hasADoor()&&(!isOpen()))
{
mob.tell(L("@x1 is closed.",name()));
return false;
}
else
if(newitem.amWearingAt(Wearable.WORN_WIELD))
{
mob.tell(L("You are already wielding that!"));
return false;
}
else
if(newitem.amWearingAt(Wearable.WORN_HELD))
{
mob.tell(L("You are holding that!"));
return false;
}
else
if(!newitem.amWearingAt(Wearable.IN_INVENTORY))
{
mob.tell(L("You are wearing that!"));
return false;
}
else
if(capacity<=0)
{
mob.tell(L("You can't put anything in @x1!",name()));
return false;
}
else
{
if(!canContain(newitem))
{
mob.tell(L("You can't put @x1 in @x2.",newitem.name(),name()));
return false;
}
else
if(newitem.phyStats().weight()>capacity)
{
mob.tell(L("@x1 won't fit in @x2.",newitem.name(),name()));
return false;
}
else
if((recursiveWeight()+newitem.phyStats().weight())>capacity)
{
if(!hasContent())
mob.tell(L("@x1 is too small.",name()));
else
if((newitem instanceof Software) && (this instanceof Computer))
mob.tell(L("@x1 is out of memory.",name()));
else
mob.tell(L("@x1 is full.",name()));
return false;
}
if((!msg.source().isMine(this))&&(msg.source().isMine(newitem)))
{
final Room R=msg.source().location();
final CMMsg msg2=CMClass.getMsg(mob,newitem,null,CMMsg.MASK_OPTIMIZE|CMMsg.MASK_INTERMSG|CMMsg.MSG_DROP,null);
if((R!=null)&&(R.okMessage(mob,msg2)))
R.send(mob,msg2);
else
return false;
}
return true;
}
}
break;
case CMMsg.TYP_GET:
if(msg.tool() instanceof Item)
{
final Item newitem=(Item)msg.tool();
if(newitem.container()==this)
{
if((!(CMLib.flags().canBeSeenBy(newitem,mob)||(newitem instanceof Light)))
&&(amWearingAt(Wearable.IN_INVENTORY))
&&(!msg.sourceMajor(CMMsg.MASK_ALWAYS)))
{
mob.tell(mob,newitem,this,L("You can't see <T-NAME> in <O-NAME>."));
return false;
}
else
if(hasADoor()&&(!isOpen()))
{
mob.tell(L("@x1 is closed.",name()));
return false;
}
else
if((mob.phyStats().level()<newitem.phyStats().level()-(10+(mob.phyStats().level()/5)))
&&(!(mob instanceof ShopKeeper))
&&(!mob.charStats().getMyRace().leveless())
&&(!mob.charStats().getCurrentClass().leveless()))
{
mob.tell(L("@x1 is too powerful to endure possessing it.",newitem.name()));
return false;
}
else
if((newitem.recursiveWeight()>(mob.maxCarry()-mob.phyStats().weight()))&&(!mob.isMine(this)))
{
mob.tell(L("@x1 is too heavy.",newitem.name()));
return false;
}
else
if((newitem.numberOfItems()>(mob.maxItems()-mob.numItems()))&&(!mob.isMine(this)))
{
mob.tell(L("You can't carry that many items."));
return false;
}
else
if(!CMLib.flags().isGettable(newitem))
{
mob.tell(L("You can't get @x1.",newitem.name()));
return false;
}
return true;
}
mob.tell(mob,newitem,this,L("You can't see <T-NAME> in <O-NAME>."));
return false;
}
else
if((recursiveWeight()>(mob.maxCarry()-mob.phyStats().weight()))&&(!mob.isMine(this)))
{
mob.tell(L("@x1 is too heavy.",name()));
return false;
}
else
if(((numberOfItems()>mob.maxItems()-mob.numItems()))&&(!mob.isMine(this)))
{
mob.tell(L("You can't carry that many items."));
return false;
}
break;
case CMMsg.TYP_REMOVE:
if(msg.tool() instanceof Item)
{
final Item newitem=(Item)msg.tool();
if(newitem.container()==this)
{
if((!CMLib.flags().canBeSeenBy(newitem,mob))
&&(!msg.sourceMajor(CMMsg.MASK_ALWAYS)))
{
mob.tell(L("You can't see that."));
return false;
}
else
if(hasADoor()&&(!isOpen()))
{
mob.tell(L("@x1 is closed.",name()));
return false;
}
else
return true;
}
mob.tell(L("You don't see that here."));
return false;
}
break;
case CMMsg.TYP_CLOSE:
if(isOpen)
{
if(!hasALid)
{
mob.tell(L("There is nothing to close on @x1.",name()));
return false;
}
return true;
}
mob.tell(L("@x1 is already closed.",name()));
return false;
case CMMsg.TYP_OPEN:
if(!hasALid)
{
mob.tell(L("There is nothing to open on @x1.",name()));
return false;
}
if(isOpen)
{
mob.tell(L("@x1 is already open!",name()));
return false;
}
if(isLocked)
{
mob.tell(L("@x1 is locked.",name()));
return false;
}
return true;
case CMMsg.TYP_LOCK:
case CMMsg.TYP_UNLOCK:
if(!hasALid)
{
mob.tell(L("There is nothing to lock or unlock on @x1.",name()));
return false;
}
if(isOpen)
{
mob.tell(L("@x1 is open!",name()));
return false;
}
else
if(!hasALock)
{
mob.tell(L("There is no lock!"));
return false;
}
else
{
if((!isLocked)&&(msg.targetMinor()==CMMsg.TYP_UNLOCK))
{
mob.tell(L("@x1 is not locked.",name()));
return false;
}
else
if((isLocked)&&(msg.targetMinor()==CMMsg.TYP_LOCK))
{
mob.tell(L("@x1 is already locked.",name()));
return false;
}
else
{
for(int i=0;i<mob.numItems();i++)
{
final Item item=mob.getItem(i);
if((item!=null)
&&(item instanceof DoorKey)
&&((DoorKey)item).getKey().equals(keyName())
&&((item.container()==null)
||((item.container().container()==null)
&&((item.container().containTypes()&Container.CONTAIN_KEYS)>0)))
&&(CMLib.flags().canBeSeenBy(item,mob)))
{
if(msg.tool()==null)
msg.setTool(item);
return true;
}
}
mob.tell(L("You don't have the key."));
return false;
}
}
//break;
default:
break;
}
}
return true;
}
@Override
public boolean tick(final Tickable ticking, final int tickID)
{
if(tickID==Tickable.TICKID_EXIT_REOPEN)
{
if(hasALock && defaultsClosed && (this.keyName().length()>0) && ((!this.isLocked)||(isOpen)))
{
for(final Item keyI : getContents())
{
if((keyI instanceof DoorKey)
&&(((DoorKey)keyI).getKey().equalsIgnoreCase(this.keyName())))
return true;
}
}
setDoorsNLocks(hasALid,!defaultsClosed,defaultsClosed,hasALock,hasALock && defaultsClosed && defaultsLocked,defaultsLocked);
return false;
}
return super.tick(ticking,tickID);
}
@Override
public void executeMsg(final Environmental myHost, final CMMsg msg)
{
if(msg.amITarget(this))
{
final MOB mob=msg.source();
switch(msg.targetMinor())
{
case CMMsg.TYP_PUT:
if(msg.tool() instanceof Item)
{
final Item newitem=(Item)msg.tool();
newitem.setContainer(this);
if(!CMath.bset(msg.targetMajor(),CMMsg.MASK_OPTIMIZE))
{
mob.location().recoverRoomStats();
newitem.recoverPhyStats();
}
}
break;
case CMMsg.TYP_CLOSE:
if((!hasALid)||(!isOpen))
return;
isOpen=false;
break;
case CMMsg.TYP_OPEN:
if((!hasALid)||(isOpen)||(isLocked))
return;
if((owner() instanceof Room)
&&(!CMLib.flags().isGettable(this))
&&(!CMLib.threads().isTicking(this,Tickable.TICKID_EXIT_REOPEN))
&&(openDelayTicks>0))
CMLib.threads().startTickDown(this,Tickable.TICKID_EXIT_REOPEN,openDelayTicks);
isLocked=false;
isOpen=true;
break;
case CMMsg.TYP_LOCK:
if((!hasALid)||(!hasALock)||(isLocked))
return;
isOpen=false;
isLocked=true;
break;
case CMMsg.TYP_UNLOCK:
if((!hasALid)||(!hasALock)||(isOpen)||(!isLocked))
return;
if((owner() instanceof Room)
&&(!CMLib.flags().isGettable(this))
&&(!CMLib.threads().isTicking(this,Tickable.TICKID_EXIT_REOPEN))
&&(openDelayTicks>0))
CMLib.threads().startTickDown(this,Tickable.TICKID_EXIT_REOPEN,openDelayTicks);
isLocked=false;
break;
default:
break;
}
}
else
if((msg.tool()==this)
&&(msg.sourceMinor()==CMMsg.TYP_THROW)
&&(msg.source().isMine(this)))
{
setContainer(null);
final Room R=CMLib.map().roomLocation(msg.target());
if(R!=null)
{
CMLib.utensils().recursiveDropMOB(msg.source(),R,this,this instanceof DeadBody);
if(!CMath.bset(msg.sourceMajor(),CMMsg.MASK_OPTIMIZE))
{
msg.source().location().recoverRoomStats();
if(msg.source().location()!=R)
R.recoverRoomStats();
}
}
}
super.executeMsg(myHost,msg);
}
@Override
public long containTypes()
{
return containType;
}
@Override
public void setContainTypes(final long containTypes)
{
containType=containTypes;
}
@Override
public boolean canContain(final Item I)
{
if(containType==0)
return true;
for(int i=0;i<Container.CONTAIN_DESCS.length;i++)
{
if(CMath.isSet((int)containType,i))
{
switch((int)CMath.pow(2,i))
{
case CONTAIN_LIQUID:
if((I.material()&RawMaterial.MATERIAL_MASK)==RawMaterial.MATERIAL_LIQUID)
return true;
break;
case CONTAIN_COINS:
if(I instanceof Coins)
return true;
break;
case CONTAIN_SWORDS:
if((I instanceof Weapon)
&&(((Weapon)I).weaponClassification()==Weapon.CLASS_SWORD))
return true;
break;
case CONTAIN_DAGGERS:
if((I instanceof Weapon)
&&(((Weapon)I).weaponClassification()==Weapon.CLASS_DAGGER))
return true;
break;
case CONTAIN_KEYS:
if(I instanceof DoorKey)
return true;
break;
case CONTAIN_DRINKABLES:
if(I instanceof Drink)
return true;
break;
case CONTAIN_EATABLES:
if(I instanceof Food)
return true;
break;
case CONTAIN_CLOTHES:
if((I instanceof Armor)
&&(((Armor)I).fitsOn(Wearable.WORN_ABOUT_BODY)
||((Armor)I).fitsOn(Wearable.WORN_ARMS)
||((Armor)I).fitsOn(Wearable.WORN_LEGS)
||((Armor)I).fitsOn(Wearable.WORN_HEAD)
||((Armor)I).fitsOn(Wearable.WORN_TORSO)
||((Armor)I).fitsOn(Wearable.WORN_WAIST)))
return true;
break;
case CONTAIN_FOOTWEAR:
if((I instanceof Armor)
&&(((Armor)I).fitsOn(Wearable.WORN_FEET)))
return true;
break;
case CONTAIN_RAWMATERIALS:
if(I instanceof RawMaterial)
return true;
break;
case CONTAIN_OTHERWEAPONS:
if((I instanceof Weapon)
&&(((Weapon)I).weaponClassification()!=Weapon.CLASS_SWORD)
&&(((Weapon)I).weaponClassification()!=Weapon.CLASS_DAGGER))
return true;
break;
case CONTAIN_ONEHANDWEAPONS:
if((I instanceof Weapon)
&&(((Weapon)I).rawLogicalAnd()==false))
return true;
break;
case CONTAIN_BODIES:
if(I instanceof DeadBody)
return true;
break;
case CONTAIN_SMOKEABLES:
if((I.material()==RawMaterial.RESOURCE_PIPEWEED)
||(I.material()==RawMaterial.RESOURCE_HERBS))
return true;
break;
case CONTAIN_CAGED:
if(I instanceof CagedAnimal)
return true;
break;
case CONTAIN_READABLES:
if(I.isReadable())
return true;
break;
case CONTAIN_SCROLLS:
if(I instanceof Scroll)
return true;
break;
case CONTAIN_SSCOMPONENTS:
if(I instanceof TechComponent)
return true;
break;
}
}
}
return false;
}
@Override
public boolean isLocked()
{
return isLocked;
}
@Override
public boolean hasALock()
{
return hasALock;
}
@Override
public boolean isOpen()
{
return isOpen;
}
@Override
public boolean hasADoor()
{
return hasALid;
}
@Override
public boolean defaultsClosed()
{
return defaultsClosed;
}
@Override
public boolean defaultsLocked()
{
return defaultsLocked;
}
@Override
public void setDoorsNLocks(final boolean newHasALid, final boolean newIsOpen, final boolean newDefaultsClosed, final boolean newHasALock, final boolean newIsLocked, final boolean newDefaultsLocked)
{
this.hasALid=newHasALid;
this.isOpen=newIsOpen;
this.hasALock=newHasALock;
this.isLocked=newIsLocked;
this.defaultsClosed=newDefaultsClosed;
this.defaultsLocked=newDefaultsLocked && this.hasALock && this.defaultsClosed;
}
@Override
public void setMiscText(final String newMiscText)
{
miscText=newMiscText;
if(!isGeneric())
setKeyName(miscText);
}
@Override
public String keyName()
{
return miscText;
}
@Override
public void setKeyName(final String newKeyName)
{
miscText=newKeyName;
}
@Override
public void emptyPlease(final boolean flatten)
{
final ItemPossessor C=owner();
if(C!=null)
{
Item I;
if(flatten)
{
final List<Item> V=getDeepContents();
for(int v=0;v<V.size();v++)
{
I=V.get(v);
I.setContainer(null);
}
}
else
for(final Enumeration<Item> e = C.items(); e.hasMoreElements();)
{
I=e.nextElement();
if(I==null)
continue;
if(I.container()==this)
I.setContainer(null);
}
}
}
@Override
public boolean isInside(final Item I)
{
if(I==null)
return false;
if((I.container()==null)
||(I.container()==I))
return false;
if(I.container()==this)
return true;
return isInside(I.container());
}
@Override
public int numberOfItems()
{
return getDeepContents().size()+1;
}
@Override
public int recursiveWeight()
{
int weight=phyStats().weight();
if(owner()==null)
return weight;
if(owner() instanceof MOB)
{
final MOB M=(MOB)owner();
for(int i=0;i<M.numItems();i++)
{
final Item thisItem=M.getItem(i);
if((thisItem!=null)&&(thisItem!=this)&&(thisItem.ultimateContainer(this)==this))
weight+=thisItem.phyStats().weight();
}
}
else
if(owner() instanceof Room)
{
final Room R=(Room)owner();
for(int i=0;i<R.numItems();i++)
{
final Item thisItem=R.getItem(i);
if((thisItem!=null)&&(thisItem!=this)&&(thisItem.ultimateContainer(this)==this))
weight+=thisItem.phyStats().weight();
}
}
return weight;
}
@Override
public ReadOnlyList<Item> getDeepContents()
{
final List<Item> V=new Vector<Item>();
if(owner()!=null)
{
Item I;
for(final Enumeration<Item> e = owner().items(); e.hasMoreElements();)
{
I=e.nextElement();
if(I!=null)
{
if(isInside(I))
V.add(I);
}
}
}
return new ReadOnlyList<Item>(V);
}
@Override
public ReadOnlyList<Item> getContents()
{
final List<Item> V=new ArrayList<Item>();
if(owner()!=null)
{
Item I;
for(final Enumeration<Item> e = owner().items(); e.hasMoreElements();)
{
I=e.nextElement();
if((I!=null)&&(I.container()==this))
V.add(I);
}
}
return new ReadOnlyList<Item>(V);
}
@Override
public boolean hasContent()
{
if(owner()!=null)
{
Item I;
for(final Enumeration<Item> e = owner().items(); e.hasMoreElements();)
{
I=e.nextElement();
if((I!=null)&&(I.container()==this))
return true;
}
}
return false;
}
}