0001: /*
0002: *
0003: * Copyright (c) 2001 Silvere Martin-Michiellot All Rights Reserved.
0004: *
0005: * Silvere Martin-Michiellot grants you ("Licensee") a non-exclusive,
0006: * royalty free, license to use, modify and redistribute this
0007: * software in source and binary code form,
0008: * provided that i) this copyright notice and license appear on all copies of
0009: * the software; and ii) Licensee does not utilize the software in a manner
0010: * which is disparaging to Silvere Martin-Michiellot.
0011: *
0012: * This software is provided "AS IS," without a warranty of any kind. ALL
0013: * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
0014: * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
0015: * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. Silvere Martin-Michiellot
0016: * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES
0017: * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
0018: * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
0019: * Silvere Martin-Michiellot OR ITS LICENSORS BE LIABLE
0020: * FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
0021: * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
0022: * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
0023: * OR INABILITY TO USE SOFTWARE, EVEN IF Silvere Martin-Michiellot HAS BEEN
0024: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
0025: *
0026: * This software is not designed or intended for use in on-line control of
0027: * aircraft, air traffic, aircraft navigation or aircraft communications; or in
0028: * the design, construction, operation or maintenance of any nuclear
0029: * facility. Licensee represents and warrants that it will not use or
0030: * redistribute the Software for such purposes.
0031: *
0032: * @Author: Silvere Martin-Michiellot
0033: *
0034: */
0035:
0036: package com.db.server;
0037:
0038: import java.io.Serializable;
0039: import java.util.*;
0040: import javax.jdo.*;
0041: import javax.media.j3d.*;
0042: import javax.vecmath.*;
0043:
0044: /**
0045: */
0046:
0047: public class Land extends VirtualElement {
0048:
0049: //Lords and self are always allowed full rights
0050:
0051: public final static int NO_CAPABILITY = 0;
0052:
0053: public final static int SALABLE = 1;
0054: //NAVIGABLE like if an invisible force field protects the Land
0055: public final static int NAVIGABLE = 2;
0056: public final static int USE_IMPORTED_OBJECTS = 4;
0057: public final static int DROP_ACCEPTED = 8;
0058: //OBSERVE_AND_HEAR is different from ObjectWorld's VISIBLE because is makes the whole land disappear in a greyed boundary
0059: public final static int OBSERVE_AND_HEAR = 16;
0060:
0061: private static int LAST_CAPABILITY = (Land.OBSERVE_AND_HEAR * 2) - 1;
0062:
0063: public static int DEFAULT_DESIGNER_CAPABILITIES = Land.LAST_CAPABILITY;
0064:
0065: public final static int HIDDEN = 0;
0066: public final static int READ = 1;
0067: public final static int READ_WRITE = 2;
0068:
0069: //VirtualElement.SALABLE = 1;
0070: //ObjectWorld.RESHAPEABLE = 2;BackgroundWorld.RESHAPEABLE = 2;
0071: //ObjectWorld.SOUNDALTERABLE = 4;BackgroundWorld.SOUNDALTERABLE = 4;
0072: //ObjectWorld.VISIBLE = 8;BackgroundWorld.VISIBLE = 8;
0073: //ObjectWorld.SONORE = 16;BackgroundWorld.SONORE = 16;
0074: //ObjectWorld.MOVABLE = 32;
0075: //ObjectWorld.COLLIDABLE = 64;
0076: //ObjectWorld.INVENTORIZABLE = 128;
0077: //ObjectWorld.ACCESSORY = 256;
0078: //ObjectWorld.CUTABLE = 512;
0079: //ObjectWorld.GLUABLE = 1024;
0080: //ObjectWorld.DUPLICABLE = 2048;
0081: //ToolWorld.GENERIC = 4096;
0082: //ToolWorld.HEADUP = 8192;
0083: //ToolWorld.FERTILE = 16384;
0084: //ToolWorld.MANIPULATES = 32768;
0085: //ToolWorld.SUPPRESSOR = 65536;
0086: //GuideWorld.REMOTEVIEW = 131072;
0087: //Skin.HANDS;
0088:
0089: public final static int OWNERS_OBJECTS_PEERLORD_DEFAULT_POLICY = 8 + 16 + 32 + 64;
0090: public final static int OWNERS_OBJECTS_PEER_DEFAULT_POLICY = 8 + 16 + 64;
0091: public final static int OWNERS_OBJECTS_PEERVASSAL_DEFAULT_POLICY = 8 + 16 + 64;
0092: public final static int OWNERS_OBJECTS_VASSAL_DEFAULT_POLICY = 2
0093: + 4 + 8 + 16 + 32 + 512 + 1024 + 2048;
0094:
0095: /**
0096: * owner
0097: * bounds (coordinates are given relatively to the world spot center)
0098: * price
0099: * currency
0100: * access rights (4 booleans grant access for invited lords, peers, peers vassals and vassals):
0101: * observe and hear
0102: * navigate inside bounds
0103: * use imported objects, tools or guides (guides could also need to navigate inside bounds since they may come by themselves in a land) on
0104: * local objects, tools or guides.
0105: * drop accepted
0106: * salable
0107: * template for owner's objects, tools and guides capabilities and access list (restricts other users access on local objects, tools and guides)
0108: * objects tools and guides on this land (this is only a pointer to a query on the world spot for convenience)
0109: **/
0110:
0111: private Bounds bounds;
0112:
0113: //rights to activate a behavior for the object depending on the triggering user
0114: private int[] othersAccessRights = { VirtualElement.READ,
0115: VirtualElement.READ, VirtualElement.HIDDEN,
0116: VirtualElement.READ };
0117: //when someone use the owner's objects on this land, a default restriction rights checks is made against this template
0118: //objects may further restrict this list
0119: private int[] ownersObjectsDefaultRights = {
0120: Land.OWNERS_OBJECTS_PEERLORD_DEFAULT_POLICY,
0121: Land.OWNERS_OBJECTS_PEER_DEFAULT_POLICY,
0122: Land.OWNERS_OBJECTS_PEERVASSAL_DEFAULT_POLICY,
0123: Land.OWNERS_OBJECTS_VASSAL_DEFAULT_POLICY };
0124:
0125: //this constructor is called only once at worldSpot instanciation by the ruler
0126: //land is eventually splitted into multiple parts that are given to some users
0127: public Land(UniverseServer universeServer, Avatar userOwner,
0128: Bounds bounds) {
0129:
0130: super (universeServer, userOwner);
0131: if ((bounds != null) && (!bounds.isEmpty())) {
0132: this .bounds = bounds;
0133: } else {
0134: throw new java.lang.IllegalArgumentException(
0135: "A land must have a valid universeServer, a valid owner and valid bounds.");
0136: }
0137:
0138: }
0139:
0140: //every "get" or "set" call assumes valid user's rights (depending on who calls)
0141: //otherwise the server returns a request refused message
0142:
0143: //must be >= 0
0144: public final void setPrice(double price) {
0145:
0146: if (this .checkWritable(VirtualElement.SALABLE)) {
0147:
0148: if (price >= 0) {
0149: this .price = price;
0150: this .doPriceChanged();
0151: }
0152:
0153: }
0154:
0155: }
0156:
0157: //any valid string will fit
0158: public final void setCurrency(String currency) {
0159:
0160: if (this .checkWritable(VirtualElement.SALABLE)) {
0161:
0162: if ((currency != null) && currency.length() > 0) {
0163: this .currency = currency;
0164: this .doCurrencyChanged();
0165: }
0166:
0167: }
0168:
0169: }
0170:
0171: public final Bounds getBounds() {
0172:
0173: return this .bounds;
0174:
0175: }
0176:
0177: public final int[] getOwnersObjectsDefaultRights() {
0178:
0179: return this .ownersObjectsDefaultRights;
0180:
0181: }
0182:
0183: public final int getOwnersObjectsDefaultRights(int userKind) {
0184:
0185: switch (userKind) {
0186: case Avatar.PEERSLORD:
0187: return this .ownersObjectsDefaultRights[0];
0188: case Avatar.PEER:
0189: return this .ownersObjectsDefaultRights[1];
0190: case Avatar.PEERSVASSAL:
0191: return this .ownersObjectsDefaultRights[2];
0192: case Avatar.VASSAL:
0193: return this .ownersObjectsDefaultRights[3];
0194: default:
0195: return 0;
0196: }
0197:
0198: }
0199:
0200: //capabilities works as a binary mask
0201: //faster than getOwnersObjectsDefaultRight()
0202: public final boolean getOwnersObjectsDefaultRights(int userKind,
0203: int capabilities) {
0204:
0205: return (this .getOwnersObjectsDefaultRights(userKind) & capabilities) != 0;
0206:
0207: }
0208:
0209: //must be a power of two
0210: public final boolean getOwnersObjectsDefaultRight(int userKind,
0211: int capability) {
0212:
0213: if (powerOfTwo(capability)) {
0214: return (this .getOwnersObjectsDefaultRights(userKind) & capability) != 0;
0215: } else {
0216: return false;
0217: }
0218:
0219: }
0220:
0221: //users: use split and join to set bounds
0222:
0223: //please forbid use of setBounds if you don't want full worldspot land to grow but only split and join
0224: //lands are mutually exclusive but worldspots have no hole
0225: //this command should only to enlarge a worldspot on its boundaries
0226: //you can wreck a lot of things by using setbounds and overlap other lands
0227: //for worlds with multiple worldspots think about giving land only to super users so that land never grows and coordinates merge between worldspots
0228: //the other solution is to forbid client access to setBounds (tweak the server)
0229: protected final void setBounds(Bounds bounds) {
0230:
0231: if (bounds != null) {
0232: this .bounds = bounds;
0233: this .doBoundsChanged();
0234: }
0235:
0236: }
0237:
0238: //userKind: Avatar.PEERSLORD, Avatar.PEER, Avatar.PEERSVASSAL, Avatar.VASSAL or a combination of these
0239: //invalid userKind doesn't set anything
0240: //accept: grants or refuse the right
0241: //capability must be a power of two that is a single capability
0242: public final void setOwnersObjectsDefaultRight(int userKind,
0243: int capability, boolean accept) {
0244:
0245: if (powerOfTwo(capability)) {
0246: switch (userKind) {
0247: case Avatar.PEERSLORD:
0248: if (isPowerOfTwoChecked(ownersObjectsDefaultRights[0],
0249: capability)
0250: && !accept) {
0251: ownersObjectsDefaultRights[0] = ownersObjectsDefaultRights[0]
0252: - capability;
0253: } else {
0254: if (!isPowerOfTwoChecked(
0255: ownersObjectsDefaultRights[0], capability)
0256: && accept) {
0257: ownersObjectsDefaultRights[0] = ownersObjectsDefaultRights[0]
0258: + capability;
0259: }
0260: }
0261: ;
0262: break;
0263: case Avatar.PEER:
0264: if (isPowerOfTwoChecked(ownersObjectsDefaultRights[1],
0265: capability)
0266: && !accept) {
0267: ownersObjectsDefaultRights[1] = ownersObjectsDefaultRights[1]
0268: - capability;
0269: } else {
0270: if (!isPowerOfTwoChecked(
0271: ownersObjectsDefaultRights[1], capability)
0272: && accept) {
0273: ownersObjectsDefaultRights[1] = ownersObjectsDefaultRights[1]
0274: + capability;
0275: }
0276: }
0277: ;
0278: break;
0279: case Avatar.PEERSVASSAL:
0280: if (isPowerOfTwoChecked(ownersObjectsDefaultRights[2],
0281: capability)
0282: && !accept) {
0283: ownersObjectsDefaultRights[2] = ownersObjectsDefaultRights[2]
0284: - capability;
0285: } else {
0286: if (!isPowerOfTwoChecked(
0287: ownersObjectsDefaultRights[2], capability)
0288: && accept) {
0289: ownersObjectsDefaultRights[2] = ownersObjectsDefaultRights[2]
0290: + capability;
0291: }
0292: }
0293: ;
0294: break;
0295: case Avatar.VASSAL:
0296: if (isPowerOfTwoChecked(ownersObjectsDefaultRights[3],
0297: capability)
0298: && !accept) {
0299: ownersObjectsDefaultRights[3] = ownersObjectsDefaultRights[3]
0300: - capability;
0301: } else {
0302: if (!isPowerOfTwoChecked(
0303: ownersObjectsDefaultRights[3], capability)
0304: && accept) {
0305: ownersObjectsDefaultRights[3] = ownersObjectsDefaultRights[3]
0306: + capability;
0307: }
0308: }
0309: ;
0310: break;
0311: }
0312: this .doOwnersObjectsDefaultRightsChanged();
0313: }
0314:
0315: }
0316:
0317: //will set for all users kinds
0318: //capability must be a power of two that is a single capability
0319: public final void setOwnersObjectsDefaultRight(int capability,
0320: boolean accept) {
0321:
0322: if (powerOfTwo(capability)) {
0323: if (isPowerOfTwoChecked(ownersObjectsDefaultRights[0],
0324: capability)
0325: && !accept) {
0326: ownersObjectsDefaultRights[0] = ownersObjectsDefaultRights[0]
0327: - capability;
0328: } else {
0329: if (!isPowerOfTwoChecked(ownersObjectsDefaultRights[0],
0330: capability)
0331: && accept) {
0332: ownersObjectsDefaultRights[0] = ownersObjectsDefaultRights[0]
0333: + capability;
0334: }
0335: }
0336: if (isPowerOfTwoChecked(ownersObjectsDefaultRights[1],
0337: capability)
0338: && !accept) {
0339: ownersObjectsDefaultRights[1] = ownersObjectsDefaultRights[1]
0340: - capability;
0341: } else {
0342: if (!isPowerOfTwoChecked(ownersObjectsDefaultRights[1],
0343: capability)
0344: && accept) {
0345: ownersObjectsDefaultRights[1] = ownersObjectsDefaultRights[1]
0346: + capability;
0347: }
0348: }
0349: if (isPowerOfTwoChecked(ownersObjectsDefaultRights[2],
0350: capability)
0351: && !accept) {
0352: ownersObjectsDefaultRights[2] = ownersObjectsDefaultRights[2]
0353: - capability;
0354: } else {
0355: if (!isPowerOfTwoChecked(ownersObjectsDefaultRights[2],
0356: capability)
0357: && accept) {
0358: ownersObjectsDefaultRights[2] = ownersObjectsDefaultRights[2]
0359: + capability;
0360: }
0361: }
0362: if (isPowerOfTwoChecked(ownersObjectsDefaultRights[3],
0363: capability)
0364: && !accept) {
0365: ownersObjectsDefaultRights[3] = ownersObjectsDefaultRights[3]
0366: - capability;
0367: } else {
0368: if (!isPowerOfTwoChecked(ownersObjectsDefaultRights[3],
0369: capability)
0370: && accept) {
0371: ownersObjectsDefaultRights[3] = ownersObjectsDefaultRights[3]
0372: + capability;
0373: }
0374: }
0375: this .doOwnersObjectsDefaultRightsChanged();
0376: }
0377:
0378: }
0379:
0380: //this is not a mask, all capabilities are set at once
0381: public final void setOwnersObjectsDefaultRights(int userKind,
0382: int capabilities) {
0383:
0384: if ((capabilities >= 0)
0385: && (capabilities <= Land.LAST_CAPABILITY)) {
0386: switch (userKind) {
0387: case Avatar.PEERSLORD:
0388: ownersObjectsDefaultRights[0] = capabilities;
0389: case Avatar.PEER:
0390: ownersObjectsDefaultRights[1] = capabilities;
0391: case Avatar.PEERSVASSAL:
0392: ownersObjectsDefaultRights[2] = capabilities;
0393: case Avatar.VASSAL:
0394: ownersObjectsDefaultRights[3] = capabilities;
0395: this .doOwnersObjectsDefaultRightsChanged();
0396: }
0397: }
0398:
0399: }
0400:
0401: //will set for all users kinds
0402: //this is not a mask, all capabilities are set at once
0403: public final void setOwnersObjectsDefaultRights(int capabilities) {
0404:
0405: if ((capabilities >= 0)
0406: && (capabilities <= Land.LAST_CAPABILITY)) {
0407: ownersObjectsDefaultRights[0] = capabilities;
0408: ownersObjectsDefaultRights[1] = capabilities;
0409: ownersObjectsDefaultRights[2] = capabilities;
0410: ownersObjectsDefaultRights[3] = capabilities;
0411: this .doOwnersObjectsDefaultRightsChanged();
0412: }
0413:
0414: }
0415:
0416: protected final void refreshContents() {
0417:
0418: Transaction transaction;
0419: Extent extent;
0420: Query query;
0421: String filter;
0422: Collection collection;
0423: ObjectWorld objectWorld;
0424: BackgroundWorld backgroundWorld;
0425: Iterator iterator;
0426:
0427: //checks against all users login stored in database
0428: try {
0429: transaction = this .getPersistenceManager()
0430: .currentTransaction();
0431: transaction.begin();
0432:
0433: extent = this .getPersistenceManager().getExtent(
0434: Avatar.class, true);
0435: filter = new String(
0436: "SELECT * FROM ObjectWorld o WHERE o.getBounds().intersect(this.getBounds())");
0437: query = this .getPersistenceManager().newQuery(Avatar.class,
0438: extent, filter);
0439: collection = (Collection) query.execute();
0440:
0441: transaction.commit();
0442:
0443: iterator = collection.iterator();
0444: while (iterator.hasNext()) {
0445: objectWorld = (ObjectWorld) iterator.next();
0446: objectWorld.refreshTransform();
0447: }
0448:
0449: try {
0450: transaction = this .getPersistenceManager()
0451: .currentTransaction();
0452: transaction.begin();
0453:
0454: extent = this .getPersistenceManager().getExtent(
0455: Avatar.class, true);
0456: filter = new String(
0457: "SELECT * FROM BackgroundWorld b WHERE b.getBounds().intersect(this.getBounds())");
0458: query = this .getPersistenceManager().newQuery(
0459: Avatar.class, extent, filter);
0460: collection = (Collection) query.execute();
0461:
0462: transaction.commit();
0463: } catch (Exception exception) {
0464: }
0465:
0466: iterator = collection.iterator();
0467: while (iterator.hasNext()) {
0468: backgroundWorld = (BackgroundWorld) iterator.next();
0469: backgroundWorld.refreshBounds();
0470: }
0471:
0472: } catch (Exception exception) {
0473: }
0474:
0475: }
0476:
0477: //convenience method (queries the database with normal caller's rights)
0478: //the lands currently connected to this land
0479: //(depending on the user's feodal rank, all lands may not be displayed)
0480: //some lands may be in other world spots and won't be displayed
0481: //Collection of Land
0482: public final HashSet getNeighbourhoodLands(Avatar caller) {
0483:
0484: Transaction transaction;
0485: Extent extent;
0486: Query query;
0487: String filter;
0488: Collection collection;
0489:
0490: try {
0491: transaction = this .getPersistenceManager()
0492: .currentTransaction();
0493: transaction.begin();
0494:
0495: extent = this .getPersistenceManager().getExtent(Land.class,
0496: true);
0497: filter = new String(
0498: "SELECT Land FROM Land l WHERE l.getBounds().intersect(this.getBounds())");
0499: query = this .getPersistenceManager().newQuery(Land.class,
0500: extent, filter);
0501: collection = (Collection) query.execute();
0502:
0503: transaction.commit();
0504:
0505: return this .filterCollection(caller, collection);
0506:
0507: } catch (Exception exception) {
0508:
0509: return null;
0510:
0511: }
0512:
0513: }
0514:
0515: //convenience method (queries the database with normal caller's rights)
0516: //the objects (tools and guides) currently on this land
0517: //(depending on the user's feodal rank, all avatars may not be displayed)
0518: //Collection of ObjectWorld
0519: public final HashSet getObjectWorlds(Avatar caller) {
0520:
0521: Transaction transaction;
0522: Extent extent;
0523: Query query;
0524: String filter;
0525: Collection collection;
0526:
0527: try {
0528: transaction = this .getPersistenceManager()
0529: .currentTransaction();
0530: transaction.begin();
0531:
0532: extent = this .getPersistenceManager().getExtent(
0533: ObjectWorld.class, true);
0534: filter = new String(
0535: "SELECT ObjectWorld FROM ObjectWorld o WHERE o.getBounds().intersect(this.getBounds())");
0536: query = this .getPersistenceManager().newQuery(
0537: ObjectWorld.class, extent, filter);
0538: collection = (Collection) query.execute();
0539:
0540: transaction.commit();
0541:
0542: return this .filterCollection(caller, collection);
0543:
0544: } catch (Exception exception) {
0545:
0546: return null;
0547:
0548: }
0549:
0550: }
0551:
0552: //convenience method (queries the database with normal caller's rights)
0553: //the avatars currently on this land
0554: //(depending on the user's feodal rank, all avatars may not be displayed)
0555: //Collection of Avatar
0556: public final HashSet getAvatars(Avatar caller) {
0557:
0558: //user must be able to observe and hear on this land for this query to work
0559: //some avatars may also refuse to be seen
0560:
0561: Point3d point3d;
0562: //query the database
0563: Transaction transaction;
0564: Extent extent;
0565: Query query;
0566: String filter;
0567: Collection collection;
0568:
0569: point3d = new Point3d();
0570: try {
0571: transaction = this .getPersistenceManager()
0572: .currentTransaction();
0573: transaction.begin();
0574:
0575: extent = this .getPersistenceManager().getExtent(
0576: Avatar.class, true);
0577: filter = new String(
0578: "SELECT Avatar FROM Avatar a WHERE this.getBounds().intersect(a.getSkin().getTransform3D().transform(point3d))");
0579: query = this .getPersistenceManager().newQuery(Avatar.class,
0580: extent, filter);
0581: collection = (Collection) query.execute();
0582:
0583: transaction.commit();
0584:
0585: return this .filterCollection(caller, collection);
0586:
0587: } catch (Exception exception) {
0588:
0589: return null;
0590:
0591: }
0592:
0593: }
0594:
0595: //user must have the right to get full land accesss (all fields) for that method to work (or be the owner or one of its lords)
0596: //Given an array of bounds, returns an array of lands that have the requested boundaries.
0597: //The array of bounds must have an empty intersection and an union that is the bounds of this land.
0598: //Original land is not kept and the resulting lands are all added to the database.
0599: protected final Land[] split(Bounds[] boundsList) {
0600:
0601: Land[] lands;
0602: BoundingPolytope someBounds;
0603: Transaction transaction;
0604: int i;
0605: int j;
0606: boolean valid;
0607:
0608: someBounds = new BoundingPolytope();
0609: someBounds.combine(boundsList);
0610:
0611: if (someBounds.equals(this .getBounds())) {
0612:
0613: valid = true;
0614: i = 0;
0615: while ((i < boundsList.length) && valid) {
0616: j = i + 1;
0617: while ((j < boundsList.length) && valid) {
0618: valid = !(boundsList[i].intersect(boundsList[j]));
0619: }
0620: i++;
0621: }
0622: if (valid) {
0623:
0624: lands = new Land[boundsList.length];
0625:
0626: for (i = 0; i < boundsList.length; i++) {
0627: //lands[i] = new Land(this.getUniverseServer(), this.getUserOwner(), this.getBounds());
0628: try {
0629:
0630: lands[i] = (Land) this .clone();
0631: //lands[i].setPrice(this.getPrice());
0632: //lands[i].setCurrency(this.getCurrency());
0633: //lands[i].setOthersAccessRights(Avatar.PEERSLORD, this.othersAccessRights[0]);
0634: //lands[i].setOthersAccessRights(Avatar.PEER, this.othersAccessRights[1]);
0635: //lands[i].setOthersAccessRights(Avatar.PEERSVASSAL, this.othersAccessRights[2]);
0636: //lands[i].setOthersAccessRights(Avatar.VASSAL, this.othersAccessRights[3]);
0637: //lands[i].setOwnersObjectsDefaultRights(Avatar.PEERSLORD, this.ownersObjectsDefaultRights[0]);
0638: //lands[i].setOwnersObjectsDefaultRights(Avatar.PEER, this.ownersObjectsDefaultRights[1]);
0639: //lands[i].setOwnersObjectsDefaultRights(Avatar.PEERSVASSAL, this.ownersObjectsDefaultRights[2]);
0640: //lands[i].setOwnersObjectsDefaultRights(Avatar.VASSAL, this.ownersObjectsDefaultRights[3]);
0641:
0642: //add lands to database
0643: try {
0644: transaction = this .getPersistenceManager()
0645: .currentTransaction();
0646: transaction.begin();
0647:
0648: this .getPersistenceManager()
0649: .makePersistentAll(lands);
0650:
0651: transaction.commit();
0652: } catch (Exception exception) {
0653: }
0654:
0655: this .deleteVirtualElement(this );
0656:
0657: } catch (CloneNotSupportedException cloneNotSupportedException) {
0658: }
0659:
0660: }
0661:
0662: } else {
0663: lands = new Land[1];
0664: lands[0] = this ;
0665: }
0666: } else {
0667: lands = new Land[1];
0668: lands[0] = this ;
0669: }
0670:
0671: return lands;
0672:
0673: }
0674:
0675: //user must have the right to get full land accesss (all fields) for that method to work (or be the owner or one of its lords)
0676: //tries to join this land with another
0677: //users must be the same
0678: //there must be a shared boundary
0679: //result is put into this land.
0680: //the most restrictive rights are kept
0681: //some objects may not have the rights to stay on the land
0682: public final void join(Land aLand) {
0683:
0684: Transaction transaction;
0685: Extent extent;
0686: Query query;
0687: String filter;
0688: Collection collection;
0689: Iterator iterator;
0690: ObjectWorld objectWorld;
0691: BackgroundWorld backgroundWorld;
0692: BoundingPolytope bounds;
0693:
0694: if (aLand != null) {
0695:
0696: if (aLand.getBounds().intersect(this .getBounds())
0697: && this .getUserOwner() == aLand.getUserOwner()) {
0698: //maybe intersect doesn't give the correct solution
0699: //maybe we should have to check manually using BoundingBox
0700: //XXX
0701:
0702: bounds = new BoundingPolytope(this .getBounds());
0703: bounds.combine(aLand.getBounds());
0704: this .setBounds(bounds);
0705: //this.currency = this.currency;
0706: //how to keep currency/price value:
0707: this .setPrice(Avatar.getWorldSpot(this .getUserOwner())
0708: .getTrade().convertPrice(aLand.getCurrency(),
0709: this .getCurrency(), aLand.getPrice()));
0710: //keep most restrictive rights:
0711:
0712: this .setOthersAccessRights(Avatar.PEERSLORD,
0713: this .othersAccessRights[0]
0714: & aLand.othersAccessRights[0]);
0715: this .setOthersAccessRights(Avatar.PEER,
0716: this .othersAccessRights[1]
0717: & aLand.othersAccessRights[1]);
0718: this .setOthersAccessRights(Avatar.PEERSVASSAL,
0719: this .othersAccessRights[2]
0720: & aLand.othersAccessRights[2]);
0721: this .setOthersAccessRights(Avatar.VASSAL,
0722: this .othersAccessRights[3]
0723: & aLand.othersAccessRights[3]);
0724:
0725: this .setOwnersObjectsDefaultRights(Avatar.PEERSLORD,
0726: this .ownersObjectsDefaultRights[0]
0727: & aLand.ownersObjectsDefaultRights[0]);
0728: this .setOwnersObjectsDefaultRights(Avatar.PEER,
0729: this .ownersObjectsDefaultRights[1]
0730: & aLand.ownersObjectsDefaultRights[1]);
0731: this .setOwnersObjectsDefaultRights(Avatar.PEERSVASSAL,
0732: this .ownersObjectsDefaultRights[2]
0733: & aLand.ownersObjectsDefaultRights[2]);
0734: this .setOwnersObjectsDefaultRights(Avatar.VASSAL,
0735: this .ownersObjectsDefaultRights[3]
0736: & aLand.ownersObjectsDefaultRights[3]);
0737:
0738: //remove aLand from database
0739:
0740: try {
0741: transaction = this .getPersistenceManager()
0742: .currentTransaction();
0743: transaction.begin();
0744:
0745: this .getPersistenceManager().refresh(this );
0746:
0747: transaction.commit();
0748: } catch (Exception exception) {
0749: }
0750:
0751: this .deleteVirtualElement(this );
0752:
0753: this .refreshHomes();
0754:
0755: try {
0756: transaction = this .getPersistenceManager()
0757: .currentTransaction();
0758: transaction.begin();
0759:
0760: extent = this .getPersistenceManager().getExtent(
0761: Avatar.class, true);
0762: filter = new String(
0763: "SELECT * FROM ObjectWorld o WHERE o.getBounds().intersect(this.getBounds())");
0764: query = this .getPersistenceManager().newQuery(
0765: Avatar.class, extent, filter);
0766: collection = (Collection) query.execute();
0767:
0768: transaction.commit();
0769:
0770: iterator = collection.iterator();
0771: while (iterator.hasNext()) {
0772: objectWorld = (ObjectWorld) iterator.next();
0773: objectWorld.refreshTransform();
0774: }
0775:
0776: try {
0777: transaction = this .getPersistenceManager()
0778: .currentTransaction();
0779: transaction.begin();
0780:
0781: extent = this .getPersistenceManager()
0782: .getExtent(Avatar.class, true);
0783: filter = new String(
0784: "SELECT * FROM BackgroundWorld b WHERE b.getBounds().intersect(this.getBounds())");
0785: query = this .getPersistenceManager().newQuery(
0786: Avatar.class, extent, filter);
0787: collection = (Collection) query.execute();
0788:
0789: transaction.commit();
0790:
0791: iterator = collection.iterator();
0792: while (iterator.hasNext()) {
0793: backgroundWorld = (BackgroundWorld) iterator
0794: .next();
0795: backgroundWorld.refreshBounds();
0796: }
0797:
0798: } catch (Exception exception) {
0799: }
0800:
0801: } catch (Exception exception) {
0802: }
0803:
0804: }
0805:
0806: }
0807:
0808: }
0809:
0810: //user must have the right to get full land access (all fields) for that method to work (or be the owner or one of its lords)
0811: //tries to reshape connected lands of the same user:
0812: //the aLand argument is set to the aLandBounds argument.
0813: //the bounds of this land are set accordingly to the new bounds of its neighbour
0814: //the resulting value is the modified lands array build out this land and aLand
0815: //it is up to the user to query the new bounds for this land if he wants.
0816: //the bounds argument must be inside the union of the lands.
0817: //It mustn't be the full union of the lands.
0818: public final Land[] reboundarize(Land aLand, Bounds aLandBounds) {
0819:
0820: Land[] lands;
0821: ExtendedBoundingPolytope unionBounds;
0822: Transaction transaction;
0823:
0824: lands = new Land[2];
0825:
0826: lands[0] = this ;
0827: lands[1] = aLand;
0828:
0829: if ((aLand != null) && (aLandBounds != null)) {
0830:
0831: if (this .getUserOwner() == aLand.getUserOwner()) {
0832:
0833: if (aLand.getBounds().intersect(this .getBounds())) {
0834: //maybe intersect doesn't give the correct solution
0835: //maybe we should have to check manually using BoundingBox
0836: //XXX
0837:
0838: unionBounds = new ExtendedBoundingPolytope(aLand
0839: .getBounds());
0840: unionBounds.combine(this .getBounds());
0841: //the bounds argument must be inside the union of the lands.
0842: //It mustn't be the full union of the lands.
0843: if (unionBounds.contains(aLandBounds)
0844: && (!unionBounds.subtract(aLandBounds)
0845: .isEmpty())) {
0846:
0847: aLand.setBounds(aLandBounds);
0848: this .setBounds(unionBounds
0849: .subtract(aLandBounds));
0850:
0851: //database should refresh this and aLand
0852:
0853: }
0854: }
0855:
0856: }
0857:
0858: }
0859:
0860: return lands;
0861:
0862: }
0863:
0864: private final void refreshHomes() {
0865:
0866: Transaction transaction;
0867: Extent extent;
0868: Query query;
0869: String filter;
0870: Collection collection;
0871: Iterator iterator;
0872: Avatar avatar;
0873:
0874: try {
0875: transaction = this .getPersistenceManager()
0876: .currentTransaction();
0877: transaction.begin();
0878:
0879: extent = this .getPersistenceManager().getExtent(Land.class,
0880: true);
0881: filter = new String(
0882: "SELECT Avatar FROM Avatar a WHERE this.getBounds().intersect(a.getHomePosition())");
0883: query = this .getPersistenceManager().newQuery(Land.class,
0884: extent, filter);
0885: collection = (Collection) query.execute();
0886:
0887: transaction.commit();
0888:
0889: iterator = collection.iterator();
0890: while (iterator.hasNext()) {
0891: avatar = (Avatar) iterator.next();
0892: if (avatar != this .getUserOwner()) {
0893: avatar.createHome();
0894: }
0895:
0896: }
0897:
0898: } catch (Exception exception) {
0899: }
0900:
0901: }
0902:
0903: //uses caller
0904: protected final boolean checkWritable(int capabilities) {
0905:
0906: int relation;
0907:
0908: relation = Avatar.getFeudalRelation(this .getUserOwner(), this
0909: .getCaller());
0910:
0911: if ((relation == Avatar.LORD) || (relation == Avatar.SELF)) {
0912: return true;
0913: } else {
0914: if (this .getOthersAccessRight(relation,
0915: VirtualElement.READ_WRITE)) {
0916: return this .getOwnersObjectsDefaultRights(relation,
0917: capabilities);
0918: } else {
0919: return false;
0920: }
0921: }
0922:
0923: }
0924:
0925: private final static HashSet filterCollection(Avatar caller,
0926: Collection collection) {
0927:
0928: Iterator iterator;
0929: Iterator iterator2;
0930: Collection passCollection;
0931: HashSet resultCollection;
0932: int relation;
0933: VirtualElement virtualElement;
0934: boolean found;
0935: Pass pass;
0936:
0937: resultCollection = new HashSet();
0938:
0939: if (caller != null) {
0940:
0941: //objects with a pass may bypass access
0942: passCollection = caller.getPass();
0943:
0944: iterator = collection.iterator();
0945:
0946: while (iterator.hasNext()) {
0947:
0948: virtualElement = (VirtualElement) iterator.next();
0949: relation = Avatar.getFeudalRelation(caller,
0950: virtualElement.getUserOwner());
0951:
0952: if ((relation == Avatar.LORD)
0953: || (relation == Avatar.SELF)) {
0954: resultCollection.add(virtualElement);
0955: } else {
0956: if (virtualElement.getOthersAccessRights(relation) != VirtualElement.HIDDEN) {
0957: resultCollection.add(virtualElement);
0958: } else {
0959: iterator2 = passCollection.iterator();
0960: found = false;
0961: while (iterator2.hasNext() && (!found)) {
0962: pass = (Pass) iterator2.next();
0963: found = (pass.getObject() == virtualElement);
0964: }
0965: if (found) {
0966: resultCollection.add(virtualElement);
0967: }
0968: }
0969: }
0970:
0971: }
0972:
0973: }
0974:
0975: return resultCollection;
0976:
0977: }
0978:
0979: //CALLS DEPENDING ON CAPABILITIES
0980:
0981: //time sliced actions
0982:
0983: //when there is a change in the bounds
0984: public void doBoundsChanged() {
0985:
0986: }
0987:
0988: //when there is a change in the capabilities
0989: public void doOwnersObjectsDefaultRightsChanged() {
0990:
0991: }
0992:
0993: //when an avatar observes
0994: public void doLook(Avatar avatar) {
0995:
0996: }
0997:
0998: //when an avatar quits land observation
0999: public void doUnLook(Avatar avatar) {
1000:
1001: }
1002:
1003: //when an avatar comes in this land
1004: public void doEnter(Avatar avatar) {
1005:
1006: }
1007:
1008: //when an avatar goes out of this land
1009: public void doGetOut(Avatar avatar) {
1010:
1011: }
1012:
1013: //when an avatar uses an imported object
1014: public void doUse(Avatar avatar, ObjectWorld objectWorld) {
1015:
1016: }
1017:
1018: //unuse detection is not always feasible
1019:
1020: //when an avatar drops its objects
1021: public void doDrop(Avatar avatar, ObjectWorld objectWorld) {
1022:
1023: }
1024:
1025: //object take is managed by object itself
1026:
1027: //INTERNAL CALLS
1028:
1029: //return expected value for positive value of int
1030: private static final boolean powerOfTwo(int value) {
1031:
1032: int i;
1033:
1034: i = 1;
1035:
1036: while (i < value) {
1037: i = i * 2;
1038: }
1039:
1040: return ((i == value) || (value == 0));
1041:
1042: /*
1043: //other implementation
1044: float floatValue;
1045:
1046: floatValue = value % 2;
1047:
1048: while ((value > 1) && (floatValue == 0 )) {
1049: value = value / 2;
1050: floatValue = value % 2;
1051: }
1052: return ((value = 1) || (value = 0));
1053:
1054: */
1055:
1056: }
1057:
1058: //return expected value for positive value of int
1059: private static final boolean powerOfThree(int value) {
1060:
1061: int i;
1062:
1063: i = 1;
1064:
1065: while (i < value) {
1066: i = i * 3;
1067: }
1068:
1069: return ((i == value) || (value == 0));
1070:
1071: /*
1072: //other implementation
1073: float floatValue;
1074:
1075: floatValue = value % 3;
1076:
1077: while ((value > 1) && (floatValue == 0 )) {
1078: value = value / 3;
1079: floatValue = value % 3;
1080: }
1081: return ((value = 1) || (value = 0));
1082:
1083: */
1084: }
1085:
1086: //value must be greater or equal 0
1087: private static final boolean isThreeNSet(int value) {
1088:
1089: int i;
1090: int val;
1091:
1092: if ((value % 3) == 0) {
1093:
1094: i = 1;
1095:
1096: while (i < value) {
1097: i = i * 3;
1098: }
1099:
1100: return ((i == value) || (value == 0));
1101:
1102: } else {
1103:
1104: if ((value % 2) == 0)
1105: val = value / 2;
1106: i = 1;
1107:
1108: while (i < value) {
1109: i = i * 3;
1110: }
1111:
1112: return ((i == value) || (value == 0));
1113:
1114: }
1115:
1116: }
1117:
1118: //powerOfTwoValue must be a pure power of two otherwise result is undefined
1119: //value and powerOfTwoValue must be greater or equal 1
1120: private static final boolean isPowerOfTwoChecked(int value,
1121: int powerOfTwoValue) {
1122:
1123: int val;
1124: int pOTV;
1125: int i;
1126:
1127: val = value;
1128: pOTV = powerOfTwoValue;
1129: i = 1;
1130:
1131: while (i < val) {
1132: i = i * 2;
1133: }
1134:
1135: if (pOTV >= i) {
1136: return false;
1137: } else {
1138: i = i / 2;
1139: if (pOTV == i) {
1140: return true;
1141: } else {
1142: val = val - i;
1143: while (pOTV < i) {
1144: if ((val - i) > 0) {
1145: val = val - i;
1146: }
1147: i = i / 2;
1148: }
1149: //(pOTV==i)
1150: if ((val - i) > 0) {
1151: return true;
1152: } else {
1153: return false;
1154: }
1155: }
1156: }
1157:
1158: }
1159:
1160: //powerOfThreeValue must be a pure power of two otherwise result is undefined
1161: //value and powerOfThreeValue must be greater or equal 1
1162: private static final boolean isPowerOfThreeChecked(int value,
1163: int powerOfThreeValue) {
1164:
1165: int val;
1166: int pOTV;
1167: int i;
1168:
1169: val = value;
1170: pOTV = powerOfThreeValue;
1171: i = 1;
1172:
1173: while (i < val) {
1174: i = i * 3;
1175: }
1176:
1177: if (pOTV >= i) {
1178: return false;
1179: } else {
1180: i = i / 3;
1181: if (pOTV == i) {
1182: return true;
1183: } else {
1184: val = val - i;
1185: while (pOTV < i) {
1186: if ((val - i) > 0) {
1187: val = val - i;
1188: }
1189: i = i / 3;
1190: }
1191: //(pOTV==i)
1192: if ((val - i) > 0) {
1193: return true;
1194: } else {
1195: return false;
1196: }
1197: }
1198: }
1199:
1200: }
1201:
1202: //threeSetValue must be equal to 2 * 3 power n or 3 power n otherwise result is undefined
1203: //value and threeSetValue must be greater or equal 1
1204: private static final boolean isThreeSetChecked(int value,
1205: int threeSetValue) {
1206:
1207: int val;
1208: int tSV;
1209: int i;
1210:
1211: val = value;
1212: tSV = threeSetValue;
1213: i = 1;
1214:
1215: while (i < val) {
1216: i = i * 3;
1217: }
1218:
1219: if (tSV >= i) {
1220: return false;
1221: } else {
1222: i = i / 3;
1223: if ((tSV == i) || (tSV == i * 2)) {
1224: return true;
1225: } else {
1226: if ((val - i) > i) {
1227: val = val - (2 * i);
1228: } else {
1229: val = val - i;
1230: }
1231: while (tSV < i) {
1232: if ((val - i) > 0) {
1233: if ((val - i) > i) {
1234: val = val - (2 * i);
1235: } else {
1236: val = val - i;
1237: }
1238: }
1239: i = i / 3;
1240: }
1241: //((tSV==i) || (tSV==i*2))
1242: if ((val - i) > 0) {
1243: return true;
1244: } else {
1245: return false;
1246: }
1247: }
1248: }
1249:
1250: }
1251:
1252: //threeSetValue must be equal to 2 * 3 power n or 3 power n otherwise result is undefined
1253: //value and threeSetValue must be greater or equal 1
1254: //returns one of VirtualElement.HIDDEN, VirtualElement.READ, VirtualElement.READ_WRITE
1255: //if threeSetValue is out of bounds VirtualElement.HIDDEN is returned
1256: private static final int getThreeSetCheck(int value,
1257: int threeSetValue) {
1258:
1259: int val;
1260: int tSV;
1261: int i;
1262:
1263: val = value;
1264: tSV = threeSetValue;
1265: i = 1;
1266:
1267: while (i < val) {
1268: i = i * 3;
1269: }
1270:
1271: if (tSV >= i) {
1272: return VirtualElement.HIDDEN;
1273: } else {
1274: i = i / 3;
1275: if (tSV == i) {
1276: return VirtualElement.READ;
1277: } else {
1278: if (tSV == i * 2) {
1279: return VirtualElement.READ_WRITE;
1280: } else {
1281: if ((val - i) > i) {
1282: val = val - (2 * i);
1283: } else {
1284: val = val - i;
1285: }
1286: while (tSV < i) {
1287: if ((val - i) > 0) {
1288: if ((val - i) > i) {
1289: val = val - (2 * i);
1290: } else {
1291: val = val - i;
1292: }
1293: }
1294: i = i / 3;
1295: }
1296: if ((val - i) > 0) {
1297: if (tSV == i) {
1298: return VirtualElement.READ;
1299: } else {
1300: if (tSV == i * 2) {
1301: return VirtualElement.READ_WRITE;
1302: } else {
1303: return VirtualElement.HIDDEN;
1304: }
1305: }
1306: } else {
1307: return VirtualElement.HIDDEN;
1308: }
1309: }
1310: }
1311: }
1312: }
1313:
1314: //threeSetValue must be equal to 2 * 3 power n or 3 power n otherwise result is undefined
1315: //value and threeSetValue must be greater or equal 1
1316: //desiredValue should be one of VirtualElement.HIDDEN, VirtualElement.READ, VirtualElement.READ_WRITE
1317: //returns the modified value
1318: private static final int setThreeSetCheck(int value,
1319: int threeSetValue, int desiredValue) {
1320:
1321: int val;
1322: int tSV;
1323: int i;
1324:
1325: val = value;
1326: tSV = threeSetValue;
1327: i = 1;
1328:
1329: while (i < val) {
1330: i = i * 3;
1331: }
1332:
1333: if (tSV >= i) {
1334: return value;
1335: } else {
1336: i = i / 3;
1337: if ((val - i) > i) {
1338: val = val - (2 * i);
1339: } else {
1340: val = val - i;
1341: }
1342: if ((tSV == i) || (tSV == i * 2)) {
1343: switch (desiredValue) {
1344: case VirtualElement.HIDDEN:
1345: return val;
1346: case VirtualElement.READ:
1347: return val + i;
1348: case VirtualElement.READ_WRITE:
1349: return val + (i * 2);
1350: default:
1351: return 0;
1352: }
1353: } else {
1354:
1355: while (tSV < i) {
1356: i = i / 3;
1357: if ((val - i) > 0) {
1358: if ((val - i) > i) {
1359: val = val - (2 * i);
1360: } else {
1361: val = val - i;
1362: }
1363: }
1364: }
1365:
1366: if ((tSV == i) || (tSV == i * 2)) {
1367: switch (desiredValue) {
1368: case VirtualElement.HIDDEN:
1369: return val;
1370: case VirtualElement.READ:
1371: return val + i;
1372: case VirtualElement.READ_WRITE:
1373: return val + (i * 2);
1374: default:
1375: return 0;
1376: }
1377: } else {
1378: return 0;
1379: }
1380:
1381: }
1382:
1383: }
1384:
1385: }
1386:
1387: //returns the int that corresponds to the operator Byte & Byte for 3 state "bytes"
1388: private static final int restrictThreeSetAccess(int firstThreeSet,
1389: int secondThreeSet) {
1390:
1391: int result;
1392: int i;
1393: int val1, val2;
1394:
1395: if (firstThreeSet > secondThreeSet) {
1396: return restrictThreeSetAccess(secondThreeSet, firstThreeSet);
1397: } else {
1398:
1399: result = 0;
1400: i = 1;
1401: val1 = firstThreeSet;
1402: val2 = secondThreeSet;
1403:
1404: while (i < val2) {
1405: i = i * 3;
1406: }
1407:
1408: i = i / 3;
1409: while ((val1 > 0) || (val2 > 0)) {
1410: if ((val2 - i) > i) {
1411: val2 = val2 - (2 * i);
1412: if ((val1 - i) > i) {
1413: val1 = val1 - (2 * i);
1414: result = result + (2 * i);
1415: } else {
1416: if ((val1 - i) > 0) {
1417: val1 = val1 - i;
1418: result = result + i;
1419: }
1420: }
1421: } else {
1422: val2 = val2 - i;
1423: if ((val1 - i) > i) {
1424: val1 = val1 - (2 * i);
1425: result = result + i;
1426: } else {
1427: if ((val1 - i) > 0) {
1428: val1 = val1 - i;
1429: result = result + i;
1430: }
1431: }
1432: }
1433: i = i / 3;
1434: }
1435:
1436: return result;
1437:
1438: }
1439:
1440: }
1441:
1442: }
|