summaryrefslogtreecommitdiff
path: root/NET/worlds/scape
diff options
context:
space:
mode:
authorFuwn <[email protected]>2026-02-12 22:33:32 -0800
committerFuwn <[email protected]>2026-02-12 22:33:32 -0800
commitc7a9d4a6bd53ed7d61731770f2f10e8b9fd435f9 (patch)
treedf9f48bf128a6c0186a8e91857d6ff30fe0e9f18 /NET/worlds/scape
downloadarchived-worldsplayer-c7a9d4a6bd53ed7d61731770f2f10e8b9fd435f9.tar.xz
archived-worldsplayer-c7a9d4a6bd53ed7d61731770f2f10e8b9fd435f9.zip
Initial commit
Diffstat (limited to 'NET/worlds/scape')
-rw-r--r--NET/worlds/scape/ASFSoundPlayer.java108
-rw-r--r--NET/worlds/scape/ASFThread.java83
-rw-r--r--NET/worlds/scape/Action.java70
-rw-r--r--NET/worlds/scape/Action_Animation.java24
-rw-r--r--NET/worlds/scape/Action_Motion.java38
-rw-r--r--NET/worlds/scape/Action_Toggle.java23
-rw-r--r--NET/worlds/scape/AddObjectAction.java69
-rw-r--r--NET/worlds/scape/AdvancingAction.java114
-rw-r--r--NET/worlds/scape/Animatable.java7
-rw-r--r--NET/worlds/scape/AnimateAction.java202
-rw-r--r--NET/worlds/scape/AnimatedAction.java203
-rw-r--r--NET/worlds/scape/AnimatedActionCallback.java5
-rw-r--r--NET/worlds/scape/AnimatedActionHandler.java9
-rw-r--r--NET/worlds/scape/AnimatedActionHandlerImp.java37
-rw-r--r--NET/worlds/scape/AnimatedActionManager.java329
-rw-r--r--NET/worlds/scape/AnimatingDoor.java301
-rw-r--r--NET/worlds/scape/Animation.java285
-rw-r--r--NET/worlds/scape/Attribute.java383
-rw-r--r--NET/worlds/scape/AudibilityFilter.java292
-rw-r--r--NET/worlds/scape/AudibleParams.java8
-rw-r--r--NET/worlds/scape/BGLoaded.java11
-rw-r--r--NET/worlds/scape/BackgroundLoader.java95
-rw-r--r--NET/worlds/scape/BackgroundLoaderElement.java87
-rw-r--r--NET/worlds/scape/BackgroundLoaderQueue.java158
-rw-r--r--NET/worlds/scape/BackgroundLoaderVector.java16
-rw-r--r--NET/worlds/scape/BadFormatException.java10
-rw-r--r--NET/worlds/scape/Billboard.java428
-rw-r--r--NET/worlds/scape/BizCard.java126
-rw-r--r--NET/worlds/scape/BooleanFieldEditorDialog.java21
-rw-r--r--NET/worlds/scape/BooleanPropertyEditor.java26
-rw-r--r--NET/worlds/scape/BoundBoxTemp.java84
-rw-r--r--NET/worlds/scape/BoxBumpCalc.java61
-rw-r--r--NET/worlds/scape/BuildRamp.java310
-rw-r--r--NET/worlds/scape/BuildStairs.java248
-rw-r--r--NET/worlds/scape/BumpAttribute.java56
-rw-r--r--NET/worlds/scape/BumpCalc.java10
-rw-r--r--NET/worlds/scape/BumpEventTemp.java151
-rw-r--r--NET/worlds/scape/BumpHandler.java5
-rw-r--r--NET/worlds/scape/BumpSensor.java21
-rw-r--r--NET/worlds/scape/CDAudio.java518
-rw-r--r--NET/worlds/scape/CDControl.java88
-rw-r--r--NET/worlds/scape/CDDBConnection.java75
-rw-r--r--NET/worlds/scape/CDDBHash.java76
-rw-r--r--NET/worlds/scape/CDDBHost.java24
-rw-r--r--NET/worlds/scape/CDDBLookup.java363
-rw-r--r--NET/worlds/scape/CDDBStatus.java52
-rw-r--r--NET/worlds/scape/CDDiskInfo.java94
-rw-r--r--NET/worlds/scape/CDPlayerAction.java258
-rw-r--r--NET/worlds/scape/CDPositionEditorDialog.java33
-rw-r--r--NET/worlds/scape/CDPositionPropertyEditor.java42
-rw-r--r--NET/worlds/scape/CDTrackInfo.java82
-rw-r--r--NET/worlds/scape/CallbackPropertyOperator.java44
-rw-r--r--NET/worlds/scape/Camera.java357
-rw-r--r--NET/worlds/scape/CameraHeightAction.java75
-rw-r--r--NET/worlds/scape/ChangeAvatarDialog.java60
-rw-r--r--NET/worlds/scape/ChangeAvatarImageButtons.java42
-rw-r--r--NET/worlds/scape/CheckboxEditorDialog.java64
-rw-r--r--NET/worlds/scape/ClassProperty.java7
-rw-r--r--NET/worlds/scape/ClickEventHandler.java13
-rw-r--r--NET/worlds/scape/ClickSensor.java359
-rw-r--r--NET/worlds/scape/ClickWidget.java17
-rw-r--r--NET/worlds/scape/ClipboardEntry.java44
-rw-r--r--NET/worlds/scape/ColorAttribute.java81
-rw-r--r--NET/worlds/scape/ColorEditorDialog.java68
-rw-r--r--NET/worlds/scape/ColorPropertyEditor.java19
-rw-r--r--NET/worlds/scape/CopyWidget.java14
-rw-r--r--NET/worlds/scape/CrashAction.java56
-rw-r--r--NET/worlds/scape/CutWidget.java14
-rw-r--r--NET/worlds/scape/DPAction.java220
-rw-r--r--NET/worlds/scape/DPLoadTracker.java44
-rw-r--r--NET/worlds/scape/DPState.java118
-rw-r--r--NET/worlds/scape/DeepEnumeration.java114
-rw-r--r--NET/worlds/scape/DialogAction.java118
-rw-r--r--NET/worlds/scape/DiffRoomSensor.java49
-rw-r--r--NET/worlds/scape/DirectShow.java51
-rw-r--r--NET/worlds/scape/DiskShadow.java61
-rw-r--r--NET/worlds/scape/DispenserAction.java98
-rw-r--r--NET/worlds/scape/DoorBasedFilter.java142
-rw-r--r--NET/worlds/scape/DoorBasedParams.java10
-rw-r--r--NET/worlds/scape/Drone.java864
-rw-r--r--NET/worlds/scape/DroneAnimator.java92
-rw-r--r--NET/worlds/scape/DroneLoader.java80
-rw-r--r--NET/worlds/scape/DropInfo.java19
-rw-r--r--NET/worlds/scape/DynamicForwardAttribute.java172
-rw-r--r--NET/worlds/scape/EditMusicDialog.java166
-rw-r--r--NET/worlds/scape/EditRoomDialog.java122
-rw-r--r--NET/worlds/scape/EditTile.java664
-rw-r--r--NET/worlds/scape/EnumFieldEditorDialog.java23
-rw-r--r--NET/worlds/scape/EnumProperties.java46
-rw-r--r--NET/worlds/scape/EnumPropertyEditor.java47
-rw-r--r--NET/worlds/scape/EquipAction.java35
-rw-r--r--NET/worlds/scape/EquippableItem.java136
-rw-r--r--NET/worlds/scape/Event.java74
-rw-r--r--NET/worlds/scape/EventQueue.java125
-rw-r--r--NET/worlds/scape/ExtensionFilter.java17
-rw-r--r--NET/worlds/scape/Facer.java14
-rw-r--r--NET/worlds/scape/FieldEditorDialog.java47
-rw-r--r--NET/worlds/scape/FieldWithListEditorDialog.java83
-rw-r--r--NET/worlds/scape/FileList.java132
-rw-r--r--NET/worlds/scape/FileTexture.java50
-rw-r--r--NET/worlds/scape/FileTextureDecoder.java15
-rw-r--r--NET/worlds/scape/FloatArrayEditorDialog.java50
-rw-r--r--NET/worlds/scape/FloatArrayPropertyEditor.java19
-rw-r--r--NET/worlds/scape/FloatFieldEditorDialog.java34
-rw-r--r--NET/worlds/scape/FloatPropertyEditor.java35
-rw-r--r--NET/worlds/scape/FloorPatch.java9
-rw-r--r--NET/worlds/scape/ForwardAttribute.java61
-rw-r--r--NET/worlds/scape/FrameEvent.java44
-rw-r--r--NET/worlds/scape/FrameHandler.java5
-rw-r--r--NET/worlds/scape/FrameSensor.java18
-rw-r--r--NET/worlds/scape/GravityAction.java189
-rw-r--r--NET/worlds/scape/HTransWidget.java20
-rw-r--r--NET/worlds/scape/Handler.java5
-rw-r--r--NET/worlds/scape/HandsOffDriver.java175
-rw-r--r--NET/worlds/scape/HighJump.java78
-rw-r--r--NET/worlds/scape/HoloCallback.java5
-rw-r--r--NET/worlds/scape/HoloDrone.java261
-rw-r--r--NET/worlds/scape/HoloPilot.java579
-rw-r--r--NET/worlds/scape/Hologram.java568
-rw-r--r--NET/worlds/scape/HorizontalRect.java38
-rw-r--r--NET/worlds/scape/Iconic.java9
-rw-r--r--NET/worlds/scape/ImageConverter.java181
-rw-r--r--NET/worlds/scape/IncrementalRestorer.java5
-rw-r--r--NET/worlds/scape/IndentStream.java94
-rw-r--r--NET/worlds/scape/IntegerFieldEditorDialog.java34
-rw-r--r--NET/worlds/scape/IntegerPropertyEditor.java35
-rw-r--r--NET/worlds/scape/InterpolatedDrone.java247
-rw-r--r--NET/worlds/scape/InventoryAction.java28
-rw-r--r--NET/worlds/scape/InventoryAvatar.java20
-rw-r--r--NET/worlds/scape/InventoryCallback.java5
-rw-r--r--NET/worlds/scape/InventoryDialog.java310
-rw-r--r--NET/worlds/scape/InventoryItem.java65
-rw-r--r--NET/worlds/scape/InventoryList.java26
-rw-r--r--NET/worlds/scape/InventoryManager.java315
-rw-r--r--NET/worlds/scape/ItemNotAvailableDialog.java42
-rw-r--r--NET/worlds/scape/Key.java53
-rw-r--r--NET/worlds/scape/KeyCharEvent.java12
-rw-r--r--NET/worlds/scape/KeyCharHandler.java5
-rw-r--r--NET/worlds/scape/KeyDownEvent.java12
-rw-r--r--NET/worlds/scape/KeyDownHandler.java5
-rw-r--r--NET/worlds/scape/KeyEvent.java19
-rw-r--r--NET/worlds/scape/KeyHandler.java5
-rw-r--r--NET/worlds/scape/KeyUpEvent.java12
-rw-r--r--NET/worlds/scape/KeyUpHandler.java5
-rw-r--r--NET/worlds/scape/LibEntContentEditorDialog.java131
-rw-r--r--NET/worlds/scape/LibEntContentPropertyEditor.java18
-rw-r--r--NET/worlds/scape/LibEventHandler.java5
-rw-r--r--NET/worlds/scape/LibrariesTile.java374
-rw-r--r--NET/worlds/scape/Library.java191
-rw-r--r--NET/worlds/scape/LibraryDrop.java5
-rw-r--r--NET/worlds/scape/LibraryDropTarget.java4
-rw-r--r--NET/worlds/scape/LibraryEntry.java141
-rw-r--r--NET/worlds/scape/Light.java58
-rw-r--r--NET/worlds/scape/ListAdderDialog.java84
-rw-r--r--NET/worlds/scape/ListChooserDialog.java55
-rw-r--r--NET/worlds/scape/ListEditorDialog.java36
-rw-r--r--NET/worlds/scape/LoadedAttribute.java5
-rw-r--r--NET/worlds/scape/LoadedURLSelf.java7
-rw-r--r--NET/worlds/scape/MCISoundCommand.java14
-rw-r--r--NET/worlds/scape/MCISoundPlayer.java161
-rw-r--r--NET/worlds/scape/MCIThread.java44
-rw-r--r--NET/worlds/scape/Manifest.java92
-rw-r--r--NET/worlds/scape/Material.java783
-rw-r--r--NET/worlds/scape/MaterialTexture.java201
-rw-r--r--NET/worlds/scape/MaybeNullDialog.java24
-rw-r--r--NET/worlds/scape/MaybeNullPropertyEditor.java21
-rw-r--r--NET/worlds/scape/MetaEnumeration.java38
-rw-r--r--NET/worlds/scape/Mirror.java34
-rw-r--r--NET/worlds/scape/MomentumBehavior.java7
-rw-r--r--NET/worlds/scape/MontyDoor.java185
-rw-r--r--NET/worlds/scape/MoreInfoDialog.java54
-rw-r--r--NET/worlds/scape/Motion.java398
-rw-r--r--NET/worlds/scape/MouseButtonEvent.java15
-rw-r--r--NET/worlds/scape/MouseButtonHandler.java5
-rw-r--r--NET/worlds/scape/MouseDeltaEvent.java17
-rw-r--r--NET/worlds/scape/MouseDeltaHandler.java5
-rw-r--r--NET/worlds/scape/MouseDownEvent.java27
-rw-r--r--NET/worlds/scape/MouseDownHandler.java5
-rw-r--r--NET/worlds/scape/MouseDragEvent.java12
-rw-r--r--NET/worlds/scape/MouseDragHandler.java5
-rw-r--r--NET/worlds/scape/MouseEnterEvent.java12
-rw-r--r--NET/worlds/scape/MouseEnterHandler.java5
-rw-r--r--NET/worlds/scape/MouseEvent.java17
-rw-r--r--NET/worlds/scape/MouseExitEvent.java12
-rw-r--r--NET/worlds/scape/MouseExitHandler.java5
-rw-r--r--NET/worlds/scape/MouseHandler.java5
-rw-r--r--NET/worlds/scape/MouseMoveEvent.java12
-rw-r--r--NET/worlds/scape/MouseMoveHandler.java5
-rw-r--r--NET/worlds/scape/MousePositionEvent.java12
-rw-r--r--NET/worlds/scape/MousePositionHandler.java5
-rw-r--r--NET/worlds/scape/MouseUpEvent.java17
-rw-r--r--NET/worlds/scape/MouseUpHandler.java5
-rw-r--r--NET/worlds/scape/MoveAction.java444
-rw-r--r--NET/worlds/scape/MoveCameraAction.java85
-rw-r--r--NET/worlds/scape/MultiManifestAction.java112
-rw-r--r--NET/worlds/scape/MultiMotion.java531
-rw-r--r--NET/worlds/scape/MusicManager.java258
-rw-r--r--NET/worlds/scape/MusicManagerDialog.java397
-rw-r--r--NET/worlds/scape/MusicRoom.java32
-rw-r--r--NET/worlds/scape/MusicTrack.java52
-rw-r--r--NET/worlds/scape/MutedDrone.java46
-rw-r--r--NET/worlds/scape/MyButton.java14
-rw-r--r--NET/worlds/scape/NamedPortal.java33
-rw-r--r--NET/worlds/scape/NametagDrone.java50
-rw-r--r--NET/worlds/scape/NoSuchPropertyException.java4
-rw-r--r--NET/worlds/scape/NonPersister.java4
-rw-r--r--NET/worlds/scape/NotifyScriptAction.java57
-rw-r--r--NET/worlds/scape/NumberAttribute.java81
-rw-r--r--NET/worlds/scape/ObjEditorDialog.java12
-rw-r--r--NET/worlds/scape/ObjPropertyEditor.java37
-rw-r--r--NET/worlds/scape/ObjectAdderDialog.java12
-rw-r--r--NET/worlds/scape/ObjectPropertyAdder.java42
-rw-r--r--NET/worlds/scape/ObjectSelectorDialog.java91
-rw-r--r--NET/worlds/scape/OpenURLAction.java124
-rw-r--r--NET/worlds/scape/ParallelAction.java140
-rw-r--r--NET/worlds/scape/PassthroughBumpCalc.java33
-rw-r--r--NET/worlds/scape/PasteWidget.java14
-rw-r--r--NET/worlds/scape/PathMoveAction.java24
-rw-r--r--NET/worlds/scape/PendingCacheDrone.java66
-rw-r--r--NET/worlds/scape/PendingDrone.java303
-rw-r--r--NET/worlds/scape/PeriodicTimeSensor.java80
-rw-r--r--NET/worlds/scape/Persister.java11
-rw-r--r--NET/worlds/scape/PickEvent.java19
-rw-r--r--NET/worlds/scape/PickHandler.java5
-rw-r--r--NET/worlds/scape/PickUpAction.java33
-rw-r--r--NET/worlds/scape/Pilot.java853
-rw-r--r--NET/worlds/scape/PitchDriver.java196
-rw-r--r--NET/worlds/scape/PitchWidget.java19
-rw-r--r--NET/worlds/scape/PlaneBumpCalc.java65
-rw-r--r--NET/worlds/scape/PlaybackRecordingAction.java59
-rw-r--r--NET/worlds/scape/Point2.java129
-rw-r--r--NET/worlds/scape/Point2EditorDialog.java66
-rw-r--r--NET/worlds/scape/Point2PropertyEditor.java19
-rw-r--r--NET/worlds/scape/Point3.java47
-rw-r--r--NET/worlds/scape/Point3EditorDialog.java71
-rw-r--r--NET/worlds/scape/Point3PropertyEditor.java19
-rw-r--r--NET/worlds/scape/Point3Temp.java168
-rw-r--r--NET/worlds/scape/Polygon.java75
-rw-r--r--NET/worlds/scape/Portal.java831
-rw-r--r--NET/worlds/scape/PosableAction.java74
-rw-r--r--NET/worlds/scape/PosableDrone.java197
-rw-r--r--NET/worlds/scape/PosableDroneLoader.java84
-rw-r--r--NET/worlds/scape/PosableShape.java1331
-rw-r--r--NET/worlds/scape/Postrenderable.java5
-rw-r--r--NET/worlds/scape/PostspinBehavior.java130
-rw-r--r--NET/worlds/scape/Prerenderable.java5
-rw-r--r--NET/worlds/scape/PrintAction.java71
-rw-r--r--NET/worlds/scape/ProgressiveAdder.java49
-rw-r--r--NET/worlds/scape/PropAdder.java48
-rw-r--r--NET/worlds/scape/PropEditor.java18
-rw-r--r--NET/worlds/scape/PropList.java119
-rw-r--r--NET/worlds/scape/PropPropEditor.java27
-rw-r--r--NET/worlds/scape/PropPropEditorDialog.java55
-rw-r--r--NET/worlds/scape/PropTreeNode.java142
-rw-r--r--NET/worlds/scape/Properties.java14
-rw-r--r--NET/worlds/scape/Property.java153
-rw-r--r--NET/worlds/scape/ProximitySensor.java149
-rw-r--r--NET/worlds/scape/RPAction.java12
-rw-r--r--NET/worlds/scape/Rect.java421
-rw-r--r--NET/worlds/scape/RectPatch.java401
-rw-r--r--NET/worlds/scape/Recycler.java75
-rw-r--r--NET/worlds/scape/RelativeMoveAction.java196
-rw-r--r--NET/worlds/scape/RemotePortal.java73
-rw-r--r--NET/worlds/scape/RemoveObjectAction.java72
-rw-r--r--NET/worlds/scape/RenderWare.java7
-rw-r--r--NET/worlds/scape/Restorer.java430
-rw-r--r--NET/worlds/scape/RollBehavior.java79
-rw-r--r--NET/worlds/scape/RollWidget.java21
-rw-r--r--NET/worlds/scape/RollingAttribute.java188
-rw-r--r--NET/worlds/scape/Room.java996
-rw-r--r--NET/worlds/scape/RoomEnvironment.java116
-rw-r--r--NET/worlds/scape/RoomSubscribeInfo.java15
-rw-r--r--NET/worlds/scape/RunningActionCallback.java5
-rw-r--r--NET/worlds/scape/RunningActionHandler.java153
-rw-r--r--NET/worlds/scape/SameRoomSensor.java60
-rw-r--r--NET/worlds/scape/SaveWidget.java31
-rw-r--r--NET/worlds/scape/Saver.java174
-rw-r--r--NET/worlds/scape/ScaleWidget.java23
-rw-r--r--NET/worlds/scape/ScapePicMovie.java140
-rw-r--r--NET/worlds/scape/ScapePicTexture.java94
-rw-r--r--NET/worlds/scape/ScapePicTextureDecoder.java15
-rw-r--r--NET/worlds/scape/ScrollingImagePanel.java398
-rw-r--r--NET/worlds/scape/ScrollingListElement.java17
-rw-r--r--NET/worlds/scape/SelectAvatarAction.java152
-rw-r--r--NET/worlds/scape/SendURLAction.java442
-rw-r--r--NET/worlds/scape/Sensor.java99
-rw-r--r--NET/worlds/scape/SensorFrameHandler.java17
-rw-r--r--NET/worlds/scape/SeqFile.java29
-rw-r--r--NET/worlds/scape/SequenceAction.java135
-rw-r--r--NET/worlds/scape/SequenceActionState.java91
-rw-r--r--NET/worlds/scape/SetBooleanAction.java57
-rw-r--r--NET/worlds/scape/SetColorAction.java108
-rw-r--r--NET/worlds/scape/SetFloatAction.java82
-rw-r--r--NET/worlds/scape/SetIntegerAction.java82
-rw-r--r--NET/worlds/scape/SetPoint2Action.java115
-rw-r--r--NET/worlds/scape/SetPoint3Action.java125
-rw-r--r--NET/worlds/scape/SetPropertyAction.java270
-rw-r--r--NET/worlds/scape/SetStringAction.java57
-rw-r--r--NET/worlds/scape/SetURLAction.java68
-rw-r--r--NET/worlds/scape/SetVisibleBumpableAction.java73
-rw-r--r--NET/worlds/scape/SetZoomMode.java61
-rw-r--r--NET/worlds/scape/Shadow.java5
-rw-r--r--NET/worlds/scape/ShallowEnumeration.java38
-rw-r--r--NET/worlds/scape/Shape.java557
-rw-r--r--NET/worlds/scape/ShapeLoader.java113
-rw-r--r--NET/worlds/scape/ShapeLoaderListener.java5
-rw-r--r--NET/worlds/scape/ShapeTextureLoader.java27
-rw-r--r--NET/worlds/scape/Sharer.java590
-rw-r--r--NET/worlds/scape/SlidePropertyAction.java65
-rw-r--r--NET/worlds/scape/SmoothDriver.java473
-rw-r--r--NET/worlds/scape/Sound.java623
-rw-r--r--NET/worlds/scape/SoundCallback.java28
-rw-r--r--NET/worlds/scape/SoundPlayer.java31
-rw-r--r--NET/worlds/scape/SoundResource.java89
-rw-r--r--NET/worlds/scape/SoundState.java307
-rw-r--r--NET/worlds/scape/SpinBehavior.java122
-rw-r--r--NET/worlds/scape/StandardTexture.java45
-rw-r--r--NET/worlds/scape/StandardTextureDecoder.java15
-rw-r--r--NET/worlds/scape/StartupSensor.java41
-rw-r--r--NET/worlds/scape/State.java5
-rw-r--r--NET/worlds/scape/StateContext.java5
-rw-r--r--NET/worlds/scape/StdoutAction.java96
-rw-r--r--NET/worlds/scape/StopRecordingAction.java36
-rw-r--r--NET/worlds/scape/StringAttribute.java81
-rw-r--r--NET/worlds/scape/StringFieldEditorDialog.java31
-rw-r--r--NET/worlds/scape/StringPropertyEditor.java19
-rw-r--r--NET/worlds/scape/StringTexture.java103
-rw-r--r--NET/worlds/scape/SubclumpShape.java47
-rw-r--r--NET/worlds/scape/SuperRoot.java388
-rw-r--r--NET/worlds/scape/Surface.java190
-rw-r--r--NET/worlds/scape/SwitchableBehavior.java62
-rw-r--r--NET/worlds/scape/TCompressor.java465
-rw-r--r--NET/worlds/scape/TabbedDisplayPanel.java98
-rw-r--r--NET/worlds/scape/TabbedPanel.java274
-rw-r--r--NET/worlds/scape/TalkAction.java66
-rw-r--r--NET/worlds/scape/Teleport.java122
-rw-r--r--NET/worlds/scape/TeleportAction.java539
-rw-r--r--NET/worlds/scape/TeleportDialog.java44
-rw-r--r--NET/worlds/scape/TeleportStatus.java5
-rw-r--r--NET/worlds/scape/Texture.java102
-rw-r--r--NET/worlds/scape/TextureDecoder.java73
-rw-r--r--NET/worlds/scape/TextureSurface.java85
-rw-r--r--NET/worlds/scape/TextureSurfaceRenderer.java5
-rw-r--r--NET/worlds/scape/Toggle.java165
-rw-r--r--NET/worlds/scape/ToggleZoomMode.java20
-rw-r--r--NET/worlds/scape/TooNewException.java10
-rw-r--r--NET/worlds/scape/ToolBar.java238
-rw-r--r--NET/worlds/scape/ToolTipManager.java102
-rw-r--r--NET/worlds/scape/TradeAction.java151
-rw-r--r--NET/worlds/scape/TrajectoryBehavior.java305
-rw-r--r--NET/worlds/scape/TransAttribute.java214
-rw-r--r--NET/worlds/scape/Transform.java362
-rw-r--r--NET/worlds/scape/TransformEditorDialog.java341
-rw-r--r--NET/worlds/scape/TransformPropertyEditor.java19
-rw-r--r--NET/worlds/scape/Trigger.java199
-rw-r--r--NET/worlds/scape/TriggeredSwitchableBehavior.java11
-rw-r--r--NET/worlds/scape/TwoWayPortal.java64
-rw-r--r--NET/worlds/scape/URLEditorDialog.java54
-rw-r--r--NET/worlds/scape/URLPropertyEditor.java73
-rw-r--r--NET/worlds/scape/URLSelf.java13
-rw-r--r--NET/worlds/scape/URLSelfLoader.java182
-rw-r--r--NET/worlds/scape/UndoStack.java41
-rw-r--r--NET/worlds/scape/UndoWidget.java14
-rw-r--r--NET/worlds/scape/UndoabCopy.java14
-rw-r--r--NET/worlds/scape/UndoablAdd.java21
-rw-r--r--NET/worlds/scape/UndoablCut.java23
-rw-r--r--NET/worlds/scape/UndoablDelete.java19
-rw-r--r--NET/worlds/scape/UndoablPaste.java16
-rw-r--r--NET/worlds/scape/UndoablSet.java17
-rw-r--r--NET/worlds/scape/UndoablTransform.java16
-rw-r--r--NET/worlds/scape/Undoable.java5
-rw-r--r--NET/worlds/scape/UniqueHasher.java31
-rw-r--r--NET/worlds/scape/UnitEnumeration.java23
-rw-r--r--NET/worlds/scape/UniverseHandler.java66
-rw-r--r--NET/worlds/scape/UserEvent.java12
-rw-r--r--NET/worlds/scape/UserHandler.java5
-rw-r--r--NET/worlds/scape/VTransWidget.java19
-rw-r--r--NET/worlds/scape/ValueEvent.java15
-rw-r--r--NET/worlds/scape/ValueHandler.java5
-rw-r--r--NET/worlds/scape/VectorProperty.java76
-rw-r--r--NET/worlds/scape/VehicleDriver.java653
-rw-r--r--NET/worlds/scape/VehicleShape.java571
-rw-r--r--NET/worlds/scape/VelocityBehavior.java260
-rw-r--r--NET/worlds/scape/VideoControlAction.java115
-rw-r--r--NET/worlds/scape/VideoManager.java29
-rw-r--r--NET/worlds/scape/VideoSurface.java53
-rw-r--r--NET/worlds/scape/VideoTexture.java232
-rw-r--r--NET/worlds/scape/VideoWall.java191
-rw-r--r--NET/worlds/scape/VisiAttribute.java56
-rw-r--r--NET/worlds/scape/WMPSoundPlayer.java65
-rw-r--r--NET/worlds/scape/WObject.java1450
-rw-r--r--NET/worlds/scape/WObjectHighlighter.java52
-rw-r--r--NET/worlds/scape/WaitAction.java91
-rw-r--r--NET/worlds/scape/WaitActionState.java41
-rw-r--r--NET/worlds/scape/WavSoundPlayer.java275
-rw-r--r--NET/worlds/scape/WavSoundTerminator.java21
-rw-r--r--NET/worlds/scape/WearAction.java339
-rw-r--r--NET/worlds/scape/WearWall.java223
-rw-r--r--NET/worlds/scape/WebPageWall.java408
-rw-r--r--NET/worlds/scape/WebWallControlAction.java128
-rw-r--r--NET/worlds/scape/Whiteboard.java96
-rw-r--r--NET/worlds/scape/WidgetButton.java125
-rw-r--r--NET/worlds/scape/WobClassLoader.java96
-rw-r--r--NET/worlds/scape/WobLoaded.java5
-rw-r--r--NET/worlds/scape/WobLoader.java107
-rw-r--r--NET/worlds/scape/World.java1157
-rw-r--r--NET/worlds/scape/WorldRedirector.java79
-rw-r--r--NET/worlds/scape/WorldScript.java47
-rw-r--r--NET/worlds/scape/WorldScriptLoader.java109
-rw-r--r--NET/worlds/scape/WorldScriptManager.java164
-rw-r--r--NET/worlds/scape/WorldScriptToolkit.java100
-rw-r--r--NET/worlds/scape/WorldScriptToolkitImp.java429
-rw-r--r--NET/worlds/scape/WorldValidator.java84
-rw-r--r--NET/worlds/scape/WrRamp.java207
-rw-r--r--NET/worlds/scape/WrRectPatch.java19
-rw-r--r--NET/worlds/scape/WrStaircase.java137
-rw-r--r--NET/worlds/scape/WrVisiRectPatch.java46
-rw-r--r--NET/worlds/scape/YawWidget.java21
-rw-r--r--NET/worlds/scape/sendURL.java156
419 files changed, 51033 insertions, 0 deletions
diff --git a/NET/worlds/scape/ASFSoundPlayer.java b/NET/worlds/scape/ASFSoundPlayer.java
new file mode 100644
index 0000000..1f87064
--- /dev/null
+++ b/NET/worlds/scape/ASFSoundPlayer.java
@@ -0,0 +1,108 @@
+package NET.worlds.scape;
+
+import NET.worlds.network.URL;
+
+public class ASFSoundPlayer extends MCISoundPlayer {
+ float ang;
+ float dist;
+ float vol;
+ int leftToRepeat;
+ int running;
+ private URL url;
+
+ public ASFSoundPlayer(Sound owner) {
+ super(owner);
+ }
+
+ @Override
+ public boolean open(float volume, float stopDist, boolean atten, boolean pan) {
+ return true;
+ }
+
+ @Override
+ public void close() {
+ this.stop();
+ }
+
+ @Override
+ public boolean position(Point3Temp cam, Point3Temp obj, Point3Temp out, Point3Temp up) {
+ Point3Temp toObj = Point3Temp.make(obj).minus(cam);
+ Point3Temp right = Point3Temp.make(out).cross(up);
+ float y = toObj.dot(out);
+ float x = toObj.dot(right);
+ this.ang = (float)(Math.atan2(y, x) / Math.PI);
+ this.dist = toObj.length();
+ return this.setVolume(this.vol);
+ }
+
+ @Override
+ public boolean setVolume(float v) {
+ return true;
+ }
+
+ @Override
+ public int getState() {
+ this.gotFinished(!ASFThread.isActive());
+ return this.running != 0 ? 0 : 1;
+ }
+
+ @Override
+ public synchronized void start(int repeatCount) {
+ if (repeatCount == 0) {
+ this.running = 0;
+ } else {
+ this.leftToRepeat = repeatCount;
+ if (this.leftToRepeat > 0) {
+ this.leftToRepeat--;
+ }
+
+ this.running = 1;
+ URL myURL = this.owner == null ? this.url : this.owner.getURL();
+ this.running = 2;
+ new ASFThread(myURL, this);
+ }
+ }
+
+ @Override
+ public synchronized void start(URL u) {
+ this.url = u;
+ this.start(1);
+ }
+
+ public static void pauseSystem() {
+ ASFThread.pauseASF();
+ WavSoundPlayer.pauseSystemExceptASF();
+ }
+
+ public static void resumeSystem() {
+ ASFThread.resumeASF();
+ WavSoundPlayer.resumeSystemExceptASF();
+ }
+
+ @Override
+ synchronized void gotFinished(boolean f) {
+ if (f && this.running == 2) {
+ this.start(this.leftToRepeat);
+ }
+ }
+
+ @Override
+ public synchronized void stop() {
+ this.leftToRepeat = 0;
+ ASFThread.stopASF();
+ }
+
+ @Override
+ public void volume(float left, float right) {
+ }
+
+ public static synchronized boolean isActive() {
+ return ASFThread.isActive();
+ }
+
+ static synchronized void shutdown() {
+ ASFThread.stopASF();
+ }
+
+ static native boolean nativePlay(String var0);
+}
diff --git a/NET/worlds/scape/ASFThread.java b/NET/worlds/scape/ASFThread.java
new file mode 100644
index 0000000..a9e043f
--- /dev/null
+++ b/NET/worlds/scape/ASFThread.java
@@ -0,0 +1,83 @@
+package NET.worlds.scape;
+
+import NET.worlds.network.Cache;
+import NET.worlds.network.CacheFile;
+import NET.worlds.network.URL;
+
+class ASFThread extends Thread {
+ private URL url;
+ private ASFSoundPlayer player;
+ private static ASFThread asfThread;
+ private static boolean paused;
+
+ ASFThread(URL url, ASFSoundPlayer player) {
+ this.url = url;
+ this.player = player;
+ setASF(this);
+ }
+
+ @Override
+ public void run() {
+ CacheFile cf = Cache.getFile(this.url);
+ cf.waitUntilLoaded();
+ if (cf.error()) {
+ this.player.running = 3;
+ releaseASF(this);
+ } else if (!paused) {
+ String localName = cf.getLocalName().replace('/', '\\');
+ if (!ASFSoundPlayer.nativePlay(localName)) {
+ this.player.running = 3;
+ }
+
+ releaseASF(this);
+ }
+ }
+
+ static synchronized void pauseASF() {
+ if (!paused && asfThread != null) {
+ ASFThread t = asfThread;
+ stopASF();
+ paused = true;
+ new ASFThread(t.url, t.player);
+ }
+
+ paused = true;
+ }
+
+ static synchronized void resumeASF() {
+ if (paused) {
+ ASFThread t = asfThread;
+ paused = false;
+ if (t != null) {
+ new ASFThread(t.url, t.player);
+ }
+ }
+ }
+
+ static synchronized void releaseASF(ASFThread t) {
+ if (asfThread == t) {
+ asfThread = null;
+ }
+ }
+
+ static synchronized void setASF(ASFThread t) {
+ if (asfThread == null || !asfThread.url.equals(t.url)) {
+ asfThread = t;
+ asfThread.setDaemon(true);
+ asfThread.start();
+ }
+ }
+
+ static synchronized void stopASF() {
+ if (asfThread != null) {
+ asfThread = null;
+ if (!paused) {
+ ASFSoundPlayer.nativePlay("");
+ }
+ }
+ }
+
+ static boolean isActive() {
+ return asfThread != null;
+ }
+}
diff --git a/NET/worlds/scape/Action.java b/NET/worlds/scape/Action.java
new file mode 100644
index 0000000..98abf35
--- /dev/null
+++ b/NET/worlds/scape/Action.java
@@ -0,0 +1,70 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+public abstract class Action extends SuperRoot {
+ public String rightMenuLabel;
+ private static Object classCookie = new Object();
+
+ public abstract Persister trigger(Event var1, Persister var2);
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(4, classCookie);
+ s.saveString(this.rightMenuLabel);
+ super.saveState(s);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 1:
+ r.restoreInt();
+ this.setName(r.restoreString());
+ case 0:
+ r.setOldFlag();
+ break;
+ case 2:
+ r.setOldFlag();
+ super.restoreState(r);
+ r.restoreInt();
+ break;
+ case 4:
+ this.rightMenuLabel = r.restoreString();
+ case 3:
+ super.restoreState(r);
+ break;
+ default:
+ throw new TooNewException();
+ }
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Trigger Now"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(false);
+ } else if (mode == 2 && (Boolean)value) {
+ RunningActionHandler.trigger(this, this.getWorld(), null);
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Right Menu Label").allowSetNull());
+ } else if (mode == 1) {
+ ret = this.rightMenuLabel;
+ } else if (mode == 2) {
+ this.rightMenuLabel = (String)value;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 2, mode, value);
+ }
+
+ return ret;
+ }
+}
diff --git a/NET/worlds/scape/Action_Animation.java b/NET/worlds/scape/Action_Animation.java
new file mode 100644
index 0000000..615cea3
--- /dev/null
+++ b/NET/worlds/scape/Action_Animation.java
@@ -0,0 +1,24 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+public class Action_Animation extends Action {
+ @Override
+ public Persister trigger(Event e, Persister seqID) {
+ return null;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ assert false;
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException {
+ AnimateAction a = new AnimateAction();
+ r.replace(this, a);
+ a.cycleTime = (int)r.restoreFloat();
+ a.cycles = r.restoreInt();
+ a.frameList = r.restoreString();
+ }
+}
diff --git a/NET/worlds/scape/Action_Motion.java b/NET/worlds/scape/Action_Motion.java
new file mode 100644
index 0000000..b7eaaa0
--- /dev/null
+++ b/NET/worlds/scape/Action_Motion.java
@@ -0,0 +1,38 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+public class Action_Motion extends Action {
+ @Override
+ public Persister trigger(Event e, Persister seqID) {
+ return null;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ assert false;
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException {
+ MoveAction a = new MoveAction();
+ r.replace(this, a);
+ a.cycleTime = (int)r.restoreFloat();
+ a.cycles = r.restoreInt();
+
+ try {
+ a.extentPoint.restoreState(r);
+ a.startPoint.restoreState(r);
+ a.extentScale.restoreState(r);
+ a.startScale.restoreState(r);
+ a.extentSpin.restoreState(r);
+ a.startSpin.restoreState(r);
+ } catch (Exception var4) {
+ }
+
+ a.extentRotation = r.restoreFloat();
+ a.startRotation = r.restoreFloat();
+ a.extentPoint.minus(a.startPoint);
+ a.extentScale.dividedBy(a.startScale);
+ }
+}
diff --git a/NET/worlds/scape/Action_Toggle.java b/NET/worlds/scape/Action_Toggle.java
new file mode 100644
index 0000000..4be876b
--- /dev/null
+++ b/NET/worlds/scape/Action_Toggle.java
@@ -0,0 +1,23 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+class Action_Toggle extends Action {
+ @Override
+ public Persister trigger(Event e, Persister seqID) {
+ return null;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ assert false;
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException {
+ SetVisibleBumpableAction a = new SetVisibleBumpableAction();
+ r.replace(this, a);
+ a.targetBumpable = r.restoreBoolean();
+ a.targetVisible = r.restoreBoolean();
+ }
+}
diff --git a/NET/worlds/scape/AddObjectAction.java b/NET/worlds/scape/AddObjectAction.java
new file mode 100644
index 0000000..2a43f2d
--- /dev/null
+++ b/NET/worlds/scape/AddObjectAction.java
@@ -0,0 +1,69 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+import java.util.Vector;
+
+public class AddObjectAction extends SetPropertyAction {
+ private SuperRoot _value;
+ private static Object classCookie = new Object();
+
+ @Override
+ public Persister trigger(Event e, Persister seqID) {
+ assert !this.useParam();
+
+ this.add((Object)this._value);
+ return null;
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ VectorProperty vp = new VectorProperty(this, index, "Object to Add");
+ if (this._value != null) {
+ vp.allowSetNull();
+ ret = vp;
+ }
+ } else if (mode == 1) {
+ ret = new Vector(1);
+ if (this._value != null) {
+ ((Vector)ret).addElement(this._value);
+ }
+ } else if (mode == 4) {
+ assert value == this._value;
+
+ this._value = null;
+ } else if (mode == 3) {
+ assert this._value == null;
+
+ this._value = (SuperRoot)value;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 1, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(1, classCookie);
+ super.saveState(s);
+ s.saveMaybeNull(this._value);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 1:
+ super.restoreState(r);
+ this._value = (SuperRoot)r.restoreMaybeNull();
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/AdvancingAction.java b/NET/worlds/scape/AdvancingAction.java
new file mode 100644
index 0000000..909b1b2
--- /dev/null
+++ b/NET/worlds/scape/AdvancingAction.java
@@ -0,0 +1,114 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Vector;
+
+public class AdvancingAction extends Action {
+ private Vector actions = new Vector();
+ private int nextAction = 0;
+ boolean singleTrigger = true;
+ boolean inProgress = false;
+ private static Object classCookie = new Object();
+
+ @Override
+ public Persister trigger(Event evt, Persister seqID) {
+ if (this.singleTrigger && this.inProgress && seqID == null) {
+ return null;
+ } else {
+ if (this.nextAction >= this.actions.size()) {
+ this.nextAction = 0;
+ }
+
+ Action act = (Action)this.actions.elementAt(this.nextAction);
+ Persister id = null;
+ if (act != null) {
+ id = act.trigger(evt, seqID);
+ this.inProgress = id != null;
+ }
+
+ if (id == null || !this.singleTrigger) {
+ this.nextAction++;
+ }
+
+ return id;
+ }
+ }
+
+ public void addComponent(Action act) {
+ this.actions.addElement(act);
+ }
+
+ public void insertComponent(Action act, int index) {
+ this.actions.insertElementAt(act, index);
+ }
+
+ public boolean removeComponent(Action act) {
+ return this.actions.removeElement(act);
+ }
+
+ public Enumeration getComponents() {
+ return this.actions.elements();
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ VectorProperty vp = new VectorProperty(this, index, "Components");
+ vp.allowSorting(false);
+ ret = ObjectPropertyAdder.make(vp, this.getRoot(), "NET.worlds.scape.Action");
+ } else if (mode == 1) {
+ ret = this.actions.clone();
+ } else if (mode == 4) {
+ this.actions.removeElement(value);
+ } else if (mode == 3) {
+ this.actions.addElement((Action)value);
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Prevent overlapping actions"), "Overlapping", "One at a time");
+ } else if (mode == 1) {
+ ret = new Boolean(this.singleTrigger);
+ } else if (mode == 2) {
+ this.singleTrigger = (Boolean)value;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 2, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(1, classCookie);
+ super.saveState(s);
+ s.saveVector(this.actions);
+ s.saveInt(this.nextAction);
+ s.saveBoolean(this.singleTrigger);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ this.actions = r.restoreVector();
+ this.nextAction = r.restoreInt();
+ break;
+ case 1:
+ super.restoreState(r);
+ this.actions = r.restoreVector();
+ this.nextAction = r.restoreInt();
+ this.singleTrigger = r.restoreBoolean();
+ break;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/Animatable.java b/NET/worlds/scape/Animatable.java
new file mode 100644
index 0000000..d5fb63e
--- /dev/null
+++ b/NET/worlds/scape/Animatable.java
@@ -0,0 +1,7 @@
+package NET.worlds.scape;
+
+public interface Animatable {
+ boolean hasClump();
+
+ void setMaterial(Material var1);
+}
diff --git a/NET/worlds/scape/AnimateAction.java b/NET/worlds/scape/AnimateAction.java
new file mode 100644
index 0000000..44f2520
--- /dev/null
+++ b/NET/worlds/scape/AnimateAction.java
@@ -0,0 +1,202 @@
+package NET.worlds.scape;
+
+import NET.worlds.core.Std;
+import java.io.IOException;
+
+public class AnimateAction extends Action {
+ int startTime;
+ public int cycleTime = 1000;
+ public String frameList = "";
+ protected int frameListCount = 0;
+ protected Material[] frameMaterialArray = null;
+ public int cycles = 0;
+ public boolean infiniteLoop = false;
+ protected int cycleNo;
+ protected int currentFrameNo;
+ private boolean running = false;
+ private static Object classCookie = new Object();
+
+ public AnimateAction() {
+ this.startAnimation();
+ }
+
+ public void startAnimation() {
+ this.cycleNo = 0;
+ this.currentFrameNo = -1;
+ this.startTime = Std.getRealTime();
+ }
+
+ public void preprocessFrameList(String frameList) {
+ this.frameMaterialArray = AnimatingDoor.namesToMaterialArray(this, frameList);
+ this.frameListCount = this.frameMaterialArray == null ? 0 : this.frameMaterialArray.length;
+ }
+
+ @Override
+ public void detach() {
+ if (this.frameMaterialArray != null) {
+ int i = this.frameMaterialArray.length;
+
+ while (--i >= 0) {
+ this.frameMaterialArray[i].setKeepLoaded(false);
+ }
+
+ this.frameMaterialArray = null;
+ this.frameListCount = 0;
+ }
+
+ super.detach();
+ }
+
+ @Override
+ public Persister trigger(Event e, Persister seqID) {
+ Object owner = this.getOwner();
+ if (!(owner instanceof Animatable)) {
+ this.frameMaterialArray = null;
+ this.frameListCount = 0;
+ return null;
+ } else {
+ Animatable o = (Animatable)owner;
+ if (!o.hasClump()) {
+ this.frameMaterialArray = null;
+ this.frameListCount = 0;
+ return seqID;
+ } else {
+ if (this.frameMaterialArray == null) {
+ this.preprocessFrameList(this.frameList);
+ }
+
+ if (seqID == null) {
+ if (this.running && !this.infiniteLoop) {
+ return null;
+ }
+
+ this.startAnimation();
+ }
+
+ int nextFrameNo = 0;
+ if (this.frameListCount != 0 && this.cycleTime > 0) {
+ int runTime = Std.getRealTime() - this.startTime;
+ long frameNo = (long)this.frameListCount * runTime / this.cycleTime;
+ this.cycleNo = (int)(frameNo / this.frameListCount);
+ nextFrameNo = (int)(frameNo - this.cycleNo * this.frameListCount);
+ } else {
+ this.cycleNo = 1000000000;
+ }
+
+ if (this.cycleNo >= this.cycles && !this.infiniteLoop) {
+ nextFrameNo = this.frameListCount - 1;
+ this.running = false;
+ } else {
+ this.running = true;
+ }
+
+ if (nextFrameNo != this.currentFrameNo) {
+ this.currentFrameNo = nextFrameNo;
+ if (o.hasClump() && this.currentFrameNo >= 0) {
+ o.setMaterial(this.frameMaterialArray[this.currentFrameNo]);
+ }
+ }
+
+ return this.running ? this : null;
+ }
+ }
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = IntegerPropertyEditor.make(new Property(this, index, "Cycle Time"));
+ } else if (mode == 1) {
+ ret = new Integer(this.cycleTime);
+ } else if (mode == 2) {
+ this.cycleTime = (Integer)value;
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = IntegerPropertyEditor.make(new Property(this, index, "Cycles"));
+ } else if (mode == 1) {
+ ret = new Integer(this.cycles);
+ } else if (mode == 2) {
+ this.cycles = (Integer)value;
+ }
+ break;
+ case 2:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Infinite Loop"), "False", "True");
+ } else if (mode == 1) {
+ ret = new Boolean(this.infiniteLoop);
+ } else if (mode == 2) {
+ this.infiniteLoop = (Boolean)value;
+ }
+ break;
+ case 3:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Frame List"));
+ } else if (mode == 1) {
+ ret = new String(this.frameList);
+ } else if (mode == 2) {
+ this.frameList = ((String)value).toString().trim().toLowerCase();
+ this.preprocessFrameList(this.frameList);
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 4, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public String toString() {
+ String ret = super.toString() + "[cycleTime " + this.cycleTime + ", cycles " + this.cycles + ",";
+ if (!this.infiniteLoop) {
+ ret = ret + " not ";
+ }
+
+ return ret + "Infinite ]";
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(3, classCookie);
+ super.saveState(s);
+ s.saveBoolean(this.infiniteLoop);
+ s.saveInt(this.cycleTime);
+ s.saveInt(this.cycles);
+ s.saveString(this.frameList);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 1:
+ super.restoreState(r);
+ case 0:
+ this.cycleTime = (int)r.restoreFloat();
+ this.cycles = r.restoreInt();
+ this.infiniteLoop = this.cycles == 0;
+ this.frameList = r.restoreString();
+ break;
+ case 2:
+ super.restoreState(r);
+ this.cycleTime = r.restoreInt();
+ this.cycles = r.restoreInt();
+ this.infiniteLoop = this.cycles == 0;
+ this.frameList = r.restoreString();
+ break;
+ case 3:
+ super.restoreState(r);
+ this.infiniteLoop = r.restoreBoolean();
+ this.cycleTime = r.restoreInt();
+ this.cycles = r.restoreInt();
+ this.frameList = r.restoreString();
+ break;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/AnimatedAction.java b/NET/worlds/scape/AnimatedAction.java
new file mode 100644
index 0000000..95e6d23
--- /dev/null
+++ b/NET/worlds/scape/AnimatedAction.java
@@ -0,0 +1,203 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.DefaultConsole;
+import NET.worlds.core.Timer;
+import NET.worlds.core.TimerCallback;
+import NET.worlds.network.URL;
+import java.util.Vector;
+
+public class AnimatedAction implements AnimatedActionCallback, TimerCallback {
+ static final int noAction = 0;
+ static final int addToInventory = 1;
+ static final int removeObject = 2;
+ static final int animateObject = 3;
+ static final int moveObjectTo = 4;
+ static final int playSound = 5;
+ static final int obtainConsent = 0;
+ static final int zoomOut = 1;
+ static final int moveToObject = 2;
+ static final int preAnimateAction = 3;
+ static final int actOnObject1 = 4;
+ static final int simulAnimateAction = 5;
+ static final int postAnimateAction = 6;
+ static final int actOnObject2 = 7;
+ static final int zoomBack = 8;
+ static String[] actions = new String[]{"noAction", "addToInventory", "removeObject", "animateObject", "moveObjectTo", "playSound"};
+ String actionName;
+ Vector avatarNames;
+ Vector targetObjects;
+ Shape _targetShape = null;
+ boolean consentRequired;
+ Point2 targetRelPosition;
+ Point2 targetPosition;
+ double targetRelYaw;
+ float targetYaw;
+ int preAnimationAction;
+ String preAnimationParameter;
+ String actionName1;
+ int simultaneousAction;
+ String simultaneousParameter;
+ int postAnimationAction;
+ String postAnimationParameter;
+ String actionName2;
+ int _oldMode;
+ int _oldSpeed;
+ private int _state;
+ private HoloPilot _pilot;
+ private float _waitTime;
+
+ AnimatedAction() {
+ this.avatarNames = new Vector();
+ this.targetObjects = new Vector();
+ }
+
+ public static int getAction(String action) {
+ for (int i = 0; i < actions.length; i++) {
+ if (action.equals(actions[i])) {
+ return i;
+ }
+ }
+
+ return 0;
+ }
+
+ void setTargetShape(Shape s) {
+ this._targetShape = s;
+ Point3Temp objVec = Point3Temp.make(this.targetRelPosition.x, this.targetRelPosition.y, 0.0F);
+ this.targetYaw = this._targetShape.getObjectToWorldMatrix().getYaw();
+ Transform t = new Transform();
+ t.yaw(-this.targetYaw);
+ objVec.vectorTimes(t);
+ t.recycle();
+ Point3Temp shapePos = this._targetShape.getWorldPosition();
+ objVec.plus(shapePos);
+ this.targetPosition = new Point2(objVec.x, objVec.y);
+ }
+
+ public void execute(HoloPilot pilot) {
+ if (this._targetShape == null) {
+ System.out.println("No target shape for action " + this.actionName);
+ } else {
+ this._targetShape.setBumpable(false);
+ this._pilot = pilot;
+ this._state = 0;
+ this.stateChanged();
+ }
+ }
+
+ @Override
+ public void motionComplete(int completionCode) {
+ this._state++;
+ this.stateChanged();
+ }
+
+ @Override
+ public void timerDone() {
+ this.motionComplete(0);
+ }
+
+ private void stateChanged() {
+ switch (this._state) {
+ case 0:
+ this.motionComplete(0);
+ break;
+ case 1:
+ Console c = Console.getActive();
+ if (c instanceof DefaultConsole) {
+ Pilot p = Pilot.getActive();
+ this._oldMode = p.getOutsideCameraMode();
+ this._oldSpeed = p.getOutsideCameraSpeed();
+ p.setOutsideCameraMode(8, 1);
+ }
+
+ this.motionComplete(0);
+ break;
+ case 2:
+ double newYaw = this.targetYaw + this.targetRelYaw;
+ this._pilot.addCallback(this);
+ this._pilot.walkTo(new Point2(this.targetPosition.x, this.targetPosition.y), (float)newYaw);
+ break;
+ case 3:
+ this._pilot.removeSmoothDriver();
+ this._pilot.returnHandsOffDriver();
+ this.doAction(this.preAnimationAction, this.preAnimationParameter);
+ this.motionComplete(0);
+ break;
+ case 4:
+ case 7:
+ String actionName;
+ if (this._state == 4) {
+ actionName = this.actionName1;
+ } else {
+ actionName = this.actionName2;
+ }
+
+ this._waitTime = this._pilot.animate(actionName);
+ this.motionComplete(0);
+ break;
+ case 5:
+ this.doAction(this.simultaneousAction, this.simultaneousParameter + "|sender|" + this.actionName1);
+ Timer tm = new Timer(this._waitTime, this);
+ tm.start();
+ break;
+ case 6:
+ this.doAction(this.postAnimationAction, this.postAnimationParameter);
+ this.motionComplete(0);
+ break;
+ case 8:
+ Console c = Console.getActive();
+ if (c instanceof DefaultConsole) {
+ Pilot p = Pilot.getActive();
+ p.setOutsideCameraMode(this._oldMode, this._oldSpeed);
+ }
+
+ this._pilot.removeHandsOffDriver();
+ this._pilot.returnSmoothDriver();
+ AnimatedActionManager.get().actionCompleted(this);
+ this.motionComplete(0);
+ }
+ }
+
+ public void abort() {
+ this._state = 8;
+ this.stateChanged();
+ }
+
+ private void doAction(int action, String parameter) {
+ switch (action) {
+ case 5:
+ Sound s = new Sound(URL.make(parameter));
+ this._pilot.add(s);
+ s.trigger(null, null);
+ case 3:
+ Drone targetDrone = null;
+ if (this._targetShape != null && this._targetShape instanceof PosableShape) {
+ SuperRoot owner = this._targetShape.getOwner();
+ if (owner instanceof Drone) {
+ targetDrone = (Drone)owner;
+ }
+ }
+
+ if (targetDrone != null) {
+ Pilot.sendText(targetDrone.getLongID(), "&|+action2>" + parameter);
+ }
+
+ if (this._targetShape instanceof PosableShape) {
+ String actionName = null;
+ int idx = parameter.indexOf("|sender|");
+ if (idx != -1) {
+ actionName = parameter.substring(0, idx);
+ } else {
+ actionName = parameter;
+ }
+
+ ((PosableShape)this._targetShape).animate(actionName);
+ }
+ case 0:
+ case 1:
+ case 2:
+ case 4:
+ }
+ }
+}
diff --git a/NET/worlds/scape/AnimatedActionCallback.java b/NET/worlds/scape/AnimatedActionCallback.java
new file mode 100644
index 0000000..516ff6f
--- /dev/null
+++ b/NET/worlds/scape/AnimatedActionCallback.java
@@ -0,0 +1,5 @@
+package NET.worlds.scape;
+
+public interface AnimatedActionCallback {
+ void motionComplete(int var1);
+}
diff --git a/NET/worlds/scape/AnimatedActionHandler.java b/NET/worlds/scape/AnimatedActionHandler.java
new file mode 100644
index 0000000..7fdea88
--- /dev/null
+++ b/NET/worlds/scape/AnimatedActionHandler.java
@@ -0,0 +1,9 @@
+package NET.worlds.scape;
+
+public interface AnimatedActionHandler {
+ void addCallback(AnimatedActionCallback var1);
+
+ void removeCallback(AnimatedActionCallback var1);
+
+ void notifyCallbacks(int var1);
+}
diff --git a/NET/worlds/scape/AnimatedActionHandlerImp.java b/NET/worlds/scape/AnimatedActionHandlerImp.java
new file mode 100644
index 0000000..2b32de3
--- /dev/null
+++ b/NET/worlds/scape/AnimatedActionHandlerImp.java
@@ -0,0 +1,37 @@
+package NET.worlds.scape;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+public class AnimatedActionHandlerImp implements AnimatedActionHandler {
+ Vector callbacks = new Vector();
+
+ AnimatedActionHandlerImp() {
+ }
+
+ @Override
+ public void addCallback(AnimatedActionCallback c) {
+ assert this.callbacks != null;
+
+ this.callbacks.addElement(c);
+ }
+
+ @Override
+ public void removeCallback(AnimatedActionCallback c) {
+ assert this.callbacks != null;
+
+ this.callbacks.removeElement(c);
+ }
+
+ @Override
+ public void notifyCallbacks(int completionCode) {
+ assert this.callbacks != null;
+
+ Enumeration e = this.callbacks.elements();
+
+ while (e.hasMoreElements()) {
+ AnimatedActionCallback c = (AnimatedActionCallback)e.nextElement();
+ c.motionComplete(completionCode);
+ }
+ }
+}
diff --git a/NET/worlds/scape/AnimatedActionManager.java b/NET/worlds/scape/AnimatedActionManager.java
new file mode 100644
index 0000000..5ab97a9
--- /dev/null
+++ b/NET/worlds/scape/AnimatedActionManager.java
@@ -0,0 +1,329 @@
+package NET.worlds.scape;
+
+import NET.worlds.core.IniFile;
+import NET.worlds.network.NetUpdate;
+import NET.worlds.network.URL;
+import java.awt.Menu;
+import java.awt.MenuItem;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.util.Enumeration;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+public class AnimatedActionManager implements ActionListener, BGLoaded {
+ private AnimatedAction _currentAction = null;
+ static final String actionFile = "actions/actions.dat";
+ static final String localActionFile = "actions.dat";
+ static final String version = "VERSION";
+ static final String action = "ACTION";
+ private Vector actionList;
+ private Vector currentMenuActions;
+ private static AnimatedActionManager theAnimatedActionManager = null;
+
+ public static AnimatedActionManager get() {
+ if (theAnimatedActionManager == null) {
+ theAnimatedActionManager = new AnimatedActionManager();
+ }
+
+ return theAnimatedActionManager;
+ }
+
+ private Vector getActionList(URL avatar, URL object) {
+ if (this.actionList != null && avatar != null && object != null) {
+ String av = PosableShape.getBodyType(avatar);
+ if (av == null) {
+ return null;
+ } else {
+ String ob = object.toString();
+ int dot = ob.lastIndexOf(".");
+ if (dot != -1) {
+ ob = ob.substring(0, dot);
+ }
+
+ Vector ret = new Vector();
+ Enumeration e = this.actionList.elements();
+
+ while (e.hasMoreElements()) {
+ AnimatedAction a = (AnimatedAction)e.nextElement();
+ if (this.vectorCheck(av, a.avatarNames) && this.vectorCheck(ob, a.targetObjects)) {
+ ret.addElement(a);
+ }
+ }
+
+ return ret;
+ }
+ } else {
+ return null;
+ }
+ }
+
+ private boolean vectorCheck(String s, Vector v) {
+ Enumeration e = v.elements();
+
+ while (e.hasMoreElements()) {
+ String element = (String)e.nextElement();
+ if (s.toLowerCase().endsWith(element.toLowerCase())) {
+ return true;
+ }
+
+ if (element.equals("any")) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public boolean buildActionMenu(Menu m, Shape target) {
+ assert m != null;
+
+ if (this._currentAction != null) {
+ return false;
+ } else {
+ SuperRoot ultimateOwner = target;
+
+ while (ultimateOwner.getOwner() != null) {
+ ultimateOwner = ultimateOwner.getOwner();
+ if (ultimateOwner instanceof PosableShape) {
+ target = (Shape)ultimateOwner;
+ break;
+ }
+ }
+
+ Pilot p = Pilot.getActive();
+ if (p == null) {
+ return false;
+ } else if (!(p instanceof HoloPilot)) {
+ return false;
+ } else {
+ HoloPilot hp = (HoloPilot)p;
+ if (hp.getInternalDrone().getRoom() != target.getRoom()) {
+ return false;
+ } else {
+ Vector v = this.getActionList(hp.getInternalDrone().getCurrentURL(), target.getURL());
+ this.currentMenuActions = v;
+ if (v == null) {
+ return false;
+ } else if (v.size() == 0) {
+ return false;
+ } else {
+ Enumeration e = v.elements();
+
+ while (e.hasMoreElements()) {
+ AnimatedAction a = (AnimatedAction)e.nextElement();
+ a.setTargetShape(target);
+ int idx = a.actionName.indexOf("\\");
+ if (idx != -1) {
+ String action = a.actionName.substring(idx + 1);
+ String submenu = a.actionName.substring(0, idx);
+ int items = m.getItemCount();
+ boolean inserted = false;
+
+ for (int i = 0; i < items; i++) {
+ MenuItem item = m.getItem(i);
+ if (item.getLabel().equals(submenu) && item instanceof Menu) {
+ ((Menu)item).add(action);
+ inserted = true;
+ break;
+ }
+ }
+
+ if (!inserted) {
+ Menu sm = new Menu(submenu);
+ sm.addActionListener(this);
+ sm.add(action);
+ m.add(sm);
+ }
+ } else {
+ m.add(a.actionName);
+ }
+ }
+
+ return true;
+ }
+ }
+ }
+ }
+ }
+
+ public boolean processMenuClick(String actionName) {
+ if (this.currentMenuActions == null) {
+ return false;
+ } else {
+ Enumeration e = this.currentMenuActions.elements();
+
+ while (e.hasMoreElements()) {
+ AnimatedAction a = (AnimatedAction)e.nextElement();
+ String thisAction = a.actionName;
+ int idx = thisAction.indexOf(92);
+ if (idx != -1) {
+ thisAction = thisAction.substring(idx + 1);
+ }
+
+ if (thisAction.equals(actionName)) {
+ Pilot p = Pilot.getActive();
+ if (p == null) {
+ return false;
+ }
+
+ if (!(p instanceof HoloPilot)) {
+ return false;
+ }
+
+ HoloPilot hp = (HoloPilot)p;
+ if (this._currentAction != null) {
+ this._currentAction.abort();
+ }
+
+ this._currentAction = a;
+ a.execute(hp);
+ return true;
+ }
+ }
+
+ return false;
+ }
+ }
+
+ public void actionCompleted(AnimatedAction a) {
+ assert a == this._currentAction;
+
+ this._currentAction = null;
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ this.processMenuClick(e.getActionCommand());
+ }
+
+ private AnimatedActionManager() {
+ System.out.println("Loading action manager");
+ this.actionList = new Vector();
+ this.loadActionsFile();
+ }
+
+ private void loadActionsFile() {
+ File f = new File("actions.dat");
+ if (f.exists()) {
+ this.parseActionFile("actions.dat");
+ }
+
+ String serv = NetUpdate.getUpgradeServerURL();
+ String s = IniFile.override().getIniString("actionFile", "actions/actions.dat");
+ BackgroundLoader.get(this, URL.make(serv + s));
+ }
+
+ @Override
+ public synchronized Object asyncBackgroundLoad(String localName, URL remoteURL) {
+ return localName;
+ }
+
+ @Override
+ public boolean syncBackgroundLoad(Object obj, URL remoteURL) {
+ System.out.println("Got actions file ");
+ String localName = (String)obj;
+ if (localName != null && new File(localName).exists()) {
+ this.parseActionFile(localName);
+ }
+
+ return false;
+ }
+
+ @Override
+ public Room getBackgroundLoadRoom() {
+ return null;
+ }
+
+ private String getLine(RandomAccessFile fIn) throws IOException {
+ while (fIn.getFilePointer() < fIn.length()) {
+ String line = fIn.readLine().trim();
+ if (line == null) {
+ return null;
+ }
+
+ if (!line.startsWith("//") && line.length() != 0) {
+ return line;
+ }
+ }
+
+ return null;
+ }
+
+ private void parseActionFile(String fileName) {
+ int verNum = 0;
+
+ assert this.actionList != null;
+
+ this.actionList.removeAllElements();
+
+ try {
+ RandomAccessFile fIn = new RandomAccessFile(fileName, "r");
+
+ String line;
+ while ((line = this.getLine(fIn)) != null) {
+ StringTokenizer tok = new StringTokenizer(line);
+ String firstWord = tok.nextToken();
+ if (firstWord.equals("VERSION")) {
+ String ver = tok.nextToken();
+ if (ver.equals("1")) {
+ verNum = 1;
+ } else {
+ if (!ver.equals("2")) {
+ throw new Exception("Bad version.");
+ }
+
+ verNum = 2;
+ }
+ } else if (firstWord.equals("ACTION")) {
+ if (verNum == 0) {
+ throw new Exception("Actions file version not specified.");
+ }
+
+ AnimatedAction a = new AnimatedAction();
+ a.actionName = line.substring("ACTION".length() + 1);
+ this.readVector(fIn, a.avatarNames);
+ this.readVector(fIn, a.targetObjects);
+ if (verNum > 1) {
+ a.consentRequired = this.getLine(fIn).toLowerCase().equals("consent");
+ }
+
+ StringTokenizer tok2 = new StringTokenizer(this.getLine(fIn));
+ Float x = new Float(tok2.nextToken());
+ Float y = new Float(tok2.nextToken());
+ a.targetRelPosition = new Point2(x, y);
+ Float yaw = new Float(this.getLine(fIn));
+ a.targetRelYaw = yaw.floatValue();
+ a.preAnimationAction = AnimatedAction.getAction(this.getLine(fIn));
+ a.preAnimationParameter = this.getLine(fIn);
+ a.actionName1 = this.getLine(fIn);
+ if (verNum > 1) {
+ a.simultaneousAction = AnimatedAction.getAction(this.getLine(fIn));
+ a.simultaneousParameter = this.getLine(fIn);
+ }
+
+ a.postAnimationAction = AnimatedAction.getAction(this.getLine(fIn));
+ a.postAnimationParameter = this.getLine(fIn);
+ a.actionName2 = this.getLine(fIn);
+ this.actionList.addElement(a);
+ }
+ }
+
+ fIn.close();
+ } catch (Exception var12) {
+ System.out.println("Error reading actions.dat: " + var12.toString());
+ }
+ }
+
+ private void readVector(RandomAccessFile fIn, Vector v) throws IOException {
+ String line = this.getLine(fIn);
+ StringTokenizer tok = new StringTokenizer(line);
+
+ while (tok.hasMoreTokens()) {
+ v.addElement(tok.nextToken());
+ }
+ }
+}
diff --git a/NET/worlds/scape/AnimatingDoor.java b/NET/worlds/scape/AnimatingDoor.java
new file mode 100644
index 0000000..5a974f9
--- /dev/null
+++ b/NET/worlds/scape/AnimatingDoor.java
@@ -0,0 +1,301 @@
+package NET.worlds.scape;
+
+import NET.worlds.core.Std;
+import NET.worlds.network.URL;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+public class AnimatingDoor extends Portal implements FrameHandler {
+ public String frameList = "";
+ protected transient Material[] frames = null;
+ float perFrame = 100.0F;
+ private URL openSound;
+ private URL closeSound;
+ private transient float state;
+ private transient int lastUpdate;
+ private transient boolean wasSameRoom;
+ private transient int lastFrame = -1;
+ private Point3 start = new Point3(-0.5F, -1.0F, 0.0F);
+ private Point3 end = new Point3(1.5F, 0.0F, 1.0F);
+ private static Object classCookie = new Object();
+
+ public AnimatingDoor() {
+ this.flags |= 262208;
+ }
+
+ @Override
+ public void detach() {
+ if (this.frames != null) {
+ int i = this.frames.length;
+
+ while (--i >= 0) {
+ this.frames[i].setKeepLoaded(false);
+ }
+
+ this.frames = null;
+ }
+
+ super.detach();
+ }
+
+ @Override
+ public boolean handle(FrameEvent e) {
+ Pilot pilot = Pilot.getActive();
+ Room pilotRoom = pilot.getRoom();
+ boolean sameRoom = pilotRoom == this.getRoom();
+ boolean inRange = false;
+ Point3Temp pos = pilot.getPosition();
+ if (sameRoom) {
+ BoundBoxTemp bbt = BoundBoxTemp.make(Point3Temp.make(this.start).times(this), Point3Temp.make(this.end).times(this));
+ inRange = bbt.contains(pos);
+ }
+
+ Portal far = this.farSide();
+ if (far != null && far instanceof AnimatingDoor) {
+ AnimatingDoor afar = (AnimatingDoor)far;
+ if (!inRange) {
+ Room farRoom = afar.getRoom();
+ if (farRoom == null) {
+ this.animate(sameRoom, inRange);
+ return true;
+ }
+
+ if (afar.getRoom() == pilotRoom) {
+ if (!sameRoom) {
+ return true;
+ }
+
+ BoundBoxTemp bbt = BoundBoxTemp.make(Point3Temp.make(afar.start).times(afar), Point3Temp.make(afar.end).times(afar));
+ inRange = bbt.contains(pos);
+ }
+ }
+
+ afar.animate(sameRoom, inRange);
+ }
+
+ this.animate(sameRoom, inRange);
+ return true;
+ }
+
+ private void animate(boolean sameRoom, boolean inRange) {
+ int now = Std.getFastTime();
+ float oldState = this.state;
+ if (this.frames == null) {
+ this.frames = namesToMaterialArray(this, this.frameList);
+ this.lastFrame = -1;
+ }
+
+ int numMovingFrames = this.frames.length - 2;
+ boolean wasSameRoom = this.wasSameRoom;
+ this.wasSameRoom = sameRoom;
+ if (!sameRoom) {
+ this.state = 0.0F;
+ } else if (!wasSameRoom) {
+ this.state = inRange ? 1.0F : 0.0F;
+ } else if (this.state == 0.0F) {
+ if (!inRange) {
+ return;
+ }
+
+ this.state = 1.0E-4F;
+ } else if (this.state == 1.0F) {
+ if (inRange) {
+ return;
+ }
+
+ this.playSound(this.closeSound);
+ this.state = 0.999F;
+ } else {
+ if (this.state == 1.0E-4F && inRange) {
+ if (this.active()) {
+ this.playSound(this.openSound);
+ this.state = 2.0E-4F;
+ } else {
+ this.lastUpdate = now;
+ }
+ }
+
+ float totalTime = numMovingFrames * this.perFrame;
+ if (totalTime > 0.0F && now != this.lastUpdate) {
+ float distMoved = (now - this.lastUpdate) / totalTime;
+ if (inRange) {
+ if ((this.state += distMoved) >= 1.0F) {
+ this.state = 1.0F;
+ }
+ } else if ((this.state -= distMoved) <= 0.0F) {
+ this.state = 0.0F;
+ }
+ }
+ }
+
+ if (oldState != 0.0F && this.state == 0.0F) {
+ this.flags |= 262144;
+ this.reset();
+ } else if (oldState == 0.0F && this.state != 0.0F) {
+ this.flags &= -262145;
+ this.reset();
+ this.triggerLoad();
+ }
+
+ this.lastUpdate = now;
+ int frame = 0;
+ if (numMovingFrames >= 0) {
+ if (this.state <= 2.0E-4F) {
+ frame = 0;
+ } else if (this.state == 1.0F) {
+ frame = numMovingFrames + 1;
+ } else {
+ frame = 1 + (int)(this.state * numMovingFrames);
+ }
+ } else if (numMovingFrames == -2) {
+ return;
+ }
+
+ this.setFrame(frame);
+ }
+
+ private void setFrame(int frame) {
+ if (frame != this.lastFrame && this.frames != null && this.frames.length > frame) {
+ this.setMaterial(this.frames[frame]);
+ this.lastFrame = frame;
+ }
+ }
+
+ private void playSound(URL url) {
+ if (url != null && this.getRoom() == Pilot.getActive().getRoom()) {
+ WavSoundPlayer wavPlayer = new WavSoundPlayer(null);
+ wavPlayer.open(1.0F, 0.0F, false, false);
+ wavPlayer.start(url);
+ }
+ }
+
+ public static Material[] namesToMaterialArray(SuperRoot base, String str) {
+ Vector v = new Vector();
+ StringTokenizer st = new StringTokenizer(str);
+
+ while (st.hasMoreTokens()) {
+ v.addElement(st.nextToken());
+ }
+
+ int count = v.size();
+ Material[] mats = new Material[count];
+ int i = count;
+
+ while (--i >= 0) {
+ String s = (String)v.elementAt(i);
+
+ URL url;
+ try {
+ url = new URL(base, s);
+ } catch (MalformedURLException var10) {
+ url = URL.make("error:\"" + s + '"');
+ }
+
+ mats[i] = new Material(url);
+ mats[i].setKeepLoaded(true);
+ }
+
+ return mats;
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Frame List"));
+ } else if (mode == 1) {
+ ret = this.frameList;
+ } else if (mode == 2) {
+ this.frameList = ((String)value).toString().trim();
+ this.frames = null;
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = Point3PropertyEditor.make(new Property(this, index, "Start"));
+ } else if (mode == 1) {
+ ret = new Point3(this.start);
+ } else if (mode == 2) {
+ this.start = (Point3)value;
+ }
+ break;
+ case 2:
+ if (mode == 0) {
+ ret = Point3PropertyEditor.make(new Property(this, index, "End"));
+ } else if (mode == 1) {
+ ret = new Point3(this.end);
+ } else if (mode == 2) {
+ this.end = (Point3)value;
+ }
+ break;
+ case 3:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Time Per Frame"));
+ } else if (mode == 1) {
+ ret = new Float(this.perFrame);
+ } else if (mode == 2) {
+ this.perFrame = (Float)value;
+ }
+ break;
+ case 4:
+ if (mode == 0) {
+ ret = URLPropertyEditor.make(new Property(this, index, "Open Sound URL").allowSetNull(), "wav;mid;ram;ra;rm");
+ } else if (mode == 1) {
+ ret = this.openSound;
+ } else if (mode == 2) {
+ this.openSound = (URL)value;
+ }
+ break;
+ case 5:
+ if (mode == 0) {
+ ret = URLPropertyEditor.make(new Property(this, index, "Close Sound URL").allowSetNull(), "wav;mid;ram;ra;rm");
+ } else if (mode == 1) {
+ ret = this.closeSound;
+ } else if (mode == 2) {
+ this.closeSound = (URL)value;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 6, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ this.setFrame(0);
+ s.saveVersion(0, classCookie);
+ int f = this.flags;
+ this.flags |= 262144;
+ super.saveState(s);
+ this.flags = f;
+ s.saveString(this.frameList);
+ s.saveFloat(this.perFrame);
+ s.save(this.start);
+ s.save(this.end);
+ URL.save(s, this.openSound);
+ URL.save(s, this.closeSound);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ this.frameList = r.restoreString();
+ this.perFrame = r.restoreFloat();
+ this.start = (Point3)r.restore();
+ this.end = (Point3)r.restore();
+ this.openSound = URL.restore(r);
+ this.closeSound = URL.restore(r);
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/Animation.java b/NET/worlds/scape/Animation.java
new file mode 100644
index 0000000..1f27085
--- /dev/null
+++ b/NET/worlds/scape/Animation.java
@@ -0,0 +1,285 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.network.URL;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.text.MessageFormat;
+import java.util.Date;
+
+class Animation extends TriggeredSwitchableBehavior implements FrameHandler, Persister, MouseDownHandler, BumpHandler {
+ long startFrameTime;
+ protected float cycleTime;
+ protected String frameList;
+ protected int cycles;
+ protected int cycleNo = 0;
+ protected String[] frameListArray;
+ protected Material[] frameMaterialArray;
+ protected int frameListCount;
+ protected int currentFrameNo;
+ protected boolean animationEnd = true;
+
+ public Animation() {
+ this.cycleTime = 1000.0F;
+ this.frameList = new String("");
+ this.trigger = new String("none");
+ this.externalTriggerTag = new String("");
+ this.cycles = 0;
+ this.frameListArray = new String[200];
+ this.frameMaterialArray = new Material[200];
+ this.frameListCount = 0;
+ this.startAnimation();
+ }
+
+ @Override
+ public void ExternalTrigger(Trigger trigger_source, int sequence_no, int event_no) {
+ this.trigger_source = trigger_source;
+ this.sequence_no = sequence_no;
+ this.event_no = event_no;
+ this.startAnimation();
+ }
+
+ public void startAnimation() {
+ Date timer = new Date();
+ this.startFrameTime = timer.getTime();
+ this.cycleNo = 0;
+ this.currentFrameNo = 0;
+ this.animationEnd = false;
+ }
+
+ public float getCycleTime() {
+ return this.cycleTime;
+ }
+
+ public void setCycleTime(float t) {
+ this.cycleTime = t;
+ }
+
+ public int getNextFrameNo() {
+ Date timer = new Date();
+ int nextFrameNo = 0;
+ if (this.frameListCount > 0) {
+ nextFrameNo = (int)(this.frameListCount * ((float)(timer.getTime() - this.startFrameTime) % this.cycleTime) / (this.cycleTime + 1.0F) + 1.0F);
+ if (this.currentFrameNo > nextFrameNo) {
+ this.cycleNo++;
+ }
+ }
+
+ return nextFrameNo;
+ }
+
+ public void preprocessFrameList(String frameList) {
+ int currentIndex = 1;
+ int currentSeparator = 0;
+ int nextSeparator = 0;
+ int lastSeparator = frameList.lastIndexOf(" ");
+ if (lastSeparator != -1 || frameList.length() != 0) {
+ if (lastSeparator == -1) {
+ this.frameListArray[currentIndex] = frameList;
+ } else {
+ nextSeparator = frameList.indexOf(" ");
+ this.frameListArray[currentIndex] = frameList.substring(0, nextSeparator);
+ currentIndex++;
+
+ while (nextSeparator != lastSeparator) {
+ currentSeparator = nextSeparator;
+ nextSeparator = frameList.indexOf(" ", nextSeparator + 1);
+ this.frameListArray[currentIndex] = frameList.substring(currentSeparator + 1, nextSeparator);
+ currentIndex++;
+ }
+
+ this.frameListArray[currentIndex] = frameList.substring(nextSeparator + 1);
+ this.frameListCount = currentIndex;
+ }
+ }
+
+ for (int var11 = 1; var11 <= this.frameListCount; var11++) {
+ String s = this.frameListArray[var11];
+
+ URL url;
+ try {
+ url = new URL(this, s);
+ } catch (MalformedURLException var9) {
+ url = URL.make("error:\"" + s + '"');
+ }
+
+ this.frameMaterialArray[var11] = new Material(url);
+ }
+ }
+
+ @Override
+ public boolean handle(FrameEvent e) {
+ if (this.enabled && e.receiver instanceof Rect) {
+ int nextFrameNo = this.getNextFrameNo();
+ if (this.cycleNo >= this.cycles && this.cycles != 0) {
+ if (this.currentFrameNo != this.frameListCount) {
+ Rect Wall = (Rect)e.receiver;
+ Wall.setMaterial(this.frameMaterialArray[this.frameListCount]);
+ this.currentFrameNo = this.frameListCount;
+ }
+ } else if (nextFrameNo > 0 && nextFrameNo != this.currentFrameNo) {
+ this.currentFrameNo = nextFrameNo;
+ Rect Wall = (Rect)e.receiver;
+ Wall.setMaterial(this.frameMaterialArray[this.currentFrameNo]);
+ }
+
+ if (this.cycleNo >= this.cycles && this.cycles != 0 && !this.animationEnd) {
+ this.animationEnd = true;
+ if (this.trigger_source != null) {
+ this.trigger_source.registerFinishedTriggerTag(this.sequence_no, this.event_no);
+ }
+ }
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean handle(MouseDownEvent e) {
+ if (this.enabled && this.trigger.equals("click")) {
+ this.startAnimation();
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean handle(BumpEventTemp e) {
+ if (this.enabled && this.trigger.equals("bump")) {
+ this.startAnimation();
+ }
+
+ return true;
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = new ClassProperty(this, index, "Animation");
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Cycle Time"));
+ } else if (mode == 1) {
+ ret = new Float(this.cycleTime);
+ } else if (mode == 2) {
+ this.cycleTime = (Float)value;
+ }
+ break;
+ case 2:
+ if (mode == 0) {
+ ret = IntegerPropertyEditor.make(new Property(this, index, "Cycles"));
+ } else if (mode == 1) {
+ ret = new Integer(this.cycles);
+ } else if (mode == 2) {
+ this.cycles = (Integer)value;
+ }
+ break;
+ case 3:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Trigger"));
+ } else if (mode == 1) {
+ ret = new String(this.trigger);
+ } else if (mode == 2) {
+ this.trigger = ((String)value).toString().trim();
+ if (this.trigger.equals("external")) {
+ Trigger.TriggeredSwitchableBehaviorList[Trigger.TriggeredSwitchableBehaviorListCount] = this;
+ Trigger.TriggeredSwitchableBehaviorListCount++;
+ }
+ }
+ break;
+ case 4:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "External Trigger Tag"));
+ } else if (mode == 1) {
+ ret = new String(this.externalTriggerTag);
+ } else if (mode == 2) {
+ this.externalTriggerTag = ((String)value).toString().trim();
+ }
+ break;
+ case 5:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Frame List"));
+ } else if (mode == 1) {
+ ret = new String(this.frameList);
+ } else if (mode == 2) {
+ this.frameList = ((String)value).toString().trim().toLowerCase();
+ this.preprocessFrameList(this.frameList);
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 6, mode, value);
+ }
+
+ if (mode == 2 && this.trigger.equals("none")) {
+ this.startAnimation();
+ }
+
+ return ret;
+ }
+
+ @Override
+ public String toString() {
+ return "Animation: cycleTime "
+ + this.cycleTime
+ + ", cycles "
+ + this.cycles
+ + ", enabled "
+ + this.enabled
+ + ", trigger "
+ + this.trigger
+ + ", externalTriggerTag "
+ + this.externalTriggerTag
+ + ", frameList "
+ + this.frameList;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveFloat(this.cycleTime);
+ s.saveInt(this.cycles);
+ s.saveString(this.trigger);
+ s.saveString(this.externalTriggerTag);
+ s.saveString(this.frameList);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException {
+ this.cycleTime = r.restoreFloat();
+ this.cycles = r.restoreInt();
+ this.trigger = r.restoreString();
+ if (this.trigger.equals("external")) {
+ Trigger.TriggeredSwitchableBehaviorList[Trigger.TriggeredSwitchableBehaviorListCount] = this;
+ Trigger.TriggeredSwitchableBehaviorListCount++;
+ }
+
+ this.externalTriggerTag = r.restoreString();
+ if (!this.trigger.equals("none")) {
+ this.cycleNo = this.cycles;
+ } else {
+ this.startAnimation();
+ }
+
+ this.frameList = r.restoreString();
+ this.preprocessFrameList(this.frameList);
+ }
+
+ @Override
+ public void postRestore(int version) {
+ String name = this.getName();
+ String arg1 = name == null ? "<null>" : name;
+ SuperRoot owner = this.getOwner();
+ String oname = "";
+ if (owner != null) {
+ oname = owner.getName();
+ }
+
+ String arg2 = oname == null ? "<null>" : oname;
+ Object[] arguments = new Object[]{new String(arg1), new String(arg2)};
+ Console.println(MessageFormat.format(Console.message("Animation-obs"), arguments));
+ }
+}
diff --git a/NET/worlds/scape/Attribute.java b/NET/worlds/scape/Attribute.java
new file mode 100644
index 0000000..12d2304
--- /dev/null
+++ b/NET/worlds/scape/Attribute.java
@@ -0,0 +1,383 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.network.InfiniteWaitException;
+import NET.worlds.network.NetworkObject;
+import NET.worlds.network.ObjID;
+import NET.worlds.network.PacketTooLargeException;
+import NET.worlds.network.WorldServer;
+import NET.worlds.network.propReqCmd;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Vector;
+
+public abstract class Attribute extends Sensor {
+ public int _shorthandVersion = this.getMaxShorthandVersion();
+ int _attrID;
+ byte[] _serverData;
+ boolean _waitingForFeedback;
+ byte[] _outgoing;
+ boolean loaded;
+ Vector<LoadedAttribute> callbacks;
+ private Attribute _to;
+ private int _storedForwardAttrID = -1;
+ protected int _propertyFlags = 208;
+ protected int _accessFlags = 0;
+ private static Object classCookie = new Object();
+
+ public int getMaxShorthandVersion() {
+ return 0;
+ }
+
+ public void load(LoadedAttribute callback) {
+ if (this.loaded) {
+ if (callback != null) {
+ callback.loadedAttribute(this, null);
+ }
+ } else {
+ Sharer s = (Sharer)this.getOwner();
+ if (s != null && s.isShared()) {
+ if (callback != null) {
+ if (this.callbacks == null) {
+ this.callbacks = new Vector<LoadedAttribute>();
+ }
+
+ this.callbacks.addElement(callback);
+ }
+
+ Attribute f = this.getForwardAttribute();
+ if (f != null) {
+ f.load(null);
+ } else {
+ assert (s.getMode() & 1) == 0;
+
+ Object served = s.getOwner();
+
+ try {
+ WorldServer servr;
+ String id;
+ if (served instanceof Room) {
+ servr = ((Room)served).getServer();
+ id = ((Room)served).getNetworkRoom().getLongID();
+ } else {
+ servr = ((NetworkObject)served).getServer();
+ id = ((NetworkObject)served).getLongID();
+ }
+
+ servr.sendNetworkMsg(new propReqCmd(new ObjID(id), this._attrID));
+ } catch (InfiniteWaitException var7) {
+ } catch (PacketTooLargeException var8) {
+ assert false;
+ }
+ }
+ } else {
+ if (callback != null) {
+ callback.loadedAttribute(this, "unshared");
+ }
+ }
+ }
+ }
+
+ public int getAttrID() {
+ return this._attrID;
+ }
+
+ public Attribute(int attrID) {
+ this._attrID = attrID;
+ }
+
+ public Attribute() {
+ }
+
+ public void setAttrID(int newID) {
+ this.flushBuffers();
+ Sharer sharer = (Sharer)this.getOwner();
+ if (sharer == null) {
+ this._attrID = newID;
+ } else {
+ sharer.resetAttributeID(this, newID);
+ }
+ }
+
+ private void flushBuffers() {
+ this._serverData = null;
+ this._waitingForFeedback = false;
+ this._outgoing = null;
+ }
+
+ public int getForwardAttrID() {
+ return this._to != null ? this._to._attrID : this._storedForwardAttrID;
+ }
+
+ public void unforward() {
+ if (this._to != null) {
+ this._storedForwardAttrID = this._to.getAttrID();
+ Sharer s = (Sharer)this._to.getOwner();
+ if (s != null) {
+ s.removeAttribute(this._to);
+ }
+ }
+
+ this.flushBuffers();
+ }
+
+ public boolean isForwarded() {
+ return this._to != null;
+ }
+
+ public Attribute getForwardAttribute() {
+ return this._to;
+ }
+
+ public void setForwardAttrID(int newID) {
+ if (this._to != null) {
+ this._to.setAttrID(newID);
+ } else {
+ this._storedForwardAttrID = newID;
+ }
+ }
+
+ public void noteChange() {
+ Sharer sharer = (Sharer)this.getOwner();
+ if (sharer != null) {
+ sharer.noteChange(this, this.actions.size() > 0);
+ }
+ }
+
+ public void addForwarding() {
+ if (!this.isForwarded()) {
+ Sharer s = (Sharer)this.getOwner();
+
+ assert ((WObject)s.getOwner()).getSharerMode() == 3;
+
+ WObject terminal = ((WObject)s.getOwner()).getServed();
+ if (terminal != null) {
+ if (this.getOwner().getOwner() != terminal) {
+ ForwardAttribute fwd = new ForwardAttribute(this, this._storedForwardAttrID);
+ terminal.addShareableAttribute(fwd);
+ this._to = fwd;
+ }
+ }
+ }
+ }
+
+ public abstract void generateNetData(DataOutputStream var1) throws IOException;
+
+ public abstract void setFromNetData(DataInputStream var1, int var2) throws IOException;
+
+ @Override
+ public void detach() {
+ super.detach();
+ this.unforward();
+ }
+
+ public int getFlags() {
+ return this._propertyFlags;
+ }
+
+ public void setFlag(int flag, boolean onoff) {
+ if (onoff) {
+ this._propertyFlags |= flag;
+ } else {
+ this._propertyFlags &= ~flag;
+ }
+ }
+
+ public void setFinger(boolean onoff) {
+ this.setFlag(32, onoff);
+ }
+
+ public boolean getFinger() {
+ return (this.getFlags() & 32) != 0;
+ }
+
+ public void setAutoUpdate(boolean onoff) {
+ this.setFlag(64, onoff);
+ }
+
+ public boolean getAutoUpdate() {
+ return (this.getFlags() & 64) != 0;
+ }
+
+ public void setDatabase(boolean onoff) {
+ this.setFlag(128, onoff);
+ }
+
+ public boolean getDatabase() {
+ return (this.getFlags() & 128) != 0;
+ }
+
+ public void setBinary(boolean onoff) {
+ this.setFlag(16, onoff);
+ }
+
+ public boolean getBinary() {
+ return (this.getFlags() & 16) != 0;
+ }
+
+ public int getAccessFlags() {
+ return this._accessFlags;
+ }
+
+ public void setAccessFlags(int flags) {
+ this._accessFlags = flags;
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = IntegerPropertyEditor.make(new Property(this, index, "Attribute ID"));
+ } else if (mode == 1) {
+ ret = new Integer(this._attrID);
+ } else if (mode == 2) {
+ int id = (Integer)value;
+ if (id >= 0 && id <= 255) {
+ this.setAttrID(id);
+ } else {
+ Console.println(Console.message("Attribute-id"));
+ }
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Fingerable"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(this.getFinger());
+ } else if (mode == 2) {
+ this.setFinger((Boolean)value);
+ }
+ break;
+ case 2:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Auto Update"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(this.getAutoUpdate());
+ } else if (mode == 2) {
+ this.setAutoUpdate((Boolean)value);
+ }
+ break;
+ case 3:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Store in Database"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(this.getDatabase());
+ } else if (mode == 2) {
+ this.setDatabase((Boolean)value);
+ }
+ break;
+ case 4:
+ if (mode == 0) {
+ ret = IntegerPropertyEditor.make(new Property(this, index, "Shorthand version"));
+ } else if (mode == 1) {
+ ret = new Integer(this._shorthandVersion);
+ } else if (mode == 2) {
+ int id = (Integer)value;
+ if (id >= 0 && id <= this.getMaxShorthandVersion()) {
+ this._shorthandVersion = id;
+ } else {
+ Console.println(Console.message("Shorthand-version") + " " + this.getMaxShorthandVersion());
+ }
+ }
+ break;
+ case 5:
+ if (mode == 0) {
+ ret = IntegerPropertyEditor.make(new Property(this, index, "Forwarder attrID"));
+ } else if (mode == 1) {
+ ret = new Integer(this.getForwardAttrID());
+ } else if (mode == 2) {
+ int id = (Integer)value;
+ if (id >= 0 && id <= 255) {
+ this.setForwardAttrID(id);
+ } else {
+ Console.println(Console.message("Attribute-id"));
+ }
+ }
+ break;
+ case 6:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Load Now"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(false);
+ } else if (mode == 2 && (Boolean)value) {
+ this.load(null);
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 7, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public Object propertyParent() {
+ return this.getOwner().getOwner();
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(5, classCookie);
+ super.saveState(s);
+ s.saveInt(this._attrID);
+ s.saveInt(this.getForwardAttrID());
+ s.saveInt(this._propertyFlags);
+ s.saveInt(this._shorthandVersion);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ this._attrID = r.restoreInt();
+ if (r.restoreBoolean()) {
+ this._storedForwardAttrID = r.restoreInt();
+ } else {
+ r.restoreInt();
+ }
+ break;
+ case 1:
+ this._attrID = r.restoreInt();
+ this._storedForwardAttrID = r.restoreInt();
+ break;
+ case 2:
+ this._attrID = r.restoreInt();
+ this._storedForwardAttrID = r.restoreInt();
+ this._propertyFlags = r.restoreInt();
+ break;
+ case 3:
+ this.restoreStateSuperRoot(r);
+ this._attrID = r.restoreInt();
+ this._storedForwardAttrID = r.restoreInt();
+ this._propertyFlags = r.restoreInt();
+ break;
+ case 4:
+ this.restoreStateSuperRoot(r);
+ this._attrID = r.restoreInt();
+ this._storedForwardAttrID = r.restoreInt();
+ this._propertyFlags = r.restoreInt();
+ this._shorthandVersion = r.restoreInt();
+ break;
+ case 5:
+ super.restoreState(r);
+ this._attrID = r.restoreInt();
+ this._storedForwardAttrID = r.restoreInt();
+ this._propertyFlags = r.restoreInt();
+ this._shorthandVersion = r.restoreInt();
+ break;
+ default:
+ throw new TooNewException();
+ }
+ }
+
+ @Override
+ public String toString() {
+ return this.isForwarded() ? super.toString() + "[forwarded to " + this._to.getName() + "]" : super.toString();
+ }
+
+ public void releaseAuxilaryData() {
+ }
+}
diff --git a/NET/worlds/scape/AudibilityFilter.java b/NET/worlds/scape/AudibilityFilter.java
new file mode 100644
index 0000000..78b6331
--- /dev/null
+++ b/NET/worlds/scape/AudibilityFilter.java
@@ -0,0 +1,292 @@
+package NET.worlds.scape;
+
+import java.util.Vector;
+
+public class AudibilityFilter {
+ WObject owner;
+ Room listenerRoom;
+ AudibleParams ownerPos;
+ AudibleParams localPos;
+ Vector roomList = new Vector();
+ int maxHopcount = 1;
+ private boolean listenerOn = false;
+ private boolean emitterOn = false;
+ Sound sound;
+ Vector breadthQueue = null;
+ int breadthLevel;
+ int breadthNextLevelIndex;
+ int breadthIndex;
+
+ public AudibilityFilter(Sound s, WObject o, int maxHops) {
+ this.debugOut(9, "AudibilityFilter::AudibilityFilter in");
+ this.sound = s;
+ this.owner = o;
+ this.maxHopcount = maxHops;
+ if (this.owner.getRoom() != null) {
+ this.floodFillRooms();
+ this.updateListenerState();
+ }
+ }
+
+ void fillOwnerEntry() {
+ this.debugOut(9, "aud fillOwnerEntry called " + this.sound.getURL());
+ this.ownerPos = new AudibleParams();
+ this.ownerPos.room = this.owner.getRoom();
+ this.ownerPos.position = new Point3(this.owner.getPosition());
+ this.ownerPos.transform = Transform.make();
+ this.ownerPos.hopcount = 0;
+ this.roomList.addElement(this.ownerPos);
+ }
+
+ private void debugOut(int level, String str) {
+ if (Sound.debugLevel > level) {
+ System.out.println(str);
+ }
+ }
+
+ public AudibilityFilter(Sound s, WObject o, int maxHops, float stopDistance) {
+ this(s, o, maxHops);
+ }
+
+ public AudibilityFilter() {
+ }
+
+ public void setHopcount(int i) {
+ this.debugOut(9, "AudibilityFilter::setHopcount");
+ this.maxHopcount = i;
+ this.moveEmitter();
+ }
+
+ public int getHopcount() {
+ this.debugOut(9, "AudibilityFilter::getHopcount");
+ return this.maxHopcount;
+ }
+
+ void setEmitterOn(boolean flag) {
+ this.debugOut(9, "setting emitterOn to " + flag);
+ this.emitterOn = flag;
+ }
+
+ void updateListenerState() {
+ assert this.sound != null;
+
+ this.debugOut(6, "updateListenerState " + this.sound.getURL());
+ Room newRoom = Pilot.getActiveRoom();
+ if (this.listenerRoom != newRoom) {
+ this.listenerRoom = newRoom;
+ AudibleParams roomElement = this.getRoomElement(newRoom);
+ if (roomElement == null) {
+ this.listenerOn = false;
+ } else {
+ this.localPos = roomElement;
+ this.adjustEmitterLocation();
+ if (!this.listenerOn) {
+ this.listenerOn = true;
+ if (this.emitterOn) {
+ RunningActionHandler.trigger(this.sound, this.owner.getWorld(), null);
+ }
+ }
+ }
+ }
+ }
+
+ private void updateEmitterState() {
+ if (this.isEmitterMoved()) {
+ this.adjustEmitterLocation();
+ }
+ }
+
+ public boolean isAudible() {
+ this.updateListenerState();
+ this.updateEmitterState();
+ this.debugOut(6, "emitterOn " + this.emitterOn + " listenerOn " + this.listenerOn);
+ return this.emitterOn && this.listenerOn;
+ }
+
+ void moveEmitter() {
+ this.debugOut(9, "moveEmitter");
+ this.removeRooms();
+ this.floodFillRooms();
+ this.updateListenerState();
+ }
+
+ private void removeRooms() {
+ this.debugOut(9, "removeRooms for sound " + this.sound.getURL());
+
+ for (int roomIndex = this.roomList.size() - 1; roomIndex >= 0; roomIndex--) {
+ AudibleParams ap = (AudibleParams)this.roomList.elementAt(roomIndex);
+ Room room = ap.room;
+ room.removeAFilter(this);
+ this.debugOut(9, "removing room " + room.getName() + " from roomList");
+ this.roomList.removeElementAt(roomIndex);
+ }
+ }
+
+ private void floodFillRooms() {
+ this.debugOut(9, "floodFillRooms " + this.sound.getURL() + " count:" + this.maxHopcount);
+
+ assert this.roomList != null;
+
+ assert this.roomList.size() == 0;
+
+ assert this.owner != null;
+
+ if (this.owner != null && this.owner.getRoom() != null) {
+ this.breadthSearchStart();
+ this.fillOwnerEntry();
+ this.owner.getRoom().addAFilter(this);
+ this.breadthAddChildren(this.owner.getRoom());
+
+ for (Portal portal = this.breadthNextElement(); portal != null && this.breadthCurrentLevel() < this.maxHopcount; portal = this.breadthNextElement()) {
+ this.debugOut(6, " trying to add " + portal.farSideRoom().getName());
+ if (this.getRoomElement(portal.farSideRoom()) == null) {
+ this.addRoomListEntry(portal, this.breadthCurrentLevel() + 1);
+ this.breadthAddChildren(portal.farSideRoom());
+ }
+ }
+
+ this.breadthSearchEnd();
+ }
+ }
+
+ private void breadthSearchStart() {
+ this.breadthQueue = new Vector();
+ this.breadthLevel = 0;
+ this.breadthNextLevelIndex = 0;
+ this.breadthIndex = 0;
+ }
+
+ private Portal breadthNextElement() {
+ if (this.breadthQueue != null && this.breadthIndex < this.breadthQueue.size()) {
+ if (this.breadthIndex == this.breadthNextLevelIndex) {
+ this.breadthLevel++;
+ this.breadthNextLevelIndex = this.breadthQueue.size();
+ }
+
+ Portal portal = (Portal)this.breadthQueue.elementAt(this.breadthIndex);
+ return (Portal)this.breadthQueue.elementAt(this.breadthIndex++);
+ } else {
+ return null;
+ }
+ }
+
+ private void breadthAddChildren(Room room) {
+ assert this.breadthQueue != null;
+
+ Vector next = room.getOutgoingPortals();
+
+ for (int j = 0; j < next.size(); j++) {
+ Portal portal = (Portal)next.elementAt(j);
+ Room r = portal.farSideRoom();
+ if (r != null && r.isActive()) {
+ this.breadthQueue.addElement(portal);
+ }
+ }
+ }
+
+ private int breadthCurrentLevel() {
+ return this.breadthLevel;
+ }
+
+ private void breadthSearchEnd() {
+ this.breadthQueue = null;
+ }
+
+ private void addRoomListEntry(Portal portal, int hopCount) {
+ this.debugOut(9, "addRoomListEntry " + portal.farSideRoom().getName());
+ AudibleParams ap = this.getRoomElement(portal.getRoom());
+
+ assert ap != null;
+
+ this.fillNewAP(ap, portal, hopCount);
+ portal.farSideRoom().addAFilter(this);
+ }
+
+ AudibleParams getRoomElement(Room room) {
+ this.debugOut(6, "getRoomElement size " + this.roomList.size() + " room " + room.getName());
+ if (room == null) {
+ return null;
+ } else {
+ for (int index = 0; index < this.roomList.size(); index++) {
+ Room newRoom = ((AudibleParams)this.roomList.elementAt(index)).room;
+ this.debugOut(9, " comparing to " + newRoom.getName());
+ if (((AudibleParams)this.roomList.elementAt(index)).room == room) {
+ return (AudibleParams)this.roomList.elementAt(index);
+ }
+ }
+
+ return null;
+ }
+ }
+
+ void fillNewAP(AudibleParams connectingRoom, Portal bestPortal, int bestCount) {
+ this.debugOut(4, "AudibilityFilter::fillNewAP for room " + bestPortal.farSideRoom().getName());
+ AudibleParams newAP = new AudibleParams();
+ newAP.room = bestPortal.farSideRoom();
+ newAP.hopcount = bestCount;
+ Transform xform;
+ if (bestPortal.p2pXform() != null) {
+ xform = bestPortal.p2pXform().getTransform();
+ } else {
+ xform = Transform.make();
+ this.debugOut(4, " xform incomplete");
+ }
+
+ newAP.transform = connectingRoom.transform.getTransform();
+ newAP.transform.post(xform);
+ xform.recycle();
+ newAP.position = new Point3(connectingRoom.position);
+ newAP.position.times(newAP.transform);
+ this.roomList.addElement(newAP);
+ }
+
+ public boolean isEmitterMoved() {
+ assert this.ownerPos != null;
+
+ if (!this.ownerPos.position.sameValue(this.owner.getPosition())) {
+ this.ownerPos.position = new Point3(this.owner.getPosition());
+ return true;
+ } else {
+ return this.ownerPos.room != this.owner.getRoom();
+ }
+ }
+
+ public void adjustEmitterLocation() {
+ this.debugOut(4, "AudibilityFilter::adjustEmitterLocation");
+ if (this.ownerPos.room != this.owner.getRoom()) {
+ this.debugOut(9, " moveEmitter because emitter changed rooms");
+ this.moveEmitter();
+ } else {
+ this.localPos.position = new Point3(this.ownerPos.position);
+ this.localPos.position.times(this.localPos.transform);
+ }
+ }
+
+ public void getListenerPosition(Point3Temp pos, Point3Temp up, Point3Temp forward) {
+ this.debugOut(9, "getListenerPosition");
+ Pilot pilot = Pilot.getActive();
+ Transform t = pilot.getObjectToWorldMatrix();
+ up.copy(Point3Temp.make(0.0F, 0.0F, 1.0F).vectorTimes(t).normalize());
+ forward.copy(Point3Temp.make(0.0F, 1.0F, 0.0F).vectorTimes(t).normalize());
+ pos.copy(pilot.getPosition());
+ t.recycle();
+ }
+
+ public void getEmitterPosition(Point3Temp pos) {
+ this.debugOut(9, "getEmitterPosition");
+
+ assert this.localPos != null;
+
+ pos.x = this.localPos.position.x;
+ pos.y = this.localPos.position.y;
+ pos.z = this.localPos.position.z;
+ }
+
+ public float getEmitterVolume() {
+ this.debugOut(9, "getEmitterVolume");
+
+ assert this.localPos != null;
+
+ return 1.0F;
+ }
+}
diff --git a/NET/worlds/scape/AudibleParams.java b/NET/worlds/scape/AudibleParams.java
new file mode 100644
index 0000000..04e24cf
--- /dev/null
+++ b/NET/worlds/scape/AudibleParams.java
@@ -0,0 +1,8 @@
+package NET.worlds.scape;
+
+class AudibleParams {
+ public Room room;
+ public Point3 position;
+ public Transform transform;
+ public int hopcount;
+}
diff --git a/NET/worlds/scape/BGLoaded.java b/NET/worlds/scape/BGLoaded.java
new file mode 100644
index 0000000..ba1671a
--- /dev/null
+++ b/NET/worlds/scape/BGLoaded.java
@@ -0,0 +1,11 @@
+package NET.worlds.scape;
+
+import NET.worlds.network.URL;
+
+public interface BGLoaded {
+ Object asyncBackgroundLoad(String var1, URL var2);
+
+ boolean syncBackgroundLoad(Object var1, URL var2);
+
+ Room getBackgroundLoadRoom();
+}
diff --git a/NET/worlds/scape/BackgroundLoader.java b/NET/worlds/scape/BackgroundLoader.java
new file mode 100644
index 0000000..8f337a0
--- /dev/null
+++ b/NET/worlds/scape/BackgroundLoader.java
@@ -0,0 +1,95 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Main;
+import NET.worlds.console.MainCallback;
+import NET.worlds.network.URL;
+import java.util.Vector;
+
+public class BackgroundLoader implements MainCallback, Runnable {
+ private static BackgroundLoader bg = new BackgroundLoader();
+ private BackgroundLoaderQueue readQueue = new BackgroundLoaderQueue();
+ private BackgroundLoaderQueue asyncLoadQueue = new BackgroundLoaderQueue();
+ private Vector syncLoadQueue = new Vector();
+ private Thread asyncLoaderThread;
+ int nextSync = 0;
+
+ public static void get(BGLoaded loader, String remoteName) {
+ get(loader, URL.make(remoteName), false);
+ }
+
+ public static void get(BGLoaded loader, URL remoteName) {
+ get(loader, remoteName, false);
+ }
+
+ public static void get(BGLoaded loader, URL remoteName, boolean highPri) {
+ new BackgroundLoaderElement(loader, remoteName, highPri);
+ }
+
+ static void activeRoomChanged(Room room) {
+ bg.asyncLoadQueue.activeRoomChanged(room);
+ }
+
+ static void asyncLoad(BackgroundLoaderElement ele) {
+ bg.asyncLoadQueue.add(ele);
+ }
+
+ static void syncLoad(BackgroundLoaderElement ele) {
+ bg.syncLoadQueue.addElement(ele);
+ }
+
+ private BackgroundLoader() {
+ this.asyncLoaderThread = new Thread(this);
+ this.asyncLoaderThread.setDaemon(true);
+ this.asyncLoaderThread.start();
+ Main.register(this);
+ }
+
+ @Override
+ public void run() {
+ if ($assertionsDisabled || Thread.currentThread() == this.asyncLoaderThread) {
+ while (true) {
+ BackgroundLoaderElement ele = this.asyncLoadQueue.getItem();
+ ele.asyncLoad();
+ synchronized (this) {
+ this.syncLoadQueue.addElement(ele);
+
+ while (this.syncLoadQueue.size() > 0) {
+ try {
+ this.wait();
+ } catch (InterruptedException var4) {
+ }
+
+ if (this.asyncLoadQueue.hasHighPriorityItems()) {
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ throw new AssertionError();
+ }
+
+ @Override
+ public synchronized void mainCallback() {
+ if (this.syncLoadQueue.size() != 0) {
+ if (this.nextSync >= this.syncLoadQueue.size()) {
+ this.nextSync = 0;
+ }
+
+ BackgroundLoaderElement ele = (BackgroundLoaderElement)this.syncLoadQueue.elementAt(this.nextSync);
+ if (!ele.syncLoad()) {
+ this.syncLoadQueue.removeElementAt(this.nextSync);
+ if (this.syncLoadQueue.size() == 0) {
+ this.notify();
+ }
+ } else {
+ if (this.asyncLoadQueue.hasHighPriorityItems()) {
+ this.notify();
+ }
+
+ this.nextSync++;
+ }
+ }
+ }
+}
diff --git a/NET/worlds/scape/BackgroundLoaderElement.java b/NET/worlds/scape/BackgroundLoaderElement.java
new file mode 100644
index 0000000..aba150a
--- /dev/null
+++ b/NET/worlds/scape/BackgroundLoaderElement.java
@@ -0,0 +1,87 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Main;
+import NET.worlds.core.IniFile;
+import NET.worlds.network.Cache;
+import NET.worlds.network.CacheFile;
+import NET.worlds.network.URL;
+import java.util.Observable;
+import java.util.Observer;
+
+class BackgroundLoaderElement implements Observer {
+ private BGLoaded object;
+ private Object arg;
+ private URL url;
+ private Room room;
+ private boolean inAllRooms;
+ private CacheFile rfile;
+ private static boolean immedLoadLocals = IniFile.gamma().getIniInt("BackgroundLoadLocalFiles", 0) == 0;
+
+ BackgroundLoaderElement(BGLoaded object, URL url, boolean inAllRooms) {
+ boolean isMain = Main.isMainThread();
+ this.object = object;
+ this.url = url;
+ if (inAllRooms) {
+ this.inAllRooms = true;
+ } else {
+ this.getRoom(isMain);
+ }
+
+ this.read(isMain);
+ }
+
+ @Override
+ public void update(Observable o, Object url) {
+ BackgroundLoader.asyncLoad(this);
+ }
+
+ private void read(boolean isMain) {
+ this.rfile = this.url != null && this.url.isRemote() ? Cache.getFile(this.url) : null;
+ if ((this.rfile == null || this.rfile.done()) && immedLoadLocals) {
+ this.asyncLoad();
+ if (!isMain || this.syncLoad()) {
+ BackgroundLoader.syncLoad(this);
+ }
+ } else if (this.rfile == null) {
+ BackgroundLoader.asyncLoad(this);
+ } else {
+ this.rfile.callWhenLoaded(this);
+ }
+ }
+
+ void asyncLoad() {
+ String name;
+ if (this.rfile == null) {
+ name = this.url.unalias();
+ } else {
+ name = this.rfile.getLocalName();
+ }
+
+ this.arg = this.object.asyncBackgroundLoad(name, this.url);
+ }
+
+ boolean syncLoad() {
+ if (this.object.syncBackgroundLoad(this.arg, this.url)) {
+ return true;
+ } else {
+ if (this.rfile != null) {
+ this.rfile.finalize();
+ this.rfile = null;
+ }
+
+ return false;
+ }
+ }
+
+ boolean inAllRooms() {
+ return this.inAllRooms;
+ }
+
+ Room getRoom(boolean isMainThread) {
+ if (this.room == null && !this.inAllRooms && isMainThread) {
+ this.room = this.object.getBackgroundLoadRoom();
+ }
+
+ return this.room;
+ }
+}
diff --git a/NET/worlds/scape/BackgroundLoaderQueue.java b/NET/worlds/scape/BackgroundLoaderQueue.java
new file mode 100644
index 0000000..97eacd9
--- /dev/null
+++ b/NET/worlds/scape/BackgroundLoaderQueue.java
@@ -0,0 +1,158 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Main;
+import NET.worlds.console.MainCallback;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+class BackgroundLoaderQueue implements MainCallback {
+ private Room activeRoom;
+ private int itemsInQueue;
+ private BackgroundLoaderVector inAllRooms = new BackgroundLoaderVector();
+ private BackgroundLoaderVector inUnknownRoom = new BackgroundLoaderVector();
+ private Hashtable rooms = new Hashtable();
+ private boolean mainRan;
+
+ synchronized void activeRoomChanged(Room room) {
+ this.activeRoom = room;
+ }
+
+ public boolean hasHighPriorityItems() {
+ return this.inAllRooms.size() > 0;
+ }
+
+ synchronized void add(BackgroundLoaderElement e) {
+ if (!this.addHelper(e, false)) {
+ if (e.inAllRooms()) {
+ this.inAllRooms.insertElementAt(e, 0);
+ } else {
+ this.inUnknownRoom.addElement(e);
+ }
+ }
+
+ this.itemsInQueue++;
+ this.notify();
+ }
+
+ private boolean addHelper(BackgroundLoaderElement e, boolean isMainThread) {
+ Room r = e.getRoom(isMainThread);
+ if (r != null && r.isActive()) {
+ BackgroundLoaderVector v = (BackgroundLoaderVector)this.rooms.get(r);
+ if (v == null) {
+ this.rooms.put(r, v = new BackgroundLoaderVector());
+ }
+
+ v.addElement(e);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ private BackgroundLoaderElement getHelper(Room r) {
+ BackgroundLoaderElement e = null;
+ BackgroundLoaderVector v = (BackgroundLoaderVector)this.rooms.get(r);
+ if (v != null) {
+ e = v.removeFirst();
+ if (v.isEmpty()) {
+ this.rooms.remove(r);
+ }
+ }
+
+ return e;
+ }
+
+ synchronized BackgroundLoaderElement getItem() {
+ BackgroundLoaderElement e = null;
+
+ while (true) {
+ while (this.itemsInQueue == 0) {
+ try {
+ this.wait();
+ } catch (InterruptedException var3) {
+ }
+ }
+
+ if (this.inAllRooms.size() != 0) {
+ e = this.inAllRooms.removeFirst();
+ break;
+ }
+
+ if (this.activeRoom != null && (e = this.getHelper(this.activeRoom)) != null) {
+ break;
+ }
+
+ this.mainRan = false;
+ Main.register(this);
+
+ while (!this.mainRan) {
+ try {
+ this.wait();
+ } catch (InterruptedException var4) {
+ }
+ }
+
+ if (this.inAllRooms.size() == 0 && (this.activeRoom == null || this.rooms.get(this.activeRoom) == null)) {
+ if ((e = this.getClosestObject()) == null) {
+ if (this.inUnknownRoom.size() != 0) {
+ e = this.inUnknownRoom.removeFirst();
+ } else {
+ Enumeration k = this.rooms.keys();
+
+ assert k.hasMoreElements();
+
+ e = this.getHelper((Room)k.nextElement());
+
+ assert e != null;
+ }
+ }
+ break;
+ }
+ }
+
+ assert e != null;
+
+ this.itemsInQueue--;
+
+ assert this.itemsInQueue >= 0;
+
+ return e;
+ }
+
+ private BackgroundLoaderElement getClosestObject() {
+ synchronized (Pilot.visibleRooms) {
+ float minDist = Float.MAX_VALUE;
+ int minEle = -1;
+ int count = Pilot.visibleRoomInfo.size();
+
+ for (int i = 0; i < count; i++) {
+ RoomSubscribeInfo s = Pilot.visibleRoomInfo.elementAt(i);
+ if (s.d < minDist && this.rooms.get(Pilot.visibleRooms.elementAt(i)) != null) {
+ minDist = s.d;
+ minEle = i;
+ }
+ }
+
+ return minEle == -1 ? null : this.getHelper(Pilot.visibleRooms.elementAt(minEle));
+ }
+ }
+
+ @Override
+ public synchronized void mainCallback() {
+ int count = this.inUnknownRoom.size();
+ int i = 0;
+
+ while (count-- != 0) {
+ BackgroundLoaderElement e = (BackgroundLoaderElement)this.inUnknownRoom.get(i);
+ if (this.addHelper(e, true)) {
+ this.inUnknownRoom.removeElementAt(i);
+ } else {
+ i++;
+ }
+ }
+
+ this.mainRan = true;
+ Main.unregister(this);
+ this.notify();
+ }
+}
diff --git a/NET/worlds/scape/BackgroundLoaderVector.java b/NET/worlds/scape/BackgroundLoaderVector.java
new file mode 100644
index 0000000..91ae254
--- /dev/null
+++ b/NET/worlds/scape/BackgroundLoaderVector.java
@@ -0,0 +1,16 @@
+package NET.worlds.scape;
+
+import java.util.Vector;
+
+class BackgroundLoaderVector extends Vector {
+ BackgroundLoaderElement removeFirst() {
+ BackgroundLoaderElement ret = (BackgroundLoaderElement)this.elementAt(0);
+ this.removeElementAt(0);
+ return ret;
+ }
+
+ @Override
+ public synchronized Object get(int i) {
+ return this.elementAt(i);
+ }
+}
diff --git a/NET/worlds/scape/BadFormatException.java b/NET/worlds/scape/BadFormatException.java
new file mode 100644
index 0000000..013de24
--- /dev/null
+++ b/NET/worlds/scape/BadFormatException.java
@@ -0,0 +1,10 @@
+package NET.worlds.scape;
+
+public class BadFormatException extends Exception {
+ public BadFormatException() {
+ }
+
+ public BadFormatException(String s) {
+ super(s);
+ }
+}
diff --git a/NET/worlds/scape/Billboard.java b/NET/worlds/scape/Billboard.java
new file mode 100644
index 0000000..7c30a3b
--- /dev/null
+++ b/NET/worlds/scape/Billboard.java
@@ -0,0 +1,428 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.DefaultConsole;
+import NET.worlds.console.NoWebControlException;
+import NET.worlds.console.WebControl;
+import NET.worlds.console.WebControlFactory;
+import NET.worlds.console.WebControlImp;
+import NET.worlds.console.WebControlListener;
+import NET.worlds.core.IniFile;
+import NET.worlds.network.URL;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Billboard extends Attribute implements WebControlListener {
+ WebControlImp _wci = null;
+ TextureSurface _surface;
+ Texture[] _textures;
+ Material _material = null;
+ String _textureURL = "$SCRIPTSERVERgetad.pl?u=$USERNAME";
+ String _adURL = "http://www.worlds.com/";
+ String _defTextureURL = IniFile.override().getIniString("defaultAd", "adworlds.cmp");
+ int _xPercent = 100;
+ int _yPercent = 100;
+ int _xSurface = 468;
+ int _ySurface = 60;
+ boolean _hasToolbar = true;
+ boolean _isFixed = false;
+ int _rows = 1;
+ int _refresh = 5;
+ boolean _passClicks = true;
+ boolean _isAdBanner = true;
+ boolean _retryURL = false;
+ int frameCnt = -1;
+ private static Object classCookie = new Object();
+
+ public Billboard(int attrID) {
+ super(attrID);
+ }
+
+ public Billboard() {
+ }
+
+ @Override
+ public final void noteChange() {
+ }
+
+ @Override
+ protected void noteAddingTo(SuperRoot owner) {
+ Rect s = (Rect)((Sharer)owner).getOwner();
+ s._billboardAttribute = this;
+ this.assignMaterial(s);
+ }
+
+ private void assignMaterial(Rect s) {
+ int xTex = this._xSurface / 128;
+ if (xTex < 1) {
+ xTex = 1;
+ }
+
+ int yTex = this._ySurface / 128;
+ if (yTex < 1) {
+ yTex = 1;
+ }
+
+ this._surface = null;
+ if (this._wci != null) {
+ this._wci.detach();
+ }
+
+ this._wci = null;
+ this._rows = yTex;
+ this._material = new Material(URL.make(this._defTextureURL), xTex, yTex);
+ s.setMaterial(this._material);
+ this._textures = this._material.getTextures();
+ this._surface = new TextureSurface(this._textures, yTex, this._xSurface, this._ySurface);
+
+ try {
+ this._wci = WebControlFactory.createWebControlImp(this._surface.getHwnd(), false, this._isAdBanner);
+ } catch (NoWebControlException var5) {
+ System.out.println("Could not create MSIE control for billboard.");
+ this._wci = null;
+ return;
+ }
+
+ if (!this._wci.setURL(this._textureURL)) {
+ this._retryURL = true;
+ }
+
+ this._wci.addListener(this);
+ }
+
+ private void setTexture() {
+ Sharer sh = (Sharer)this.getOwner();
+ if (sh != null) {
+ Rect s = (Rect)sh.getOwner();
+ this.assignMaterial(s);
+ }
+ }
+
+ @Override
+ public void detach() {
+ Rect s = (Rect)((Sharer)this.getOwner()).getOwner();
+ s._billboardAttribute = null;
+ if (this._wci != null) {
+ this._wci.detach();
+ }
+
+ super.detach();
+ }
+
+ @Override
+ public void finalize() {
+ this.releaseAuxilaryData();
+ super.finalize();
+ }
+
+ public boolean getIsAdBanner() {
+ return this._isAdBanner;
+ }
+
+ public void billboardClicked(Point2 pt) {
+ if (this._passClicks) {
+ double realX = (double)pt.x * this._surface.getWidth();
+ double realY = (double)pt.y * this._surface.getHeight();
+ realY = this._surface.getHeight() - realY;
+ this._surface.sendLeftClick((int)realX, (int)realY);
+ } else {
+ Console c = Console.getActive();
+ if (c != null && c instanceof DefaultConsole) {
+ DefaultConsole dc = (DefaultConsole)c;
+
+ try {
+ WebControl wc = new WebControl(dc.getRender(), this._xPercent, this._yPercent, this._hasToolbar, this._isFixed, false);
+ wc.activate();
+ wc.setURL(this._adURL);
+ } catch (NoWebControlException var6) {
+ new SendURLAction(this._adURL).doIt();
+ }
+ }
+ }
+ }
+
+ public void billboardFrame(FrameEvent f) {
+ if (this._retryURL && this._wci != null) {
+ if (!this._wci.setURL(this._textureURL)) {
+ return;
+ }
+
+ this._retryURL = false;
+ }
+
+ if (this._surface != null) {
+ if (this.frameCnt <= this._refresh && this.frameCnt != -1) {
+ this.frameCnt++;
+ } else {
+ if (this.frameCnt != -1 && this._refresh == -1) {
+ return;
+ }
+
+ this.frameCnt = 0;
+ this.draw();
+ }
+ }
+ }
+
+ public synchronized void draw() {
+ if (this._surface != null && this._wci != null) {
+ this._surface.setTextures(this._material.getTextures(), this._rows);
+ this._surface.draw(this._wci);
+ }
+ }
+
+ @Override
+ public void webControlEvent(int eventID) {
+ if (eventID == 1 && this._refresh == -1) {
+ this.draw();
+ }
+ }
+
+ @Override
+ public void generateNetData(DataOutputStream s) throws IOException {
+ s.writeUTF(this._adURL);
+ s.writeUTF(this._textureURL);
+ s.writeInt(this._xPercent);
+ s.writeInt(this._yPercent);
+ s.writeInt(this._xSurface);
+ s.writeInt(this._ySurface);
+ s.writeInt(this._refresh);
+ s.writeInt(this._hasToolbar ? 1 : 0);
+ s.writeInt(this._isFixed ? 1 : 0);
+ s.writeInt(this._passClicks ? 1 : 0);
+ s.writeInt(this._isAdBanner ? 1 : 0);
+ }
+
+ @Override
+ public void setFromNetData(DataInputStream ds, int len) throws IOException {
+ this._adURL = ds.readUTF();
+ this._textureURL = ds.readUTF();
+ this._xPercent = ds.readInt();
+ this._yPercent = ds.readInt();
+ this._xSurface = ds.readInt();
+ this._ySurface = ds.readInt();
+ this._refresh = ds.readInt();
+ this._hasToolbar = ds.readInt() == 1;
+ this._isFixed = ds.readInt() == 1;
+ this._passClicks = ds.readInt() == 1;
+ this._isAdBanner = ds.readInt() == 1;
+ this.noteChange();
+ this.setTexture();
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Target URL"));
+ } else if (mode == 1) {
+ ret = this._adURL;
+ } else if (mode == 2) {
+ this._adURL = (String)value;
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Texture URL"));
+ } else if (mode == 1) {
+ ret = this._textureURL;
+ } else if (mode == 2) {
+ this._textureURL = (String)value;
+ this.setTexture();
+ }
+ break;
+ case 2:
+ if (mode == 0) {
+ ret = IntegerPropertyEditor.make(new Property(this, index, "X Overlay % or Width"), 0, 1024);
+ } else if (mode == 1) {
+ ret = new Integer(this._xPercent);
+ } else if (mode == 2) {
+ this._xPercent = (Integer)value;
+ }
+ break;
+ case 3:
+ if (mode == 0) {
+ ret = IntegerPropertyEditor.make(new Property(this, index, "Y Overlay % or Height"), 0, 1024);
+ } else if (mode == 1) {
+ ret = new Integer(this._yPercent);
+ } else if (mode == 2) {
+ this._yPercent = (Integer)value;
+ }
+ break;
+ case 4:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Has Toolbar"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(this._hasToolbar);
+ } else if (mode == 2) {
+ this._hasToolbar = (Boolean)value;
+ }
+ break;
+ case 5:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Fixed size"), "No - Percentage specified", "Yes - Pixels specified");
+ } else if (mode == 1) {
+ ret = new Boolean(this._isFixed);
+ } else if (mode == 2) {
+ this._isFixed = (Boolean)value;
+ }
+ break;
+ case 6:
+ if (mode == 0) {
+ ret = IntegerPropertyEditor.make(new Property(this, index, "Texture Width"), 0, 1024);
+ } else if (mode == 1) {
+ ret = new Integer(this._xSurface);
+ } else if (mode == 2) {
+ this._xSurface = (Integer)value;
+ this.setTexture();
+ }
+ break;
+ case 7:
+ if (mode == 0) {
+ ret = IntegerPropertyEditor.make(new Property(this, index, "Texture Height"), 0, 1024);
+ } else if (mode == 1) {
+ ret = new Integer(this._ySurface);
+ } else if (mode == 2) {
+ this._ySurface = (Integer)value;
+ this.setTexture();
+ }
+ break;
+ case 8:
+ if (mode == 0) {
+ ret = IntegerPropertyEditor.make(new Property(this, index, "Texture Refresh Rate"), -1, 1024);
+ } else if (mode == 1) {
+ ret = new Integer(this._refresh);
+ } else if (mode == 2) {
+ this._refresh = (Integer)value;
+ }
+ break;
+ case 9:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(
+ new Property(this, index, "Pass clicks"), "No - Click launches specified page", "Yes - Mouse events passed through to texture page"
+ );
+ } else if (mode == 1) {
+ ret = new Boolean(this._passClicks);
+ } else if (mode == 2) {
+ this._passClicks = (Boolean)value;
+ }
+ break;
+ case 10:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Is Ad Banner"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(this._isAdBanner);
+ } else if (mode == 2) {
+ this._isAdBanner = (Boolean)value;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 11, mode, value);
+ }
+
+ if (mode == 2) {
+ this.noteChange();
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(3, classCookie);
+ super.saveState(s);
+ s.saveString(this._adURL);
+ s.saveString(this._textureURL);
+ s.saveInt(this._xPercent);
+ s.saveInt(this._yPercent);
+ s.saveBoolean(this._hasToolbar);
+ s.saveBoolean(this._isFixed);
+ s.saveInt(this._xSurface);
+ s.saveInt(this._ySurface);
+ s.saveInt(this._refresh);
+ s.saveBoolean(this._passClicks);
+ s.saveBoolean(this._isAdBanner);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ this._adURL = r.restoreString();
+ this._textureURL = r.restoreString();
+ this._xPercent = r.restoreInt();
+ this._yPercent = r.restoreInt();
+ this._hasToolbar = r.restoreBoolean();
+ this.noteChange();
+ break;
+ case 1:
+ super.restoreState(r);
+ this._adURL = r.restoreString();
+ this._textureURL = r.restoreString();
+ this._xPercent = r.restoreInt();
+ this._yPercent = r.restoreInt();
+ this._hasToolbar = r.restoreBoolean();
+ this._isFixed = r.restoreBoolean();
+ this.noteChange();
+ break;
+ case 2:
+ super.restoreState(r);
+ this._adURL = r.restoreString();
+ this._textureURL = r.restoreString();
+ this._xPercent = r.restoreInt();
+ this._yPercent = r.restoreInt();
+ this._hasToolbar = r.restoreBoolean();
+ this._isFixed = r.restoreBoolean();
+ this._xSurface = r.restoreInt();
+ this._ySurface = r.restoreInt();
+ this._refresh = r.restoreInt();
+ this._passClicks = r.restoreBoolean();
+ this.noteChange();
+ break;
+ case 3:
+ super.restoreState(r);
+ this._adURL = r.restoreString();
+ this._textureURL = r.restoreString();
+ this._xPercent = r.restoreInt();
+ this._yPercent = r.restoreInt();
+ this._hasToolbar = r.restoreBoolean();
+ this._isFixed = r.restoreBoolean();
+ this._xSurface = r.restoreInt();
+ this._ySurface = r.restoreInt();
+ this._refresh = r.restoreInt();
+ this._passClicks = r.restoreBoolean();
+ this._isAdBanner = r.restoreBoolean();
+ this.noteChange();
+ break;
+ default:
+ throw new TooNewException();
+ }
+
+ this.setTexture();
+ }
+
+ @Override
+ public void releaseAuxilaryData() {
+ if (this._wci != null) {
+ this._wci.detach();
+ this._wci = null;
+ }
+
+ if (this._surface != null) {
+ this._surface.finalize();
+ this._surface = null;
+ }
+
+ if (this._material != null) {
+ this._material.detach();
+ this._material.finalize();
+ this._material = null;
+ }
+
+ this._textures = null;
+ }
+}
diff --git a/NET/worlds/scape/BizCard.java b/NET/worlds/scape/BizCard.java
new file mode 100644
index 0000000..902d071
--- /dev/null
+++ b/NET/worlds/scape/BizCard.java
@@ -0,0 +1,126 @@
+package NET.worlds.scape;
+
+import NET.worlds.core.IniFile;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class BizCard extends Attribute {
+ String[] _line = new String[]{"", "", "", "", ""};
+ private static Object classCookie = new Object();
+
+ public BizCard(int attrID) {
+ super(attrID);
+ this.loadIni();
+ }
+
+ public BizCard() {
+ }
+
+ private void loadIni() {
+ for (int i = 0; i < 5; i++) {
+ this._line[i] = IniFile.gamma().getIniString("BizCard" + i, this._line[i]);
+ }
+ }
+
+ public String[] get() {
+ return this._line;
+ }
+
+ public void set(String[] lines) {
+ int total = 0;
+
+ for (int i = 0; i < this._line.length; i++) {
+ int l = lines[i].length();
+ total += l;
+ if (total < 200 && lines[i] != null) {
+ this._line[i] = lines[i];
+ } else {
+ this._line[i] = "";
+ }
+ }
+
+ this.noteChange();
+ }
+
+ @Override
+ protected void noteAddingTo(SuperRoot owner) {
+ this.set(this._line);
+ }
+
+ @Override
+ public void generateNetData(DataOutputStream s) throws IOException {
+ s.writeInt(this._line.length);
+
+ for (int i = 0; i < this._line.length; i++) {
+ s.writeUTF(this._line[i]);
+ }
+ }
+
+ @Override
+ public void setFromNetData(DataInputStream ds, int len) throws IOException {
+ int nLines = ds.readInt();
+ String[] serverLines = new String[nLines];
+
+ for (int i = 0; i < nLines; i++) {
+ serverLines[i] = ds.readUTF();
+ }
+
+ this.set(serverLines);
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Line " + (index - offset)));
+ } else if (mode == 1) {
+ ret = this._line[index - offset];
+ } else if (mode == 2) {
+ this._line[index - offset] = (String)value;
+ this.set(this._line);
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 5, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(0, classCookie);
+ super.saveState(s);
+ s.saveInt(this._line.length);
+
+ for (int i = 0; i < this._line.length; i++) {
+ s.saveString(this._line[i]);
+ }
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ int nLines = r.restoreInt();
+ this._line = new String[nLines];
+
+ for (int i = 0; i < nLines; i++) {
+ this._line[i] = r.restoreString();
+ }
+
+ this.set(this._line);
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/BooleanFieldEditorDialog.java b/NET/worlds/scape/BooleanFieldEditorDialog.java
new file mode 100644
index 0000000..ea661ca
--- /dev/null
+++ b/NET/worlds/scape/BooleanFieldEditorDialog.java
@@ -0,0 +1,21 @@
+package NET.worlds.scape;
+
+class BooleanFieldEditorDialog extends CheckboxEditorDialog {
+ private Property property;
+
+ BooleanFieldEditorDialog(EditTile parent, String title, Property property, String[] choices) {
+ super(parent, title, choices);
+ this.property = property;
+ this.ready();
+ }
+
+ @Override
+ protected int getValue() {
+ return this.property.get() ? 1 : 0;
+ }
+
+ @Override
+ protected void setValue(int choice) {
+ this.parent.addUndoableSet(this.property, new Boolean(choice == 1));
+ }
+}
diff --git a/NET/worlds/scape/BooleanPropertyEditor.java b/NET/worlds/scape/BooleanPropertyEditor.java
new file mode 100644
index 0000000..83db263
--- /dev/null
+++ b/NET/worlds/scape/BooleanPropertyEditor.java
@@ -0,0 +1,26 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.PolledDialog;
+
+public class BooleanPropertyEditor extends PropEditor {
+ private String[] choices;
+ private String falseName;
+ private String trueName;
+
+ private BooleanPropertyEditor(Property property, String falseName, String trueName) {
+ super(property);
+ this.falseName = falseName;
+ this.trueName = trueName;
+ }
+
+ @Override
+ public PolledDialog edit(EditTile parent, String title) {
+ String[] choices = new String[]{this.falseName, this.trueName};
+ return new BooleanFieldEditorDialog(parent, title, this.property, choices);
+ }
+
+ public static Property make(Property property, String falseName, String trueName) {
+ property.setPropertyType(0);
+ return property.setEditor(new BooleanPropertyEditor(property, falseName, trueName));
+ }
+}
diff --git a/NET/worlds/scape/BoundBoxTemp.java b/NET/worlds/scape/BoundBoxTemp.java
new file mode 100644
index 0000000..31ddc3e
--- /dev/null
+++ b/NET/worlds/scape/BoundBoxTemp.java
@@ -0,0 +1,84 @@
+package NET.worlds.scape;
+
+public class BoundBoxTemp {
+ private static Recycler recycler = new Recycler();
+ public Point3Temp lo;
+ public Point3Temp hi;
+
+ public static BoundBoxTemp make(Point3Temp a, Point3Temp b) {
+ BoundBoxTemp t = (BoundBoxTemp)recycler.alloc();
+ if (t == null) {
+ recycler.recycle(new BoundBoxTemp());
+ t = (BoundBoxTemp)recycler.alloc();
+ }
+
+ t.lo = Point3Temp.make(a);
+ t.hi = Point3Temp.make(b);
+ if (a.x > b.x) {
+ t.lo.x = b.x;
+ t.hi.x = a.x;
+ }
+
+ if (a.y > b.y) {
+ t.lo.y = b.y;
+ t.hi.y = a.y;
+ }
+
+ if (a.z > b.z) {
+ t.lo.z = b.z;
+ t.hi.z = a.z;
+ }
+
+ return t;
+ }
+
+ public static BoundBoxTemp make(BoundBoxTemp b) {
+ return make(b.lo, b.hi);
+ }
+
+ private BoundBoxTemp() {
+ }
+
+ public boolean contains(Point3Temp p) {
+ return p.x >= this.lo.x && p.x <= this.hi.x && p.y >= this.lo.y && p.y <= this.hi.y && p.z >= this.lo.z && p.z <= this.hi.z;
+ }
+
+ public boolean isEmpty() {
+ return this.lo.x == this.hi.x && this.lo.y == this.hi.y && this.lo.z == this.hi.z;
+ }
+
+ public boolean overlaps(BoundBoxTemp r) {
+ return !(this.hi.x < r.lo.x) && !(r.hi.x < this.lo.x) && !(this.hi.y < r.lo.y) && !(r.hi.y < this.lo.y) && !(this.hi.z < r.lo.z) && !(r.hi.z < this.lo.z);
+ }
+
+ public void encompass(Point3Temp p) {
+ if (p.x < this.lo.x) {
+ this.lo.x = p.x;
+ }
+
+ if (p.y < this.lo.y) {
+ this.lo.y = p.y;
+ }
+
+ if (p.z < this.lo.z) {
+ this.lo.z = p.z;
+ }
+
+ if (p.x > this.hi.x) {
+ this.hi.x = p.x;
+ }
+
+ if (p.y > this.hi.y) {
+ this.hi.y = p.y;
+ }
+
+ if (p.z > this.hi.z) {
+ this.hi.z = p.z;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "BoundBoxTemp[lo=" + this.lo + ", hi=" + this.hi + "]";
+ }
+}
diff --git a/NET/worlds/scape/BoxBumpCalc.java b/NET/worlds/scape/BoxBumpCalc.java
new file mode 100644
index 0000000..06e6c50
--- /dev/null
+++ b/NET/worlds/scape/BoxBumpCalc.java
@@ -0,0 +1,61 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+public class BoxBumpCalc extends BumpCalc {
+ private static Object classCookie = new Object();
+
+ @Override
+ public void detectBump(BumpEventTemp b, WObject owner) {
+ BoundBoxTemp box = owner.getBoundBox();
+ BoundBoxTemp sourceBox = ((WObject)b.source).getBoundBox();
+ box.lo.minus(sourceBox.hi.minus(b.sourceAt));
+ box.hi.minus(sourceBox.lo.minus(b.sourceAt));
+ Point3Temp pos = Point3Temp.make();
+ pos.x = box.lo.x;
+ pos.y = box.lo.y;
+ float xExtent = box.hi.x - box.lo.x;
+ float yExtent = box.hi.y - box.lo.y;
+ Point3Temp d = Point3Temp.make(xExtent, 0.0F, 0.0F);
+ Point3Temp extent = Point3Temp.make(0.0F, yExtent / 2.0F, 0.0F);
+ if (!b.hitTriRegion(owner, pos, d, extent)) {
+ pos.x = box.hi.x;
+ pos.y = box.hi.y;
+ d.x = -d.x;
+ extent.y = -extent.y;
+ if (!b.hitTriRegion(owner, pos, d, extent)) {
+ pos.y = box.lo.y;
+ d.y = yExtent;
+ d.x = 0.0F;
+ extent.x = -xExtent / 2.0F;
+ extent.y = 0.0F;
+ if (!b.hitTriRegion(owner, pos, d, extent)) {
+ pos.x = box.lo.x;
+ pos.y = box.hi.y;
+ d.y = -d.y;
+ extent.x = -extent.x;
+ if (!b.hitTriRegion(owner, pos, d, extent)) {
+ ;
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(0, classCookie);
+ super.saveState(s);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/BuildRamp.java b/NET/worlds/scape/BuildRamp.java
new file mode 100644
index 0000000..fc4a2e0
--- /dev/null
+++ b/NET/worlds/scape/BuildRamp.java
@@ -0,0 +1,310 @@
+package NET.worlds.scape;
+
+import java.awt.Color;
+import java.io.IOException;
+
+public class BuildRamp extends SwitchableBehavior implements FrameHandler, Persister {
+ protected boolean doBuild = false;
+ protected boolean built = false;
+ protected WrRamp ramp = null;
+ protected String stairName = "ramp";
+ protected float length = 1000.0F;
+ protected float width = 300.0F;
+ protected float pWidth = 250.0F;
+ protected float pHeight = 240.0F;
+ protected float dz = 300.0F;
+ protected float lintelZ = 50.0F;
+ protected float floorTileX = 300.0F;
+ protected float floorTileY = 200.0F;
+ protected float ceilTileX = 300.0F;
+ protected float ceilTileY = 200.0F;
+ protected float leftTileX = 100.0F;
+ protected float leftTileY = 100.0F;
+ protected float rightTileX = 100.0F;
+ protected float rightTileY = 100.0F;
+ protected Material floor = new Material(Color.green);
+ protected Material left = new Material(Color.cyan);
+ protected Material right = new Material(Color.red);
+ protected Material doorpost = new Material(Color.yellow);
+ protected Material lintel = new Material(Color.magenta);
+ protected Material ceiling = new Material(Color.blue);
+ protected String worldURL = null;
+
+ protected void build(Portal end1) {
+ Room room = end1.getRoom();
+ World world = room.getWorld();
+ this.ramp = new WrRamp(
+ world,
+ this.stairName,
+ this.length,
+ this.width,
+ this.pWidth,
+ this.pHeight,
+ this.dz,
+ this.lintelZ,
+ this.floorTileX,
+ this.floorTileY,
+ this.ceilTileX,
+ this.ceilTileY,
+ this.leftTileX,
+ this.leftTileY,
+ this.rightTileX,
+ this.rightTileY,
+ this.floor,
+ this.left,
+ this.right,
+ this.doorpost,
+ this.lintel,
+ this.ceiling
+ );
+ end1.biconnect(this.ramp.portal1);
+ this.built = true;
+ end1.removeHandler(this);
+ }
+
+ protected void unbuild(Portal end1) {
+ this.built = false;
+ }
+
+ @Override
+ public boolean handle(FrameEvent e) {
+ if (!this.built && this.doBuild && e.target instanceof Portal) {
+ this.build((Portal)e.target);
+ } else if (this.built && !this.doBuild && e.target instanceof Portal) {
+ this.unbuild((Portal)e.target);
+ }
+
+ return true;
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = new ClassProperty(this, index, "BuildRamp");
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Build now?"), "Later", "Now");
+ } else if (mode == 1) {
+ ret = new Boolean(this.doBuild);
+ } else if (mode == 2) {
+ this.doBuild = (Boolean)value;
+ }
+ break;
+ case 2:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Staircase Name"));
+ } else if (mode == 1) {
+ ret = this.stairName;
+ } else if (mode == 2) {
+ this.stairName = (String)value;
+ }
+ break;
+ case 3:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Portal-to-portal Distance"));
+ } else if (mode == 1) {
+ ret = new Float(this.length);
+ } else if (mode == 2) {
+ this.length = (Float)value;
+ }
+ break;
+ case 4:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Stairwell Width"));
+ } else if (mode == 1) {
+ ret = new Float(this.width);
+ } else if (mode == 2) {
+ this.width = (Float)value;
+ }
+ break;
+ case 5:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Portal Width"));
+ } else if (mode == 1) {
+ ret = new Float(this.pWidth);
+ } else if (mode == 2) {
+ this.pWidth = (Float)value;
+ }
+ break;
+ case 6:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Portal Height"));
+ } else if (mode == 1) {
+ ret = new Float(this.pHeight);
+ } else if (mode == 2) {
+ this.pHeight = (Float)value;
+ }
+ break;
+ case 7:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Total Rise"));
+ } else if (mode == 1) {
+ ret = new Float(this.dz);
+ } else if (mode == 2) {
+ this.dz = (Float)value;
+ }
+ break;
+ case 8:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Lintel Height"));
+ } else if (mode == 1) {
+ ret = new Float(this.lintelZ);
+ } else if (mode == 2) {
+ this.lintelZ = (Float)value;
+ }
+ break;
+ case 9:
+ if (mode == 0) {
+ ret = Point2PropertyEditor.make(new Property(this, index, "Floor Tile Size"));
+ } else if (mode == 1) {
+ Point2 coords = new Point2();
+ coords.x = this.floorTileX;
+ coords.y = this.floorTileY;
+ ret = coords;
+ } else if (mode == 2) {
+ this.floorTileX = ((Point2)value).x;
+ this.floorTileY = ((Point2)value).y;
+ }
+ break;
+ case 10:
+ if (mode == 0) {
+ ret = Point2PropertyEditor.make(new Property(this, index, "Ceiling Tile Size"));
+ } else if (mode == 1) {
+ Point2 coords = new Point2();
+ coords.x = this.ceilTileX;
+ coords.y = this.ceilTileY;
+ ret = coords;
+ } else if (mode == 2) {
+ this.ceilTileX = ((Point2)value).x;
+ this.ceilTileY = ((Point2)value).y;
+ }
+ break;
+ case 11:
+ if (mode == 0) {
+ ret = Point2PropertyEditor.make(new Property(this, index, "Left Wall Tile Size"));
+ } else if (mode == 1) {
+ Point2 coords = new Point2();
+ coords.x = this.leftTileX;
+ coords.y = this.leftTileY;
+ ret = coords;
+ } else if (mode == 2) {
+ this.leftTileX = ((Point2)value).x;
+ this.leftTileY = ((Point2)value).y;
+ }
+ break;
+ case 12:
+ if (mode == 0) {
+ ret = Point2PropertyEditor.make(new Property(this, index, "Right Wall Tile Size"));
+ } else if (mode == 1) {
+ Point2 coords = new Point2();
+ coords.x = this.rightTileX;
+ coords.y = this.rightTileY;
+ ret = coords;
+ } else if (mode == 2) {
+ this.rightTileX = ((Point2)value).x;
+ this.rightTileY = ((Point2)value).y;
+ }
+ break;
+ case 13:
+ if (mode == 0) {
+ ret = new Property(this, index, "Floor Material");
+ } else if (mode == 1) {
+ ret = this.floor;
+ }
+ break;
+ case 14:
+ if (mode == 0) {
+ ret = new Property(this, index, "Left Wall Material");
+ } else if (mode == 1) {
+ ret = this.left;
+ }
+ break;
+ case 15:
+ if (mode == 0) {
+ ret = new Property(this, index, "Right Wall Material");
+ } else if (mode == 1) {
+ ret = this.right;
+ }
+ break;
+ case 16:
+ if (mode == 0) {
+ ret = new Property(this, index, "Doorpost Material");
+ } else if (mode == 1) {
+ ret = this.doorpost;
+ }
+ break;
+ case 17:
+ if (mode == 0) {
+ ret = new Property(this, index, "Lintel Material");
+ } else if (mode == 1) {
+ ret = this.lintel;
+ }
+ break;
+ case 18:
+ if (mode == 0) {
+ ret = new Property(this, index, "Ceiling Material");
+ } else if (mode == 1) {
+ ret = this.ceiling;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 19, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public String toString() {
+ return "Ramp: built=" + this.built;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveBoolean(this.built);
+ s.saveString(this.stairName);
+ s.saveFloat(this.length);
+ s.saveFloat(this.width);
+ s.saveFloat(this.pWidth);
+ s.saveFloat(this.pHeight);
+ s.saveFloat(this.dz);
+ s.saveFloat(this.lintelZ);
+ s.saveFloat(this.floorTileX);
+ s.saveFloat(this.floorTileY);
+ s.saveFloat(this.ceilTileX);
+ s.saveFloat(this.ceilTileY);
+ s.saveFloat(this.leftTileX);
+ s.saveFloat(this.leftTileY);
+ s.saveFloat(this.rightTileX);
+ s.saveFloat(this.rightTileY);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException {
+ this.built = r.restoreBoolean();
+ this.stairName = r.restoreString();
+ this.length = r.restoreFloat();
+ this.width = r.restoreFloat();
+ this.pWidth = r.restoreFloat();
+ this.pHeight = r.restoreFloat();
+ this.dz = r.restoreFloat();
+ this.lintelZ = r.restoreFloat();
+ this.floorTileX = r.restoreFloat();
+ this.floorTileY = r.restoreFloat();
+ this.ceilTileX = r.restoreFloat();
+ this.ceilTileY = r.restoreFloat();
+ this.leftTileX = r.restoreFloat();
+ this.leftTileY = r.restoreFloat();
+ this.rightTileX = r.restoreFloat();
+ this.rightTileY = r.restoreFloat();
+ }
+
+ @Override
+ public void postRestore(int version) {
+ }
+}
diff --git a/NET/worlds/scape/BuildStairs.java b/NET/worlds/scape/BuildStairs.java
new file mode 100644
index 0000000..0b3d086
--- /dev/null
+++ b/NET/worlds/scape/BuildStairs.java
@@ -0,0 +1,248 @@
+package NET.worlds.scape;
+
+import java.awt.Color;
+import java.io.IOException;
+
+public class BuildStairs extends SwitchableBehavior implements FrameHandler, Persister {
+ protected boolean doBuild = false;
+ protected boolean built = false;
+ protected WrStaircase stairs = null;
+ protected String stairName = "staircase";
+ protected float length = 1000.0F;
+ protected float width = 300.0F;
+ protected float pWidth = 250.0F;
+ protected float pHeight = 240.0F;
+ protected float dz = 300.0F;
+ protected float lintelZ = 50.0F;
+ protected int numsteps = 10;
+ protected Material riser = new Material(Color.gray);
+ protected Material tread = new Material(Color.green);
+ protected Material left = new Material(Color.cyan);
+ protected Material right = new Material(Color.red);
+ protected Material doorpost = new Material(Color.yellow);
+ protected Material lintel = new Material(Color.magenta);
+ protected Material ceiling = new Material(Color.blue);
+ protected String worldURL = null;
+
+ protected void build(Portal end1) {
+ Room room = end1.getRoom();
+ World world = room.getWorld();
+ this.stairs = new WrStaircase(
+ world,
+ this.stairName,
+ this.length,
+ this.width,
+ this.pWidth,
+ this.pHeight,
+ this.dz,
+ this.lintelZ,
+ this.numsteps,
+ this.riser,
+ this.tread,
+ this.left,
+ this.right,
+ this.doorpost,
+ this.lintel,
+ this.ceiling
+ );
+ end1.biconnect(this.stairs.portal1);
+ this.built = true;
+ end1.removeHandler(this);
+ }
+
+ protected void unbuild(Portal end1) {
+ this.built = false;
+ }
+
+ @Override
+ public boolean handle(FrameEvent e) {
+ if (!this.built && this.doBuild && e.target instanceof Portal) {
+ this.build((Portal)e.target);
+ } else if (this.built && !this.doBuild && e.target instanceof Portal) {
+ this.unbuild((Portal)e.target);
+ }
+
+ return true;
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = new ClassProperty(this, index, "BuildStairs");
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Build now?"), "Later", "Now");
+ } else if (mode == 1) {
+ ret = new Boolean(this.doBuild);
+ } else if (mode == 2) {
+ this.doBuild = (Boolean)value;
+ }
+ break;
+ case 2:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Staircase Name"));
+ } else if (mode == 1) {
+ ret = this.stairName;
+ } else if (mode == 2) {
+ this.stairName = (String)value;
+ }
+ break;
+ case 3:
+ if (mode == 0) {
+ ret = IntegerPropertyEditor.make(new Property(this, index, "Number of Steps"));
+ } else if (mode == 1) {
+ ret = new Integer(this.numsteps);
+ } else if (mode == 2) {
+ this.numsteps = (Integer)value;
+ }
+ break;
+ case 4:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Portal-to-portal Distance"));
+ } else if (mode == 1) {
+ ret = new Float(this.length);
+ } else if (mode == 2) {
+ this.length = (Float)value;
+ }
+ break;
+ case 5:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Stairwell Width"));
+ } else if (mode == 1) {
+ ret = new Float(this.width);
+ } else if (mode == 2) {
+ this.width = (Float)value;
+ }
+ break;
+ case 6:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Portal Width"));
+ } else if (mode == 1) {
+ ret = new Float(this.pWidth);
+ } else if (mode == 2) {
+ this.pWidth = (Float)value;
+ }
+ break;
+ case 7:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Portal Height"));
+ } else if (mode == 1) {
+ ret = new Float(this.pHeight);
+ } else if (mode == 2) {
+ this.pHeight = (Float)value;
+ }
+ break;
+ case 8:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Total Rise"));
+ } else if (mode == 1) {
+ ret = new Float(this.dz);
+ } else if (mode == 2) {
+ this.dz = (Float)value;
+ }
+ break;
+ case 9:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Lintel Height"));
+ } else if (mode == 1) {
+ ret = new Float(this.lintelZ);
+ } else if (mode == 2) {
+ this.lintelZ = (Float)value;
+ }
+ break;
+ case 10:
+ if (mode == 0) {
+ ret = new Property(this, index, "Riser Material");
+ } else if (mode == 1) {
+ ret = this.riser;
+ }
+ break;
+ case 11:
+ if (mode == 0) {
+ ret = new Property(this, index, "Tread Material");
+ } else if (mode == 1) {
+ ret = this.tread;
+ }
+ break;
+ case 12:
+ if (mode == 0) {
+ ret = new Property(this, index, "Left Wall Material");
+ } else if (mode == 1) {
+ ret = this.left;
+ }
+ break;
+ case 13:
+ if (mode == 0) {
+ ret = new Property(this, index, "Right Wall Material");
+ } else if (mode == 1) {
+ ret = this.right;
+ }
+ break;
+ case 14:
+ if (mode == 0) {
+ ret = new Property(this, index, "Doorpost Material");
+ } else if (mode == 1) {
+ ret = this.doorpost;
+ }
+ break;
+ case 15:
+ if (mode == 0) {
+ ret = new Property(this, index, "Lintel Material");
+ } else if (mode == 1) {
+ ret = this.lintel;
+ }
+ break;
+ case 16:
+ if (mode == 0) {
+ ret = new Property(this, index, "Ceiling Material");
+ } else if (mode == 1) {
+ ret = this.ceiling;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 17, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public String toString() {
+ return "Stairs: built=" + this.built;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveBoolean(this.built);
+ s.saveString(this.stairName);
+ s.saveFloat(this.length);
+ s.saveFloat(this.width);
+ s.saveFloat(this.pWidth);
+ s.saveFloat(this.pHeight);
+ s.saveFloat(this.dz);
+ s.saveFloat(this.lintelZ);
+ s.saveInt(this.numsteps);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException {
+ this.built = r.restoreBoolean();
+ this.stairName = r.restoreString();
+ this.length = r.restoreFloat();
+ this.width = r.restoreFloat();
+ this.pWidth = r.restoreFloat();
+ this.pHeight = r.restoreFloat();
+ this.dz = r.restoreFloat();
+ this.lintelZ = r.restoreFloat();
+ this.numsteps = r.restoreInt();
+ }
+
+ @Override
+ public void postRestore(int version) {
+ }
+}
diff --git a/NET/worlds/scape/BumpAttribute.java b/NET/worlds/scape/BumpAttribute.java
new file mode 100644
index 0000000..1944c35
--- /dev/null
+++ b/NET/worlds/scape/BumpAttribute.java
@@ -0,0 +1,56 @@
+package NET.worlds.scape;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class BumpAttribute extends Attribute {
+ private static Object classCookie = new Object();
+
+ public BumpAttribute(int attrID) {
+ super(attrID);
+ }
+
+ public BumpAttribute() {
+ }
+
+ @Override
+ protected void noteAddingTo(SuperRoot owner) {
+ WObject w = (WObject)((Sharer)owner).getOwner();
+ w._bumpableAttribute = this;
+ }
+
+ @Override
+ public void detach() {
+ WObject w = (WObject)((Sharer)this.getOwner()).getOwner();
+ w._bumpableAttribute = null;
+ super.detach();
+ }
+
+ @Override
+ public void generateNetData(DataOutputStream s) throws IOException {
+ s.writeBoolean(((WObject)this.getOwner().getOwner()).getBumpable());
+ }
+
+ @Override
+ public void setFromNetData(DataInputStream ds, int len) throws IOException {
+ ((WObject)this.getOwner().getOwner()).setBumpable(ds.readBoolean());
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(0, classCookie);
+ super.saveState(s);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/BumpCalc.java b/NET/worlds/scape/BumpCalc.java
new file mode 100644
index 0000000..4bc0a0b
--- /dev/null
+++ b/NET/worlds/scape/BumpCalc.java
@@ -0,0 +1,10 @@
+package NET.worlds.scape;
+
+public abstract class BumpCalc extends SuperRoot {
+ public abstract void detectBump(BumpEventTemp var1, WObject var2);
+
+ @Override
+ public String toString() {
+ return this.getName();
+ }
+}
diff --git a/NET/worlds/scape/BumpEventTemp.java b/NET/worlds/scape/BumpEventTemp.java
new file mode 100644
index 0000000..b050a44
--- /dev/null
+++ b/NET/worlds/scape/BumpEventTemp.java
@@ -0,0 +1,151 @@
+package NET.worlds.scape;
+
+public class BumpEventTemp extends Event {
+ private static Recycler recycler = new Recycler();
+ public Point3Temp fullPath;
+ public Point3Temp path;
+ public BoundBoxTemp bound;
+ public float fraction;
+ public Room postBumpRoom;
+ public Transform postBumpPosition;
+ public Point3Temp postBumpPath;
+ public Point3Temp sourceAt;
+ public BoundBoxTemp sourceBoxMinus;
+ public Point3Temp bumpNormal;
+
+ public static BumpEventTemp make(int time, WObject mover, Point3Temp motion) {
+ BumpEventTemp t = (BumpEventTemp)recycler.alloc();
+ if (t == null) {
+ recycler.recycle(new BumpEventTemp(0, null));
+ t = (BumpEventTemp)recycler.alloc();
+ }
+
+ assert t.source == null;
+
+ t.time = time;
+ t.source = mover;
+ t.fullPath = Point3Temp.make(motion);
+ t.path = t.fullPath;
+ t.sourceAt = ((WObject)t.source).getWorldPosition();
+ t.sourceBoxMinus = ((WObject)t.source).getBoundBox();
+ t.sourceBoxMinus.lo.minus(t.sourceAt);
+ t.sourceBoxMinus.hi.minus(t.sourceAt);
+ t.setPathFraction(1.0F);
+ Room r = mover.getRoom();
+ if (r.getBumpable()) {
+ r.detectBump(t);
+ }
+
+ return t;
+ }
+
+ public void recycle() {
+ this.time = 0;
+ this.source = null;
+ this.target = null;
+ this.receiver = null;
+ this.postBumpRoom = null;
+ this.postBumpPath = null;
+ this.postBumpPosition = null;
+ }
+
+ private BumpEventTemp(int time, Object source) {
+ super(time, source, null);
+ }
+
+ public void setPathFraction(float fraction) {
+ this.fraction = fraction;
+ this.path = Point3Temp.make(this.path).times(fraction);
+ this.bound = BoundBoxTemp.make(this.sourceAt, Point3Temp.make(this.sourceAt).plus(this.path));
+ this.bound.lo.plus(this.sourceBoxMinus.lo);
+ this.bound.hi.plus(this.sourceBoxMinus.hi);
+ }
+
+ public float isCollision(Point3Temp left, Point3Temp d, Point3Temp start, Point3Temp motion) {
+ double D = (double)motion.x * -d.y + (double)motion.y * d.x;
+ if (D > 0.0) {
+ Point3Temp C = Point3Temp.make(start).minus(left);
+ double betaNum = (double)C.x * d.y - (double)C.y * d.x;
+ double alphaNum = (double)C.x * motion.y - (double)motion.x * C.y;
+ return alphaNum >= 0.0 && alphaNum <= D && betaNum >= 0.0 && betaNum <= D ? (float)(betaNum / D) : -2.0F;
+ } else {
+ return -1.0F;
+ }
+ }
+
+ public float hitPlane(WObject o, Point3Temp left, Point3Temp d) {
+ float dist = this.isCollision(left, d, this.sourceAt, this.path);
+ if (dist >= 0.0F) {
+ this.target = o;
+ this.setPathFraction(dist);
+ this.bumpNormal = Point3Temp.make(d.y, -d.x, 0.0F).normalize();
+ this.path.plus(Point3Temp.make(this.path).normalize().times(0.2F));
+ }
+
+ return dist;
+ }
+
+ public boolean hitRegion(WObject o, Point3Temp left, Point3Temp d, Point3Temp extent) {
+ float dist = this.hitPlane(o, left, d);
+ if (dist >= 0.0F) {
+ return true;
+ } else if (dist == -1.0F) {
+ return false;
+ } else {
+ Point3Temp right = Point3Temp.make(left).plus(d);
+ Point3Temp minusD = Point3Temp.make().minus(d);
+ Point3Temp minusExtent = Point3Temp.make().minus(extent);
+ if (this.isCollision(right, minusD, this.sourceAt, minusExtent) > 0.0F) {
+ this.target = o;
+ this.setPathFraction(0.0F);
+ this.bumpNormal = minusExtent;
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+
+ public boolean hitTriRegion(WObject o, Point3Temp left, Point3Temp d, Point3Temp extent) {
+ float dist = this.hitPlane(o, left, d);
+ if (dist >= 0.0F) {
+ return true;
+ } else if (dist == -1.0F) {
+ return false;
+ } else {
+ Point3Temp right = Point3Temp.make(left).plus(d);
+ Point3Temp minusD = Point3Temp.make().minus(d);
+ Point3Temp minusExtent = Point3Temp.make().minus(extent);
+ if (this.isCollision(right, minusD, this.sourceAt, minusExtent) > 0.0F) {
+ float dx = this.sourceAt.x - (left.x + d.x / 2.0F);
+ float dy = this.sourceAt.y - (left.y + d.y / 2.0F);
+ float squaredDistFromMid = dx * dx + dy * dy;
+ dx = this.sourceAt.x - (left.x + extent.x);
+ dy = this.sourceAt.y - (left.y + extent.y);
+ float squaredDistFromA = dx * dx + dy * dy;
+ if (squaredDistFromA < squaredDistFromMid) {
+ return false;
+ } else {
+ dx = this.sourceAt.x - (right.x + extent.x);
+ dy = this.sourceAt.y - (right.y + extent.y);
+ float squaredDistFromB = dx * dx + dy * dy;
+ if (squaredDistFromB < squaredDistFromMid) {
+ return false;
+ } else {
+ this.target = o;
+ this.setPathFraction(0.0F);
+ this.bumpNormal = minusExtent;
+ return true;
+ }
+ }
+ } else {
+ return false;
+ }
+ }
+ }
+
+ @Override
+ public boolean deliver(Object o) {
+ return o instanceof BumpHandler ? ((BumpHandler)o).handle(this) : false;
+ }
+}
diff --git a/NET/worlds/scape/BumpHandler.java b/NET/worlds/scape/BumpHandler.java
new file mode 100644
index 0000000..c307e32
--- /dev/null
+++ b/NET/worlds/scape/BumpHandler.java
@@ -0,0 +1,5 @@
+package NET.worlds.scape;
+
+public interface BumpHandler {
+ boolean handle(BumpEventTemp var1);
+}
diff --git a/NET/worlds/scape/BumpSensor.java b/NET/worlds/scape/BumpSensor.java
new file mode 100644
index 0000000..1833a61
--- /dev/null
+++ b/NET/worlds/scape/BumpSensor.java
@@ -0,0 +1,21 @@
+package NET.worlds.scape;
+
+public class BumpSensor extends Sensor implements BumpHandler {
+ public BumpSensor(Action a) {
+ if (a != null) {
+ this.addAction(a);
+ }
+ }
+
+ public BumpSensor() {
+ }
+
+ @Override
+ public boolean handle(BumpEventTemp e) {
+ if (e.source instanceof Pilot) {
+ this.trigger(e);
+ }
+
+ return true;
+ }
+}
diff --git a/NET/worlds/scape/CDAudio.java b/NET/worlds/scape/CDAudio.java
new file mode 100644
index 0000000..2f1ea8f
--- /dev/null
+++ b/NET/worlds/scape/CDAudio.java
@@ -0,0 +1,518 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Main;
+import NET.worlds.console.MainCallback;
+import NET.worlds.console.MainTerminalCallback;
+import NET.worlds.core.IniFile;
+import NET.worlds.network.URL;
+import java.io.File;
+import java.io.IOException;
+import java.util.Vector;
+
+public class CDAudio implements Runnable, MainCallback, MainTerminalCallback {
+ private static final int STOP = 0;
+ private static final int PLAY = 1;
+ private static final int PAUSE = 2;
+ private static final int NEXT = 3;
+ private static final int PREV = 4;
+ private static final int CHANGE = 5;
+ private static final int CHANGE_MIDI = 6;
+ private boolean performedStartupPlay;
+ private boolean cancel;
+ private Thread playerThread;
+ private Vector commandBuffer = new Vector();
+ private boolean paused;
+ private int driveID;
+ private CDTrackInfo tracks;
+ private int trackOffset;
+ private Object tracksMutex = new Object();
+ private int pos;
+ private SoundPlayer midiPlayer;
+ private URL defaultMIDIFile = URL.make("home:start.mid");
+ private URL curMIDIFile = this.defaultMIDIFile;
+ private int trackToRepeat = -1;
+ private int repeatingTrack = -1;
+ private boolean enabled = true;
+ private static CDAudio instance = new CDAudio();
+ static boolean useMidiFlag = IniFile.gamma().getIniInt("MIDIONSTART", 1) != 0;
+ static boolean useAutoCDFlag = IniFile.gamma().getIniInt("AUTOPLAYCD", 1) != 0;
+ private boolean cdInDrive;
+ private boolean allowMIDIAnyway;
+ private boolean midiPaused;
+ private boolean midiStarted;
+
+ public static CDAudio get() {
+ return instance;
+ }
+
+ public String getTimeReadout() {
+ synchronized (this.tracksMutex) {
+ if (this.tracks == null) {
+ this.tracksMutex.notify();
+ return "00 [00:00]";
+ } else {
+ int count = this.tracks.getNumTracks();
+ if (this.pos != 0) {
+ for (int i = 0; i < count; i++) {
+ if (this.pos < this.tracks.getEndFrames(i)) {
+ return fmt2(i + 1) + " " + fmtFrames(this.pos - this.tracks.getStartFrames(i));
+ }
+ }
+ }
+
+ return fmt2(count) + " " + fmtFrames(this.tracks.getEndFrames(count - 1));
+ }
+ }
+ }
+
+ public void setEnabled(boolean state) {
+ if (this.enabled != state) {
+ this.enabled = state;
+ if (!this.enabled) {
+ this.stop();
+ } else {
+ this.change(true);
+ }
+ }
+ }
+
+ public void play() {
+ this.queueCommand(1);
+ }
+
+ public void pause() {
+ this.queueCommand(2);
+ }
+
+ public void stop() {
+ this.queueCommand(0);
+ }
+
+ public void next() {
+ this.queueCommand(3);
+ }
+
+ public void prev() {
+ this.queueCommand(4);
+ }
+
+ public void change(boolean loop) {
+ this.queueCommand(5);
+ }
+
+ public static void startupPlay() {
+ get();
+ }
+
+ public void setMIDIFile(URL url) {
+ this.curMIDIFile = url;
+ }
+
+ public URL getDefaultMIDIFile() {
+ return this.defaultMIDIFile;
+ }
+
+ public URL getMIDIFile() {
+ return this.curMIDIFile;
+ }
+
+ public void setCDTrack(int track) {
+ this.trackToRepeat = track - 1;
+ }
+
+ public int getCDTrack() {
+ return this.trackToRepeat + 1;
+ }
+
+ private CDAudio() {
+ this.playerThread = new Thread(this);
+ this.playerThread.start();
+ }
+
+ @Override
+ public void run() {
+ Main.register(this);
+ int numDrives = CDPlayerAction.getNumDrives();
+
+ while (!this.cancel) {
+ for (int i = 0; i < numDrives; i++) {
+ this.cdInDrive = false;
+
+ try {
+ if ((this.driveID = CDPlayerAction.openDrive(i)) != 0) {
+ if (!CDPlayerAction.isPlaying(this.driveID)) {
+ CDTrackInfo tmp = CDPlayerAction.getDriveTrackList(this.driveID);
+ char drive = (char)(65 + CDPlayerAction.getDriveLetterOffset(i));
+ File f = new File(drive + ":\\WORLDS.CD");
+ if (f.exists()) {
+ synchronized (this.tracksMutex) {
+ this.tracks = tmp;
+ this.trackOffset = 0;
+ if (f.length() == 1L) {
+ this.trackOffset = 1;
+ }
+ }
+
+ this.cdInDrive = true;
+ if (this.performedStartupPlay) {
+ this.flushPendingCommands();
+ } else {
+ this.performedStartupPlay = true;
+ }
+
+ this.change(true);
+ this.waitForCommands();
+ }
+ }
+
+ this.driveID = 0;
+ }
+ } catch (IOException var12) {
+ }
+
+ if (this.driveID != 0) {
+ try {
+ CDPlayerAction.closeDrive(this.driveID);
+ } catch (IOException var10) {
+ }
+
+ this.driveID = 0;
+ this.paused = false;
+ this.pos = 0;
+ }
+ }
+
+ this.performedStartupPlay = true;
+ this.cdInDrive = false;
+ synchronized (this.tracksMutex) {
+ this.tracks = null;
+ }
+
+ if (!this.cancel) {
+ this.timedWait(10);
+ synchronized (this.tracksMutex) {
+ if (!this.cancel) {
+ try {
+ this.tracksMutex.wait();
+ } catch (InterruptedException var7) {
+ }
+ }
+ }
+ }
+ }
+
+ Main.unregister(this);
+ }
+
+ public void useAutoCD(boolean f) {
+ if (f != useAutoCDFlag) {
+ useAutoCDFlag = f;
+ IniFile.gamma().setIniInt("AUTOPLAYCD", useAutoCDFlag ? 1 : 0);
+ if (f) {
+ if (this.trackToRepeat != -1) {
+ this.queueCommand(5);
+ }
+ } else {
+ this.queueCommand(0);
+ }
+ }
+ }
+
+ private synchronized void flushPendingCommands() {
+ this.commandBuffer.removeAllElements();
+ }
+
+ private synchronized void prequeueCommand(int command) {
+ this.commandBuffer.insertElementAt(new Integer(command), 0);
+ }
+
+ private synchronized void queueCommand(int command) {
+ if (command != 6) {
+ this.allowMIDIAnyway = false;
+ }
+
+ this.commandBuffer.addElement(new Integer(command));
+ }
+
+ private synchronized int getQueuedCommand(boolean isMidi) {
+ if (this.commandBuffer.size() <= 0) {
+ return -1;
+ } else {
+ int command = (Integer)this.commandBuffer.elementAt(0);
+ if (command == 6) {
+ if (!isMidi) {
+ return -1;
+ }
+ } else if (isMidi == this.cdInDrive) {
+ return -1;
+ }
+
+ this.commandBuffer.removeElementAt(0);
+ return command;
+ }
+ }
+
+ private synchronized int peekQueuedCommand() {
+ return this.commandBuffer.size() <= 0 ? -1 : (Integer)this.commandBuffer.elementAt(0);
+ }
+
+ private void waitForCommands() throws IOException {
+ while (!this.cancel) {
+ boolean playing = CDPlayerAction.isPlaying(this.driveID);
+ if (playing) {
+ int tmp = CDPlayerAction.getPosition(this.driveID);
+ if (tmp > this.pos) {
+ this.pos = tmp;
+ }
+
+ this.paused = false;
+ } else {
+ CDPlayerAction.checkDrive(this.driveID);
+ if (!this.paused) {
+ this.pos = 0;
+ }
+
+ if (this.repeatingTrack != -1) {
+ this.pos = this.tracks.getStartFrames(this.repeatingTrack + this.trackOffset);
+ CDPlayerAction.playAudio(this.driveID, this.pos, this.tracks.getEndFrames(this.repeatingTrack + this.trackOffset));
+ }
+ }
+
+ int command;
+ if ((command = this.getQueuedCommand(false)) >= 0) {
+ this.processCommand(command, playing);
+ } else {
+ this.timedWait(1);
+ }
+ }
+
+ CDPlayerAction.stopAudio(this.driveID);
+ }
+
+ private void processCommand(int command, boolean playing) throws IOException {
+ int wasRepeatingTrack = this.repeatingTrack;
+ this.repeatingTrack = -1;
+ switch (command) {
+ case 0:
+ if (playing || this.paused) {
+ CDPlayerAction.stopAudio(this.driveID);
+ }
+
+ this.paused = false;
+ break;
+ case 1:
+ if (!playing) {
+ this.play(-this.pos);
+ }
+ break;
+ case 2:
+ if (playing && !this.paused) {
+ CDPlayerAction.stopAudio(this.driveID);
+ this.paused = true;
+ }
+ break;
+ case 3:
+ if (!playing && !this.paused) {
+ this.play(0);
+ } else {
+ for (int ix = 0; ix < this.tracks.getNumTracks() - 1; ix++) {
+ if (this.pos >= this.tracks.getStartFrames(ix) && this.pos < this.tracks.getEndFrames(ix)) {
+ this.play(ix + 1);
+ return;
+ }
+ }
+ }
+ break;
+ case 4:
+ if (playing || this.paused) {
+ for (int i = 0; i < this.tracks.getNumTracks(); i++) {
+ if (this.pos < this.tracks.getEndFrames(i)) {
+ if (i > 0 && this.pos < this.tracks.getStartFrames(i) + 75) {
+ this.play(i - 1);
+ } else {
+ this.play(i);
+ }
+ break;
+ }
+ }
+ }
+ break;
+ case 5:
+ if (useAutoCDFlag && this.enabled) {
+ if (this.trackToRepeat == -1 || this.trackToRepeat < this.tracks.getNumTracks()) {
+ this.repeatingTrack = this.trackToRepeat;
+ if (wasRepeatingTrack == this.trackToRepeat && wasRepeatingTrack != -1) {
+ return;
+ }
+ }
+
+ CDPlayerAction.stopAudio(this.driveID);
+ if (this.repeatingTrack == -1) {
+ this.allowMIDIAnyway = true;
+ this.queueCommand(6);
+ }
+
+ this.paused = false;
+ }
+ }
+ }
+
+ private void play(int location) throws IOException {
+ if (location < 0) {
+ this.pos = -location;
+ } else {
+ this.pos = this.tracks.getStartFrames(location);
+ }
+
+ CDPlayerAction.playAudio(this.driveID, this.pos, this.tracks.getEndFrames(this.tracks.getNumTracks() - 1));
+ this.paused = false;
+ }
+
+ private void startMidi() {
+ if (this.curMIDIFile != this.defaultMIDIFile) {
+ if (this.midiPlayer != null) {
+ this.midiPlayer.stop();
+ this.midiPlayer.close();
+ this.midiStarted = false;
+ if (MCISoundPlayer.isActive() || WMPSoundPlayer.isActive()) {
+ this.midiPlayer = null;
+ return;
+ }
+ } else if (MCISoundPlayer.isActive() || WMPSoundPlayer.isActive()) {
+ return;
+ }
+
+ Sound s = new Sound(this.curMIDIFile);
+ if (!this.curMIDIFile.endsWith(".mid") && !this.curMIDIFile.endsWith(".wav")) {
+ this.midiPlayer = new WMPSoundPlayer(s);
+ } else {
+ this.midiPlayer = new MCISoundPlayer(s);
+ }
+
+ this.midiPlayer.open(1.0F, 0.0F, false, false);
+ if (!this.midiPaused) {
+ this.midiPlayer.start(1);
+ }
+ }
+ }
+
+ private void killMidi() {
+ if (this.midiPlayer != null) {
+ this.midiStarted = false;
+ this.midiPlayer.stop();
+ this.midiPlayer.close();
+ this.midiPlayer = null;
+ }
+ }
+
+ private void useMidi() {
+ if (useMidiFlag && this.enabled && (!this.cdInDrive || this.allowMIDIAnyway)) {
+ if (this.midiPlayer == null) {
+ this.startMidi();
+ } else if (this.midiPlayer.getState() == 1) {
+ if (this.midiStarted) {
+ this.startMidi();
+ this.midiStarted = false;
+ }
+ } else {
+ this.midiStarted = true;
+ }
+ }
+
+ if (!useMidiFlag || !this.enabled || this.cdInDrive && !this.allowMIDIAnyway) {
+ this.killMidi();
+ }
+ }
+
+ public void setMidiFlag(boolean f) {
+ useMidiFlag = f;
+ IniFile.gamma().setIniInt("MIDIONSTART", useMidiFlag ? 1 : 0);
+ }
+
+ @Override
+ public void mainCallback() {
+ if (this.performedStartupPlay) {
+ this.useMidi();
+
+ while (this.midiPlayer != null || this.peekQueuedCommand() == 6) {
+ if (this.cdInDrive && this.repeatingTrack != -1) {
+ if (this.peekQueuedCommand() == 6) {
+ this.getQueuedCommand(true);
+ }
+
+ this.allowMIDIAnyway = false;
+ this.useMidi();
+ return;
+ }
+
+ int command;
+ if ((command = this.getQueuedCommand(true)) < 0) {
+ return;
+ }
+
+ switch (command) {
+ case 0:
+ case 2:
+ this.midiPaused = true;
+ this.midiPlayer.stop();
+ this.midiStarted = false;
+ break;
+ case 1:
+ if (this.midiPaused || !this.midiStarted) {
+ this.midiPaused = false;
+ this.startMidi();
+ }
+ break;
+ case 3:
+ case 4:
+ this.startMidi();
+ break;
+ case 5:
+ case 6:
+ if (useMidiFlag && this.enabled) {
+ this.midiStarted = false;
+ this.midiPaused = false;
+ this.startMidi();
+ }
+ }
+ }
+ }
+ }
+
+ private synchronized void timedWait(int secs) {
+ if (!this.cancel) {
+ try {
+ this.wait(secs * 1000);
+ } catch (InterruptedException var3) {
+ }
+ }
+ }
+
+ @Override
+ public void terminalCallback() {
+ this.cancel = true;
+ this.killMidi();
+ synchronized (this) {
+ this.notify();
+ }
+
+ synchronized (this.tracksMutex) {
+ this.tracksMutex.notify();
+ }
+ }
+
+ private static String fmt2(int val) {
+ return val < 10 ? "0" + val : "" + val;
+ }
+
+ private static String fmtFrames(int frames) {
+ if (frames < 0) {
+ frames = 0;
+ }
+
+ int minutes = frames / 4500;
+ frames -= minutes * 4500;
+ int seconds = frames / 75;
+ return "[" + fmt2(minutes) + ":" + fmt2(seconds) + "]";
+ }
+}
diff --git a/NET/worlds/scape/CDControl.java b/NET/worlds/scape/CDControl.java
new file mode 100644
index 0000000..b881b00
--- /dev/null
+++ b/NET/worlds/scape/CDControl.java
@@ -0,0 +1,88 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.DialogReceiver;
+import NET.worlds.console.PolledDialog;
+import java.awt.Button;
+import java.awt.Checkbox;
+import java.awt.FlowLayout;
+import java.awt.Font;
+import java.awt.GridLayout;
+import java.awt.Label;
+import java.awt.Panel;
+import java.awt.Window;
+
+public class CDControl extends PolledDialog {
+ private Label display;
+ private Button stopButton = new Button("[]");
+ private Button pauseButton = new Button("||");
+ private Button playButton = new Button(">");
+ private Button prevButton = new Button("|<<");
+ private Button nextButton = new Button(">>|");
+ private Panel top = new Panel();
+ private Panel bottom = new Panel();
+ private Checkbox cdBox = new Checkbox(Console.message("Autoplay-CD"), CDAudio.useAutoCDFlag);
+ private Checkbox midiBox = new Checkbox(Console.message("Autoplay-MIDI"), CDAudio.useMidiFlag);
+ private String time;
+ private static Font font = new Font(Console.message("MenuFont"), 0, 12);
+
+ public CDControl(Window parent, DialogReceiver receiver) {
+ super(parent, receiver, Console.message("Music"), false);
+ this.display = new Label(this.time = CDAudio.get().getTimeReadout());
+ this.setAlignment(1);
+ this.ready();
+ }
+
+ @Override
+ protected void build() {
+ this.setLayout(new GridLayout(2, 1));
+ this.top.setLayout(new FlowLayout());
+ this.top.add(this.display);
+ this.top.add(this.stopButton);
+ this.top.add(this.pauseButton);
+ this.top.add(this.playButton);
+ this.top.add(this.prevButton);
+ this.top.add(this.nextButton);
+ this.bottom.setLayout(new GridLayout(2, 1));
+ this.cdBox.setFont(font);
+ this.midiBox.setFont(font);
+ this.bottom.add(this.cdBox);
+ this.bottom.add(this.midiBox);
+ this.add(this.top);
+ this.add(this.bottom);
+ }
+
+ @Override
+ protected void activeCallback() {
+ String tmp = CDAudio.get().getTimeReadout();
+ if (!tmp.equals(this.time)) {
+ this.display.setText(this.time = tmp);
+ }
+ }
+
+ @Override
+ public boolean action(java.awt.Event event, Object what) {
+ Object target = event.target;
+ if (target == this.stopButton) {
+ CDAudio.get().stop();
+ } else if (target == this.pauseButton) {
+ CDAudio.get().pause();
+ } else if (target == this.playButton) {
+ CDAudio.get().play();
+ } else if (target == this.prevButton) {
+ CDAudio.get().prev();
+ } else if (target == this.nextButton) {
+ CDAudio.get().next();
+ } else if (target == this.cdBox) {
+ CDAudio.get().useAutoCD(this.cdBox.getState());
+ } else {
+ if (target != this.midiBox) {
+ return false;
+ }
+
+ CDAudio.get().setMidiFlag(this.midiBox.getState());
+ }
+
+ return true;
+ }
+}
diff --git a/NET/worlds/scape/CDDBConnection.java b/NET/worlds/scape/CDDBConnection.java
new file mode 100644
index 0000000..c446d1d
--- /dev/null
+++ b/NET/worlds/scape/CDDBConnection.java
@@ -0,0 +1,75 @@
+package NET.worlds.scape;
+
+import NET.worlds.network.DNSLookup;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.net.Socket;
+
+class CDDBConnection {
+ private Socket sock;
+ private PrintStream sockOut;
+ private DataInputStream sockIn;
+ private boolean readOnly;
+ private boolean debug;
+
+ public CDDBConnection(CDDBHost host, boolean debug) throws IOException {
+ this.debug = debug;
+ if (debug) {
+ System.out.println("Contacting host " + host);
+ }
+
+ this.sock = new Socket(DNSLookup.lookup(host.getHost()), host.getPort());
+ CDDBLookup.markActivity();
+ this.sockOut = new PrintStream(this.sock.getOutputStream(), true);
+ this.sockIn = new DataInputStream(this.sock.getInputStream());
+ String msg = this.recv();
+ if (msg.startsWith("200 ")) {
+ this.readOnly = false;
+ } else {
+ if (!msg.startsWith("201 ")) {
+ throw new IOException("Can't connect to " + host + ": " + msg);
+ }
+
+ this.readOnly = true;
+ }
+ }
+
+ public String command(String command) throws IOException {
+ this.send(command);
+ return this.recv();
+ }
+
+ public String readBody() throws IOException {
+ String str = this.recv();
+ return str.equals(".") ? null : str;
+ }
+
+ public void close() {
+ try {
+ this.send("quit");
+ this.recv();
+ this.sock.close();
+ } catch (IOException var2) {
+ }
+ }
+
+ private void send(String msg) throws IOException {
+ if (this.debug) {
+ System.out.println("--> " + msg);
+ }
+
+ this.sockOut.println(msg);
+ CDDBLookup.markActivity();
+ }
+
+ private String recv() throws IOException {
+ String msg = this.sockIn.readLine();
+ CDDBLookup.markActivity();
+ if (this.debug) {
+ System.out.println("<-- " + msg);
+ }
+
+ return msg;
+ }
+}
diff --git a/NET/worlds/scape/CDDBHash.java b/NET/worlds/scape/CDDBHash.java
new file mode 100644
index 0000000..5d9ba86
--- /dev/null
+++ b/NET/worlds/scape/CDDBHash.java
@@ -0,0 +1,76 @@
+package NET.worlds.scape;
+
+public class CDDBHash {
+ public static String hashString(CDTrackInfo tracks) {
+ String id = Integer.toHexString(hash(tracks));
+ int len = id.length();
+ if (len >= 8) {
+ return id;
+ } else {
+ String pad = "0";
+
+ while (++len < 8) {
+ pad = pad + "0";
+ }
+
+ return pad + id;
+ }
+ }
+
+ public static String lookupString(CDTrackInfo tracks) {
+ int numTracks = tracks.getNumTracks();
+ String ret = hashString(tracks) + " " + numTracks;
+
+ for (int i = 0; i < numTracks; i++) {
+ ret = ret + " " + tracks.getStartFrames(i);
+ }
+
+ return ret + " " + leadOutSecs(tracks);
+ }
+
+ private static int addDigits(int n) {
+ String buf = "" + n;
+ int ret = 0;
+
+ for (int i = 0; i < buf.length(); i++) {
+ ret += buf.charAt(i) - '0';
+ }
+
+ return ret;
+ }
+
+ private static int leadOutSecs(CDTrackInfo tracks) {
+ int last = tracks.getNumTracks() - 1;
+ int omin = tracks.getPosM(last);
+ int osec = tracks.getPosS(last);
+ int ofrm = tracks.getPosF(last);
+ int lmin = tracks.getLenM(last);
+ int lsec = tracks.getLenS(last);
+ int lfrm = tracks.getLenF(last);
+ if (++lfrm == 75) {
+ lfrm = 0;
+ if (++lsec == 60) {
+ lsec = 0;
+ lmin++;
+ }
+ }
+
+ ofrm += lfrm;
+ osec += ofrm / 75 + lsec;
+ omin += osec / 60 + lmin;
+ osec %= 60;
+ return omin * 60 + osec;
+ }
+
+ private static int hash(CDTrackInfo tracks) {
+ int n = 0;
+ int numTracks = tracks.getNumTracks();
+
+ for (int i = 0; i < numTracks; i++) {
+ n += addDigits(tracks.getPosM(i) * 60 + tracks.getPosS(i));
+ }
+
+ int t = leadOutSecs(tracks) - tracks.getPosM(0) * 60 - tracks.getPosS(0);
+ return n % 255 << 24 | t << 8 | numTracks;
+ }
+}
diff --git a/NET/worlds/scape/CDDBHost.java b/NET/worlds/scape/CDDBHost.java
new file mode 100644
index 0000000..5e7ed15
--- /dev/null
+++ b/NET/worlds/scape/CDDBHost.java
@@ -0,0 +1,24 @@
+package NET.worlds.scape;
+
+class CDDBHost {
+ private String host;
+ private int port;
+
+ public CDDBHost(String host, int port) {
+ this.host = host;
+ this.port = port;
+ }
+
+ public String getHost() {
+ return this.host;
+ }
+
+ public int getPort() {
+ return this.port;
+ }
+
+ @Override
+ public String toString() {
+ return this.host + ":" + this.port;
+ }
+}
diff --git a/NET/worlds/scape/CDDBLookup.java b/NET/worlds/scape/CDDBLookup.java
new file mode 100644
index 0000000..0deef54
--- /dev/null
+++ b/NET/worlds/scape/CDDBLookup.java
@@ -0,0 +1,363 @@
+package NET.worlds.scape;
+
+import NET.worlds.core.Hashtable;
+import NET.worlds.network.URL;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.NoSuchElementException;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+public class CDDBLookup implements Runnable {
+ public static final int STATUS_SERVERERROR = -3;
+ public static final int STATUS_NOTUNIQUE = -2;
+ public static final int STATUS_NOTFOUND = -1;
+ public static final int STATUS_LOOKING = 0;
+ public static final int STATUS_EXACTMATCH = 1;
+ public static final int STATUS_CLOSEMATCH = 2;
+ private static final boolean debug = false;
+ private static final String lookupThreadName = "lookup";
+ private static final String siteThreadName = "site";
+ private static final String pkgName = "gamma";
+ private static final String pkgVersion = "1.0";
+ private static final int TIMEOUT = 3000;
+ private static final String dbName = "home:cdcache.db";
+ private static CDDBHost siteHost = new CDDBHost("cddb.cddb.com", 888);
+ private static Vector sites;
+ private static Object siteMutex = new Object();
+ private static Object knownDisksMutex = new Object();
+ private static int lastHostUsed = -1;
+ private static Hashtable threadActivity = new Hashtable();
+ private static Hashtable knownDisks;
+ private static String userName;
+ private static String hostName;
+ private CDTrackInfo tracks;
+ private String hash;
+ private CDDBStatus status;
+ private static final String discTitleKey = "DTITLE=";
+ private static final String trackTitleKey = "TTITLE";
+
+ public CDDBLookup(CDTrackInfo tracks) {
+ if (userName == null) {
+ userName = System.getProperty("user.name").replace(' ', '_');
+
+ try {
+ hostName = InetAddress.getLocalHost().getHostName();
+ } catch (UnknownHostException var3) {
+ hostName = "unknown";
+ }
+ }
+
+ this.tracks = tracks;
+ this.hash = CDDBHash.hashString(tracks);
+ if ((this.status = this.dbLookup()) == null) {
+ this.runThread("lookup");
+ }
+ }
+
+ public String getHash() {
+ return this.hash;
+ }
+
+ public CDDiskInfo getDiskInfo() {
+ return this.getDiskInfo(false);
+ }
+
+ public synchronized CDDiskInfo getDiskInfo(boolean wait) {
+ if (wait) {
+ while (this.status == null) {
+ try {
+ this.wait();
+ } catch (InterruptedException var3) {
+ }
+ }
+ }
+
+ return this.status != null ? this.status.getDiskInfo() : null;
+ }
+
+ public int getStatus() {
+ return this.status != null ? this.status.getStatus() : 0;
+ }
+
+ @Override
+ public void run() {
+ String name = Thread.currentThread().getName();
+ if (name.equals("lookup")) {
+ this.maybeRunSiteThread();
+
+ for (int i = 0; i < sites.size(); i++) {
+ synchronized (this) {
+ Thread t = this.runThread("" + i);
+
+ try {
+ do {
+ this.wait(3000L);
+ } while (this.status == null && this.recentlyActive(t));
+ } catch (InterruptedException var13) {
+ }
+
+ this.forgetThread(t);
+ if (this.status != null) {
+ break;
+ }
+
+ if (i == sites.size() - 1) {
+ this.status = new CDDBStatus(-3);
+ this.notifyAll();
+ }
+ }
+ }
+ } else if (name.equals("site")) {
+ Vector v = getSiteList();
+ synchronized (siteMutex) {
+ if (sites == null) {
+ sites = v;
+ }
+
+ siteMutex.notifyAll();
+ }
+ } else {
+ CDDBStatus newStatus = null;
+ int hostIndex = 0;
+
+ try {
+ hostIndex = Integer.parseInt(name);
+ } catch (NumberFormatException var11) {
+ }
+
+ CDDBHost host = null;
+ synchronized (siteMutex) {
+ host = (CDDBHost)sites.elementAt(hostIndex);
+ }
+
+ newStatus = this.findDiskInfo(host);
+ synchronized (this) {
+ if (this.status == null && newStatus != null) {
+ this.status = newStatus;
+ if (hostIndex != 0) {
+ synchronized (siteMutex) {
+ Object site = sites.elementAt(hostIndex);
+ sites.removeElementAt(hostIndex);
+ sites.insertElementAt(site, 0);
+ }
+ }
+
+ this.notifyAll();
+ }
+ }
+ }
+ }
+
+ private static void addSite(Vector v, String host, int port) {
+ v.addElement(new CDDBHost(host, port));
+ }
+
+ private static void defaultSites() {
+ sites = new Vector();
+ addSite(sites, "cddb.moonsoft.com", 888);
+ addSite(sites, "cddb.moonsoft.com", 8880);
+ addSite(sites, "cddb.celestial.com", 888);
+ addSite(sites, "cddb.sonic.net", 888);
+ addSite(sites, "sunsite.unc.edu", 888);
+ addSite(sites, "cddb.netads.com", 888);
+ addSite(sites, "cddb.mattdm.org", 888);
+ addSite(sites, "cddb.dartmouth.edu", 888);
+ }
+
+ private static Vector getSiteList() {
+ CDDBConnection con = null;
+
+ try {
+ con = new CDDBConnection(siteHost, false);
+ con.command("sites").startsWith("210 ");
+ Vector v = new Vector();
+
+ String line;
+ while ((line = con.readBody()) != null) {
+ StringTokenizer tok = new StringTokenizer(line, " ");
+ addSite(v, tok.nextToken(), Integer.parseInt(tok.nextToken()));
+ }
+
+ return v;
+ } catch (IOException var10) {
+ } catch (NumberFormatException var11) {
+ } catch (NoSuchElementException var12) {
+ } finally {
+ if (con != null) {
+ con.close();
+ }
+ }
+
+ return null;
+ }
+
+ private CDDBStatus findDiskInfo(CDDBHost host) {
+ CDDBConnection con = null;
+
+ CDDBStatus var9;
+ try {
+ con = new CDDBConnection(host, false);
+ if (!con.command("cddb hello " + userName + " " + hostName + " " + "gamma" + " " + "1.0").startsWith("200 ")) {
+ return null;
+ }
+
+ String resp = con.command("cddb query " + CDDBHash.lookupString(this.tracks));
+ StringTokenizer t = new StringTokenizer(resp, " ");
+ String code = t.nextToken();
+ if (code.equals("200")) {
+ return this.dbAdd(new CDDBStatus(1, this.getCDDBEntry(con, t)));
+ }
+
+ if (code.equals("211")) {
+ String line = con.readBody();
+ int extra = 0;
+
+ while (con.readBody() != null) {
+ extra++;
+ }
+
+ if (extra != 0) {
+ return this.dbAdd(new CDDBStatus(-2));
+ }
+
+ return this.dbAdd(new CDDBStatus(2, this.getCDDBEntry(con, new StringTokenizer(line, " "))));
+ }
+
+ if (!code.equals("202")) {
+ return null;
+ }
+
+ var9 = new CDDBStatus(-1);
+ } catch (IOException var13) {
+ return null;
+ } catch (NoSuchElementException var14) {
+ return null;
+ } finally {
+ if (con != null) {
+ con.close();
+ }
+ }
+
+ return var9;
+ }
+
+ private Thread runThread(String name) {
+ Thread t = new Thread(this, name);
+ t.setDaemon(true);
+ t.start();
+ return t;
+ }
+
+ private void maybeRunSiteThread() {
+ synchronized (siteMutex) {
+ if (sites == null) {
+ Thread t = this.runThread("site");
+
+ try {
+ do {
+ siteMutex.wait(3000L);
+ } while (sites == null && this.recentlyActive(t));
+ } catch (InterruptedException var4) {
+ }
+
+ this.forgetThread(t);
+ if (sites == null) {
+ defaultSites();
+ }
+ }
+ }
+ }
+
+ private CDDiskInfo getCDDBEntry(CDDBConnection con, StringTokenizer t) {
+ try {
+ String cat = t.nextToken();
+ String id = t.nextToken();
+ if (con.command("cddb read " + cat + " " + id).startsWith("210 ")) {
+ return this.parseCDDBEntry(cat, con);
+ }
+ } catch (IOException var5) {
+ } catch (NoSuchElementException var6) {
+ }
+
+ return null;
+ }
+
+ private CDDiskInfo parseCDDBEntry(String category, CDDBConnection con) throws IOException {
+ String artist = null;
+ String title = null;
+ String[] trackNames = new String[this.tracks.getNumTracks()];
+
+ for (int i = 0; i < trackNames.length; i++) {
+ trackNames[i] = "";
+ }
+
+ String line;
+ while ((line = con.readBody()) != null) {
+ if (line.startsWith("DTITLE=")) {
+ line = line.substring("DTITLE=".length());
+ int slashPos = line.indexOf(47);
+ if (slashPos == -1) {
+ artist = title = line.trim();
+ } else {
+ artist = line.substring(0, slashPos).trim();
+ title = line.substring(slashPos + 1).trim();
+ }
+ } else if (line.startsWith("TTITLE")) {
+ int eqIndex = line.indexOf(61);
+
+ try {
+ int trackNum = Integer.parseInt(line.substring("TTITLE".length(), eqIndex));
+ trackNames[trackNum] = trackNames[trackNum] + line.substring(eqIndex + 1);
+ } catch (NumberFormatException var9) {
+ } catch (IndexOutOfBoundsException var10) {
+ }
+ }
+ }
+
+ return new CDDiskInfo(artist, title, category, trackNames);
+ }
+
+ static void markActivity() {
+ threadActivity.put(Thread.currentThread(), new Long(System.currentTimeMillis()));
+ }
+
+ private boolean recentlyActive(Thread t) {
+ Long l = (Long)threadActivity.get(t);
+ return l != null ? System.currentTimeMillis() - l < 3000L : false;
+ }
+
+ private void forgetThread(Thread t) {
+ threadActivity.remove(t);
+ }
+
+ private CDDBStatus dbAdd(CDDBStatus status) {
+ synchronized (knownDisksMutex) {
+ if (knownDisks.get(this.hash) == null) {
+ knownDisks.put(this.hash, status);
+
+ try {
+ new Saver(new URL("home:cdcache.db")).save(knownDisks);
+ } catch (Exception var4) {
+ }
+ }
+
+ return status;
+ }
+ }
+
+ private CDDBStatus dbLookup() {
+ synchronized (knownDisksMutex) {
+ if (knownDisks == null) {
+ try {
+ knownDisks = (Hashtable)new Restorer(new URL("home:cdcache.db")).restore();
+ } catch (Exception var3) {
+ knownDisks = new Hashtable();
+ }
+ }
+
+ return (CDDBStatus)knownDisks.get(this.hash);
+ }
+ }
+}
diff --git a/NET/worlds/scape/CDDBStatus.java b/NET/worlds/scape/CDDBStatus.java
new file mode 100644
index 0000000..bcf8922
--- /dev/null
+++ b/NET/worlds/scape/CDDBStatus.java
@@ -0,0 +1,52 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+public class CDDBStatus implements Persister {
+ private int status;
+ private CDDiskInfo diskInfo;
+ private static Object classCookie = new Object();
+
+ public CDDBStatus(int status, CDDiskInfo diskInfo) {
+ this.status = status;
+ this.diskInfo = diskInfo;
+ }
+
+ public CDDBStatus(int status) {
+ this.status = status;
+ }
+
+ public CDDBStatus() {
+ }
+
+ public int getStatus() {
+ return this.status;
+ }
+
+ public CDDiskInfo getDiskInfo() {
+ return this.diskInfo;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(1, classCookie);
+ s.saveInt(this.status);
+ s.saveMaybeNull(this.diskInfo);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 1:
+ this.status = r.restoreInt();
+ this.diskInfo = (CDDiskInfo)r.restoreMaybeNull();
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+
+ @Override
+ public void postRestore(int version) {
+ }
+}
diff --git a/NET/worlds/scape/CDDiskInfo.java b/NET/worlds/scape/CDDiskInfo.java
new file mode 100644
index 0000000..ebfb220
--- /dev/null
+++ b/NET/worlds/scape/CDDiskInfo.java
@@ -0,0 +1,94 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+public class CDDiskInfo implements Persister {
+ private String artist;
+ private String title;
+ private String category;
+ private String[] trackNames;
+ private static Object classCookie = new Object();
+
+ public CDDiskInfo(String artist, String title, String category, String[] trackNames) {
+ this.artist = artist;
+ this.title = title;
+ this.category = category;
+ this.trackNames = new String[trackNames.length];
+ System.arraycopy(trackNames, 0, this.trackNames, 0, trackNames.length);
+ }
+
+ public CDDiskInfo() {
+ }
+
+ public String getArtist() {
+ return this.artist;
+ }
+
+ public String getTitle() {
+ return this.title;
+ }
+
+ public String getCategory() {
+ return this.category;
+ }
+
+ public int getNumTracks() {
+ return this.trackNames.length;
+ }
+
+ public String getTrackName(int track) {
+ return this.trackNames[track];
+ }
+
+ @Override
+ public String toString() {
+ String ret = "Artist: " + this.artist + "\n" + "Title: " + this.title + "\n" + "Category: " + this.category + "\n";
+
+ for (int i = 0; i < this.trackNames.length; i++) {
+ ret = ret + "Track " + (i + 1) + ":";
+ if (this.trackNames[i] != null) {
+ ret = ret + this.trackNames[i];
+ }
+
+ ret = ret + "\n";
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(1, classCookie);
+ s.saveString(this.artist);
+ s.saveString(this.title);
+ s.saveString(this.category);
+ s.saveInt(this.trackNames.length);
+
+ for (int i = 0; i < this.trackNames.length; i++) {
+ s.saveString(this.trackNames[i]);
+ }
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 1:
+ this.artist = r.restoreString();
+ this.title = r.restoreString();
+ this.category = r.restoreString();
+ this.trackNames = new String[r.restoreInt()];
+
+ for (int i = 0; i < this.trackNames.length; i++) {
+ this.trackNames[i] = r.restoreString();
+ }
+
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+
+ @Override
+ public void postRestore(int version) {
+ }
+}
diff --git a/NET/worlds/scape/CDPlayerAction.java b/NET/worlds/scape/CDPlayerAction.java
new file mode 100644
index 0000000..0d1955a
--- /dev/null
+++ b/NET/worlds/scape/CDPlayerAction.java
@@ -0,0 +1,258 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Main;
+import NET.worlds.console.MainCallback;
+import NET.worlds.console.MainTerminalCallback;
+import java.io.IOException;
+
+public class CDPlayerAction extends Action implements Runnable, MainCallback, MainTerminalCallback {
+ private static final boolean DISABLE_ALL = true;
+ private static final int STATE_INITIAL = 0;
+ private static final int STATE_WAITING = 1;
+ private static final int STATE_DONE = 2;
+ private static int numDrives = -1;
+ private static CDPlayerAction active;
+ private String artist;
+ private String title;
+ private String hash;
+ private int start;
+ private int stop;
+ private boolean isStopper;
+ private boolean cancel;
+ private int state = 0;
+ private static Object classCookie = new Object();
+
+ private boolean same(String str1, String str2) {
+ if (str1 == null) {
+ return str2 == null;
+ } else {
+ return str2 == null ? false : str1.equals(str2);
+ }
+ }
+
+ private boolean same(CDPlayerAction other) {
+ return other != null
+ && this.same(this.artist, other.artist)
+ && this.same(this.title, other.title)
+ && this.same(this.hash, other.hash)
+ && this.start == other.start
+ && this.stop == other.stop;
+ }
+
+ @Override
+ public Persister trigger(Event e, Persister seqID) {
+ return null;
+ }
+
+ @Override
+ public void run() {
+ if (numDrives == -1) {
+ numDrives = getNumDrives();
+ }
+
+ for (int i = 0; i < numDrives; i++) {
+ try {
+ CDTrackInfo trackInfo = getTrackList(i);
+ String curHash = null;
+ if (trackInfo != null) {
+ curHash = CDDBHash.hashString(trackInfo);
+ if (curHash.equals(this.hash)) {
+ this.play(i);
+ break;
+ }
+ }
+
+ if (this.cancel) {
+ break;
+ }
+ } catch (IOException var4) {
+ }
+ }
+
+ this.state = 2;
+ }
+
+ @Override
+ public void mainCallback() {
+ }
+
+ @Override
+ public void terminalCallback() {
+ this.cancel = true;
+ if (this.state == 2) {
+ Main.unregister(this);
+ }
+ }
+
+ private void play(int drive) throws IOException {
+ int driveID;
+ if ((driveID = openDrive(drive)) != 0) {
+ playAudio(driveID, this.start, this.stop);
+
+ while (isPlaying(driveID)) {
+ try {
+ Thread.sleep(1000L);
+ } catch (InterruptedException var4) {
+ }
+
+ if (this.cancel) {
+ stopAudio(driveID);
+ break;
+ }
+ }
+
+ closeDrive(driveID);
+ }
+ }
+
+ public static CDTrackInfo getTrackList(int drive) throws IOException {
+ CDTrackInfo ret = null;
+ int driveID;
+ if ((driveID = openDrive(drive)) != 0) {
+ ret = getDriveTrackList(driveID);
+ closeDrive(driveID);
+ }
+
+ return ret;
+ }
+
+ public static native int getNumDrives();
+
+ public static native int getDriveLetterOffset(int var0);
+
+ public static native int openDrive(int var0) throws IOException;
+
+ public static native void closeDrive(int var0) throws IOException;
+
+ public static native void checkDrive(int var0) throws IOException;
+
+ public static native CDTrackInfo getDriveTrackList(int var0) throws IOException;
+
+ public static native void playAudio(int var0, int var1, int var2) throws IOException;
+
+ public static native void stopAudio(int var0) throws IOException;
+
+ public static native void pauseAudio(int var0) throws IOException;
+
+ public static native void resumeAudio(int var0) throws IOException;
+
+ public static native boolean isPlaying(int var0) throws IOException;
+
+ public static native int getPosition(int var0) throws IOException;
+
+ public static native void setNTAutoPlayCode(int var0);
+
+ public static native boolean launchVolumeControlApp();
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Artist"));
+ } else if (mode == 1) {
+ ret = this.artist;
+ } else if (mode == 2) {
+ this.artist = (String)value;
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Title"));
+ } else if (mode == 1) {
+ ret = this.title;
+ } else if (mode == 2) {
+ this.title = (String)value;
+ }
+ break;
+ case 2:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Disk ID (Edit or Delete to read CD)").allowSetNull());
+ } else if (mode == 1) {
+ if (this.hash == null) {
+ try {
+ CDTrackInfo trackList = getTrackList(0);
+ if (trackList != null) {
+ this.hash = CDDBHash.hashString(trackList);
+ }
+ } catch (IOException var7) {
+ }
+ }
+
+ ret = this.hash;
+ } else if (mode == 2) {
+ this.hash = (String)value;
+ }
+ break;
+ case 3:
+ if (mode == 0) {
+ ret = CDPositionPropertyEditor.make(new Property(this, index, "Start (75ths of a second)"), false);
+ } else if (mode == 1) {
+ ret = new Integer(this.start);
+ } else if (mode == 2) {
+ this.start = (Integer)value;
+ }
+ break;
+ case 4:
+ if (mode == 0) {
+ ret = CDPositionPropertyEditor.make(new Property(this, index, "Stop (75ths of a second)"), true);
+ } else if (mode == 1) {
+ ret = new Integer(this.stop);
+ } else if (mode == 2) {
+ this.stop = (Integer)value;
+ }
+ break;
+ case 5:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Stop identical CDPlayerAction"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(this.isStopper);
+ } else if (mode == 2) {
+ this.isStopper = (Boolean)value;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 6, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(2, classCookie);
+ super.saveState(s);
+ s.saveString(this.artist);
+ s.saveString(this.title);
+ s.saveString(this.hash);
+ s.saveInt(this.start);
+ s.saveInt(this.stop);
+ s.saveBoolean(this.isStopper);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 1:
+ super.restoreState(r);
+ this.artist = r.restoreString();
+ this.title = r.restoreString();
+ this.hash = r.restoreString();
+ this.start = r.restoreInt();
+ this.stop = r.restoreInt();
+ break;
+ case 2:
+ super.restoreState(r);
+ this.artist = r.restoreString();
+ this.title = r.restoreString();
+ this.hash = r.restoreString();
+ this.start = r.restoreInt();
+ this.stop = r.restoreInt();
+ this.isStopper = r.restoreBoolean();
+ break;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/CDPositionEditorDialog.java b/NET/worlds/scape/CDPositionEditorDialog.java
new file mode 100644
index 0000000..1762758
--- /dev/null
+++ b/NET/worlds/scape/CDPositionEditorDialog.java
@@ -0,0 +1,33 @@
+package NET.worlds.scape;
+
+import java.util.Vector;
+
+class CDPositionEditorDialog extends FieldWithListEditorDialog {
+ Property property;
+
+ CDPositionEditorDialog(EditTile parent, String title, Property property, Vector trackList) {
+ super(parent, title, trackList);
+ this.property = property;
+ this.ready();
+ }
+
+ @Override
+ protected String getValue() {
+ return "" + this.property.get();
+ }
+
+ @Override
+ protected boolean setValue(String text) {
+ int index = text.indexOf("#");
+ if (index != -1) {
+ text = text.substring(0, index).trim();
+ }
+
+ try {
+ this.parent.addUndoableSet(this.property, new Integer(text));
+ return true;
+ } catch (NumberFormatException var4) {
+ return false;
+ }
+ }
+}
diff --git a/NET/worlds/scape/CDPositionPropertyEditor.java b/NET/worlds/scape/CDPositionPropertyEditor.java
new file mode 100644
index 0000000..1fe5453
--- /dev/null
+++ b/NET/worlds/scape/CDPositionPropertyEditor.java
@@ -0,0 +1,42 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.PolledDialog;
+import java.io.IOException;
+import java.text.MessageFormat;
+import java.util.Vector;
+
+public class CDPositionPropertyEditor extends PropEditor {
+ private boolean ending;
+
+ private CDPositionPropertyEditor(Property property, boolean ending) {
+ super(property);
+ this.ending = ending;
+ }
+
+ @Override
+ public PolledDialog edit(EditTile parent, String title) {
+ CDTrackInfo trackInfo = null;
+
+ try {
+ trackInfo = CDPlayerAction.getTrackList(0);
+ } catch (IOException var9) {
+ }
+
+ Vector trackList = new Vector();
+ if (trackInfo != null) {
+ for (int i = 0; i < trackInfo.getNumTracks(); i++) {
+ int frames = this.ending ? trackInfo.getEndFrames(i) : trackInfo.getStartFrames(i);
+ String type = this.ending ? Console.message("End") : Console.message("Start");
+ Object[] arguments = new Object[]{new String("" + frames), new String(type), new String("" + (i + 1))};
+ trackList.addElement(MessageFormat.format(Console.message("of-track"), arguments));
+ }
+ }
+
+ return new CDPositionEditorDialog(parent, title, this.property, trackList);
+ }
+
+ public static Property make(Property property, boolean ending) {
+ return property.setEditor(new CDPositionPropertyEditor(property, ending));
+ }
+}
diff --git a/NET/worlds/scape/CDTrackInfo.java b/NET/worlds/scape/CDTrackInfo.java
new file mode 100644
index 0000000..e3c35d9
--- /dev/null
+++ b/NET/worlds/scape/CDTrackInfo.java
@@ -0,0 +1,82 @@
+package NET.worlds.scape;
+
+public class CDTrackInfo {
+ private int[] pos;
+ private int[] len;
+
+ public CDTrackInfo(int numTracks) {
+ this.pos = new int[numTracks];
+ this.len = new int[numTracks];
+ }
+
+ public int getNumTracks() {
+ return this.pos.length;
+ }
+
+ public int getStartFrames(int track) {
+ return this.getPosM(track) * 60 * 75 + this.getPosS(track) * 75 + this.getPosF(track);
+ }
+
+ public int getEndFrames(int track) {
+ return track == this.pos.length - 1
+ ? this.getStartFrames(track) + this.getLenM(track) * 60 * 75 + this.getLenS(track) * 75 + this.getLenF(track)
+ : this.getStartFrames(track + 1) - 1;
+ }
+
+ public int getPosM(int track) {
+ return minutes(this.pos[track]);
+ }
+
+ public int getPosS(int track) {
+ return seconds(this.pos[track]);
+ }
+
+ public int getPosF(int track) {
+ return frames(this.pos[track]);
+ }
+
+ public int getLenM(int track) {
+ return minutes(this.len[track]);
+ }
+
+ public int getLenS(int track) {
+ return seconds(this.len[track]);
+ }
+
+ public int getLenF(int track) {
+ return frames(this.len[track]);
+ }
+
+ private static int minutes(int packed) {
+ return packed & 0xFF;
+ }
+
+ private static int seconds(int packed) {
+ return packed >> 8 & 0xFF;
+ }
+
+ private static int frames(int packed) {
+ return packed >> 16 & 0xFF;
+ }
+
+ private static String format2(int val) {
+ String result = "";
+ if (val < 10) {
+ result = "0";
+ }
+
+ return result + val;
+ }
+
+ private static String format(int packed) {
+ return minutes(packed) + ":" + format2(seconds(packed)) + ":" + format2(frames(packed));
+ }
+
+ public void dump() {
+ System.out.println("Tracks: " + this.pos.length);
+
+ for (int i = 0; i < this.pos.length; i++) {
+ System.out.println("Track " + i + " " + "start " + format(this.pos[i]) + " length " + format(this.len[i]));
+ }
+ }
+}
diff --git a/NET/worlds/scape/CallbackPropertyOperator.java b/NET/worlds/scape/CallbackPropertyOperator.java
new file mode 100644
index 0000000..55c2418
--- /dev/null
+++ b/NET/worlds/scape/CallbackPropertyOperator.java
@@ -0,0 +1,44 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Main;
+import NET.worlds.console.MainCallback;
+
+public class CallbackPropertyOperator implements MainCallback {
+ private Property prop;
+ private int func;
+ private Object value;
+ private boolean done;
+
+ CallbackPropertyOperator(Property prop, int func, Object value) {
+ this.prop = prop;
+ this.func = func;
+ this.value = value;
+
+ assert !Main.isMainThread();
+
+ Main.register(this);
+ }
+
+ synchronized Object getValue() {
+ while (!this.done) {
+ try {
+ this.wait();
+ } catch (InterruptedException var2) {
+ }
+ }
+
+ return this.value;
+ }
+
+ @Override
+ public synchronized void mainCallback() {
+ this.modify();
+ Main.unregister(this);
+ this.notify();
+ }
+
+ private void modify() {
+ this.value = this.prop.safeOperate(this.func, this.value);
+ this.done = true;
+ }
+}
diff --git a/NET/worlds/scape/Camera.java b/NET/worlds/scape/Camera.java
new file mode 100644
index 0000000..61addea
--- /dev/null
+++ b/NET/worlds/scape/Camera.java
@@ -0,0 +1,357 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.Gamma;
+import NET.worlds.console.RenderCanvas;
+import NET.worlds.console.Window;
+import NET.worlds.network.URL;
+import java.io.IOException;
+
+public class Camera extends WObject implements MouseButtonHandler, MouseEnterHandler, MouseExitHandler, MouseMoveHandler, IncrementalRestorer, URLSelf {
+ private RenderCanvas canvas;
+ static final int CAMERA_SIZE = 20;
+ private boolean mouseIsOverClickable = false;
+ private boolean validMouseCoordinates = false;
+ private float validMouseX = -1.0F;
+ private float validMouseY = -1.0F;
+ private static WObject cachedWObject = null;
+ private static float cachedMouseX = -1.0F;
+ private static float cachedMouseY = -1.0F;
+ private int cameraID;
+ private int cameraMode;
+ private boolean alwaysClearBackground;
+ private float xPick;
+ private float yPick;
+ private Point3Temp unpickSpot;
+ private WObject pickedObj;
+ public Transform lookAround = Transform.make();
+ private static final int isBotMode = 0;
+ private static final int isPickingMode = 1;
+ private static final int isDrawingMode = 2;
+ private static final int isThroughMode = 4;
+ static WObject[] downWentTo = new WObject[3];
+ static Point3 downAt = new Point3();
+ private static Object classCookie = new Object();
+ public float xForRoomPreAndPostRender;
+ public float yForRoomPreAndPostRender;
+ public float zForRoomPreAndPostRender;
+ public float dForRoomPreAndPostRender;
+
+ static {
+ cameraNativeInit();
+ }
+
+ public Camera() {
+ this.setVisible(false);
+ }
+
+ public static native void cameraNativeInit();
+
+ public Window getWindow() {
+ return this.canvas == null ? null : this.canvas.getWindow();
+ }
+
+ @Override
+ public BoundBoxTemp getBoundBox() {
+ Transform t = this.getObjectToWorldMatrix();
+ Point3Temp p = t.getPosition();
+ t.recycle();
+ Point3Temp q = Point3Temp.make(p).minus(20.0F);
+ return BoundBoxTemp.make(q, p.plus(20.0F));
+ }
+
+ public static WObject getMousePickWObject() {
+ return cachedWObject;
+ }
+
+ public static float getMousePickX() {
+ return cachedMouseX;
+ }
+
+ public static float getMousePickY() {
+ return cachedMouseY;
+ }
+
+ protected WObject updateView(Window w, int mode) {
+ Room r = this.getRoom();
+ if (!this.hasClump() && r != null) {
+ r.aboutToDraw();
+ }
+
+ Transform t = null;
+ SuperRoot o = this.getOwner();
+ Pilot pilot = null;
+ if (o instanceof Pilot && o.getOwner() == r) {
+ pilot = (Pilot)o;
+ if (r != null) {
+ pilot.aboutToDraw();
+ this.detach();
+ r.add(this);
+ t = this.getTransform();
+ Point3Temp motion = t.getPosition().times(pilot).minus(pilot.getPosition());
+ this.post(pilot);
+ if (motion.squaredLength() > 1.0F) {
+ this.moveBy(Point3Temp.make().minus(motion));
+ boolean pBumpable = pilot.getBumpable();
+ pilot.setBumpable(false);
+ this.moveThrough(motion);
+ pilot.setBumpable(pBumpable);
+ Room r2 = this.getRoom();
+ if (!this.hasClump() && r2 != null && r2 != r) {
+ r2.aboutToDraw();
+ }
+ }
+ }
+ }
+
+ WObject result = this.renderScene(w.getHwnd(), w.fullWidth(), w.fullHeight(), mode, pilot);
+ if (t != null) {
+ this.detach();
+ pilot.add(this);
+ this.setTransform(t);
+ t.recycle();
+ }
+
+ return result;
+ }
+
+ public void renderToCanvas() {
+ assert this.cameraID == 0;
+
+ if (this.isActive()) {
+ Window w = this.getWindow();
+ if (w != null) {
+ if (this.validMouseCoordinates) {
+ this.xPick = this.validMouseX;
+ this.yPick = this.validMouseY;
+ WObject obj = this.updateView(w, 7);
+ boolean toggleMouseCursor = false;
+ cachedWObject = obj;
+ cachedMouseX = this.validMouseX;
+ cachedMouseY = this.validMouseY;
+ if (obj != null && obj.acceptsLeftClicks()) {
+ if (!this.mouseIsOverClickable) {
+ this.mouseIsOverClickable = true;
+ toggleMouseCursor = true;
+ }
+ } else if (this.mouseIsOverClickable) {
+ this.mouseIsOverClickable = false;
+ toggleMouseCursor = true;
+ }
+
+ if (toggleMouseCursor) {
+ URL newURL = null;
+ if (this.mouseIsOverClickable) {
+ newURL = URL.make("home:HAND-M.CUR");
+ } else {
+ newURL = URL.make("system:DEFAULT_CURSOR");
+ }
+
+ Console.getActive().getCursor().setURL(newURL);
+ }
+ } else {
+ this.updateView(w, 6);
+ }
+ }
+ }
+ }
+
+ public native void nDrawText(String var1, int var2, int var3, int var4, int var5);
+
+ public RenderCanvas getCanvas() {
+ return this.canvas;
+ }
+
+ public void setCanvas(RenderCanvas c) {
+ this.canvas = c;
+ }
+
+ public void setAlwaysClearBackground(boolean in) {
+ this.alwaysClearBackground = in;
+ }
+
+ public Point3Temp lastPickSpot() {
+ return this.unpickSpot;
+ }
+
+ public void transferFrom(Camera target) {
+ this.lookAround.setTransform(target.lookAround);
+ }
+
+ synchronized native WObject renderScene(int var1, int var2, int var3, int var4, Pilot var5);
+
+ public WObject getObjectAt(float x, float y, boolean pickingThrough, Point3Temp pt) {
+ Window w = this.getWindow();
+ if (w == null) {
+ return null;
+ } else {
+ this.xPick = x;
+ this.yPick = y;
+ this.unpickSpot = null;
+ WObject obj = this.updateView(w, 1 + (pickingThrough ? 4 : 0));
+ if (pt != null && this.unpickSpot != null) {
+ pt.copy(this.unpickSpot);
+ }
+
+ return obj;
+ }
+ }
+
+ private void sendClick(WObject obj, MouseButtonEvent e) {
+ WObject oldTarget = e.target;
+ e.target = obj;
+ obj.deliver(e);
+ e.target = oldTarget;
+ }
+
+ @Override
+ public boolean handle(MouseButtonEvent e) {
+ WObject obj = null;
+ int which = 3;
+ if (e.key == '\ue301') {
+ which = 0;
+ } else if (e.key == '\ue302') {
+ which = 1;
+ } else if (e.key == '\ue304') {
+ which = 2;
+ }
+
+ assert which != 3;
+
+ if (e instanceof MouseUpEvent) {
+ obj = downWentTo[which];
+ downWentTo[which] = null;
+ } else {
+ Window w = this.getWindow();
+ if (w != null && !w.getDeltaMode()) {
+ if (which == 1 && Gamma.getShaper() != null) {
+ obj = this.getObjectAt(e.x, e.y, false, null);
+ if (obj != null) {
+ obj.rightMenu();
+ }
+ } else {
+ obj = this.getObjectAt(e.x, e.y, true, downAt);
+ }
+
+ downWentTo[which] = obj;
+ }
+ }
+
+ if (obj != null) {
+ if (which == 0 && e instanceof MouseUpEvent) {
+ obj.doAction(Console.getActive().getDefaultAction(), e);
+ }
+
+ this.sendClick(obj, e);
+ }
+
+ return false;
+ }
+
+ @Override
+ public boolean handle(MouseEnterEvent e) {
+ if (e != null) {
+ URL defaultCursor = URL.make("system:DEFAULT_CURSOR");
+ Console.getActive().getCursor().setURL(defaultCursor);
+ this.mouseIsOverClickable = false;
+ this.validMouseCoordinates = true;
+ this.validMouseX = e.x;
+ this.validMouseY = e.y;
+ cachedWObject = null;
+ cachedMouseX = -1.0F;
+ cachedMouseY = -1.0F;
+ }
+
+ return false;
+ }
+
+ @Override
+ public boolean handle(MouseExitEvent e) {
+ if (e != null) {
+ URL defaultCursor = URL.make("system:DEFAULT_CURSOR");
+ Console.getActive().getCursor().setURL(defaultCursor);
+ this.mouseIsOverClickable = false;
+ this.validMouseCoordinates = false;
+ this.validMouseX = -1.0F;
+ this.validMouseY = -1.0F;
+ cachedWObject = null;
+ cachedMouseX = -1.0F;
+ cachedMouseY = -1.0F;
+ }
+
+ return false;
+ }
+
+ @Override
+ public boolean handle(MouseMoveEvent e) {
+ if (e != null) {
+ this.validMouseX = e.x;
+ this.validMouseY = e.y;
+ }
+
+ return false;
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ int var10000 = index - offset;
+ return super.properties(index, offset + 0, mode, value);
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(2, classCookie);
+ super.saveState(s);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ case 2:
+ super.restoreState(r);
+ break;
+ case 1:
+ super.restoreState(r);
+ r.restoreFloat();
+ r.restore();
+ r.restore();
+ break;
+ default:
+ throw new TooNewException();
+ }
+ }
+
+ @Override
+ public int incRestore(int state, Restorer r, URLSelfLoader p) throws Exception {
+ if (state == 0) {
+ this.restoreState(r);
+ }
+
+ if (r.version() != 3) {
+ return -1;
+ } else {
+ if (state == 0) {
+ p.otemp1 = r.restore(false);
+ }
+
+ World w = (World)p.otemp1;
+ if (state == 0) {
+ w.setSourceURL(this.getSourceURL());
+ }
+
+ return w.incRestore(state, r, p);
+ }
+ }
+
+ @Override
+ public void incRef() {
+ assert false;
+ }
+
+ @Override
+ public void decRef() {
+ assert false;
+ }
+}
diff --git a/NET/worlds/scape/CameraHeightAction.java b/NET/worlds/scape/CameraHeightAction.java
new file mode 100644
index 0000000..46c40db
--- /dev/null
+++ b/NET/worlds/scape/CameraHeightAction.java
@@ -0,0 +1,75 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+public class CameraHeightAction extends Action {
+ public float newEyeHeight = 0.0F;
+ private static Object classCookie = new Object();
+
+ @Override
+ public Persister trigger(Event e, Persister seqID) {
+ Object owner = this.getOwner();
+ if (owner != null && owner instanceof WObject) {
+ WObject o = (WObject)owner;
+ Pilot pilot = Pilot.getActive();
+ if (pilot == null) {
+ return null;
+ } else if (pilot.getRoom() != o.getRoom()) {
+ return null;
+ } else {
+ if (pilot instanceof HoloPilot) {
+ HoloPilot hp = (HoloPilot)pilot;
+ hp.setEyeHeight(this.newEyeHeight);
+ }
+
+ return null;
+ }
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "New Eye Height"));
+ } else if (mode == 1) {
+ ret = new Float(this.newEyeHeight);
+ } else if (mode == 2) {
+ this.newEyeHeight = (Float)value;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 1, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + "[New Eye Height: " + this.newEyeHeight + "]";
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(0, classCookie);
+ super.saveState(s);
+ s.saveFloat(this.newEyeHeight);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ this.newEyeHeight = r.restoreFloat();
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/ChangeAvatarDialog.java b/NET/worlds/scape/ChangeAvatarDialog.java
new file mode 100644
index 0000000..9843b44
--- /dev/null
+++ b/NET/worlds/scape/ChangeAvatarDialog.java
@@ -0,0 +1,60 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.DialogReceiver;
+import NET.worlds.console.ImageButtons;
+import NET.worlds.console.ImageButtonsCallback;
+import NET.worlds.console.PolledDialog;
+import NET.worlds.core.IniFile;
+import java.awt.Component;
+import java.awt.Rectangle;
+import java.awt.Window;
+import java.text.MessageFormat;
+
+public class ChangeAvatarDialog extends PolledDialog implements ImageButtonsCallback {
+ private ImageButtons ib;
+
+ public ChangeAvatarDialog(Window parent, DialogReceiver receiver, String name) {
+ super(parent, receiver, Console.message("Change-Avatar"), false);
+ this.setAlignment(1);
+ Rectangle[] rects = new Rectangle[2];
+ int yesX = IniFile.override().getIniInt("changeavYesX", 39);
+ int yesY = IniFile.override().getIniInt("changeavYesY", 23);
+ int yesW = IniFile.override().getIniInt("changeavYesW", 48);
+ int yesH = IniFile.override().getIniInt("changeavYesH", 18);
+ rects[0] = new Rectangle(yesX, yesY, yesW, yesH);
+ int noX = IniFile.override().getIniInt("changeavNoX", 96);
+ int noY = IniFile.override().getIniInt("changeavNoY", 23);
+ int noW = IniFile.override().getIniInt("changeavNoW", 42);
+ int noH = IniFile.override().getIniInt("changeavnoH", 18);
+ rects[1] = new Rectangle(noX, noY, noW, noH);
+ Object[] arguments = new Object[]{new String(name)};
+ this.ib = new ChangeAvatarImageButtons(
+ IniFile.override().getIniString("changeAvDlg", Console.message("changeav.gif")),
+ rects,
+ this,
+ MessageFormat.format(Console.message("Change-avatar-to"), arguments)
+ );
+ this.ready();
+ }
+
+ @Override
+ protected void build() {
+ this.add("Center", this.ib);
+ }
+
+ @Override
+ public Object imageButtonsCallback(Component who, int which) {
+ this.done(which == 0);
+ return null;
+ }
+
+ @Override
+ public boolean keyDown(java.awt.Event event, int key) {
+ if (key == 27) {
+ return this.done(false);
+ } else {
+ return key == 10 ? this.done(true) : super.keyDown(event, key);
+ }
+ }
+}
diff --git a/NET/worlds/scape/ChangeAvatarImageButtons.java b/NET/worlds/scape/ChangeAvatarImageButtons.java
new file mode 100644
index 0000000..56bd29e
--- /dev/null
+++ b/NET/worlds/scape/ChangeAvatarImageButtons.java
@@ -0,0 +1,42 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.ImageButtons;
+import NET.worlds.console.ImageButtonsCallback;
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Rectangle;
+
+class ChangeAvatarImageButtons extends ImageButtons {
+ private static final int textBoxX = 0;
+ private static final int textBoxY = 0;
+ private static final int textBoxW = 177;
+ private static final int textBoxH = 23;
+ private static Font font = new Font(Console.message("AvatarFont"), 0, 12);
+ private static int textWidth;
+ private static int textX;
+ private static int textY;
+ private String text;
+
+ public ChangeAvatarImageButtons(String texture, Rectangle[] rects, ImageButtonsCallback cb, String text) {
+ super(texture, rects, cb);
+ this.text = text;
+ }
+
+ @Override
+ public void paint(Graphics g) {
+ super.paint(g);
+ g.setFont(font);
+ g.setColor(Color.white);
+ if (textWidth == 0) {
+ FontMetrics fm = g.getFontMetrics();
+ textWidth = fm.stringWidth(this.text);
+ textX = (177 - textWidth) / 2;
+ textY = 23 - (23 - fm.getAscent()) / 2;
+ }
+
+ g.drawString(this.text, textX, textY);
+ }
+}
diff --git a/NET/worlds/scape/CheckboxEditorDialog.java b/NET/worlds/scape/CheckboxEditorDialog.java
new file mode 100644
index 0000000..e8eb818
--- /dev/null
+++ b/NET/worlds/scape/CheckboxEditorDialog.java
@@ -0,0 +1,64 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.OkCancelDialog;
+import java.awt.Checkbox;
+import java.awt.CheckboxGroup;
+import java.awt.Dimension;
+import java.awt.GridBagConstraints;
+
+public abstract class CheckboxEditorDialog extends OkCancelDialog {
+ private CheckboxGroup group = new CheckboxGroup();
+ private Checkbox[] choices;
+ private String[] labels;
+ protected EditTile parent;
+
+ protected CheckboxEditorDialog(EditTile parent, String title, String[] labels) {
+ super(Console.getFrame(), parent, title);
+ this.labels = labels;
+ this.parent = parent;
+ }
+
+ @Override
+ protected void build() {
+ this.choices = new Checkbox[this.labels.length];
+ GridBagConstraints c = new GridBagConstraints();
+ c.weightx = 1.0;
+ c.weighty = 1.0;
+ c.gridwidth = 0;
+
+ for (int i = 0; i < this.labels.length; i++) {
+ this.add(this.gbag, this.choices[i] = new Checkbox(this.labels[i], this.group, false), c);
+ }
+
+ super.build();
+ }
+
+ protected abstract int getValue();
+
+ protected abstract void setValue(int var1);
+
+ @Override
+ protected boolean setValue() {
+ Checkbox selected = this.group.getCurrent();
+
+ for (int i = 0; i < this.choices.length; i++) {
+ if (this.choices[i] == selected) {
+ this.setValue(i);
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ @Override
+ public void show() {
+ Dimension mySize = this.size();
+ this.initialSize(mySize.width < 160 ? 160 : mySize.width, mySize.height < 120 ? 120 : mySize.height);
+ super.show();
+ int choice = this.getValue();
+ this.choices[choice].requestFocus();
+ this.choices[choice].setState(true);
+ }
+}
diff --git a/NET/worlds/scape/ClassProperty.java b/NET/worlds/scape/ClassProperty.java
new file mode 100644
index 0000000..59229cc
--- /dev/null
+++ b/NET/worlds/scape/ClassProperty.java
@@ -0,0 +1,7 @@
+package NET.worlds.scape;
+
+public class ClassProperty extends Property {
+ public ClassProperty(Properties owner, int index, String className) {
+ super(owner, index, "Class " + className + " (obsolete; for backwards compatibility)");
+ }
+}
diff --git a/NET/worlds/scape/ClickEventHandler.java b/NET/worlds/scape/ClickEventHandler.java
new file mode 100644
index 0000000..01eae57
--- /dev/null
+++ b/NET/worlds/scape/ClickEventHandler.java
@@ -0,0 +1,13 @@
+package NET.worlds.scape;
+
+import java.awt.Component;
+import java.awt.Point;
+
+public interface ClickEventHandler {
+ int DOWN = 1;
+ int UP = 2;
+ int META = 4;
+ int DRAG = 8;
+
+ void clickEvent(Component var1, Point var2, int var3);
+}
diff --git a/NET/worlds/scape/ClickSensor.java b/NET/worlds/scape/ClickSensor.java
new file mode 100644
index 0000000..aab6f0d
--- /dev/null
+++ b/NET/worlds/scape/ClickSensor.java
@@ -0,0 +1,359 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.network.URL;
+import java.io.DataInputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.text.MessageFormat;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+public class ClickSensor extends Sensor implements MouseDownHandler, MouseUpHandler, BGLoaded {
+ private static final int clickTime = 750;
+ public static final int CENTER = 4;
+ public static final int RIGHT = 2;
+ public static final int LEFT = 1;
+ public static final int ANY = 7;
+ protected long mouseDownTime = 0L;
+ protected int keyToCheck = 1;
+ protected boolean waitForUp = false;
+ protected URL config = null;
+ transient int width;
+ transient int height;
+ transient ClickSensor.Area[] configTable;
+ private static Object classCookie = new Object();
+
+ public ClickSensor(Action a, char whichButton) {
+ this(a, (int)whichButton);
+ }
+
+ public ClickSensor(Action a, int whichButton) {
+ this.keyToCheck = whichButton & 7;
+ if (a != null) {
+ this.addAction(a);
+ }
+ }
+
+ public ClickSensor(Action a) {
+ this(a, 7);
+ }
+
+ public ClickSensor() {
+ }
+
+ public int getWhichButton() {
+ return this.keyToCheck;
+ }
+
+ public boolean getWaitForUp() {
+ return this.waitForUp;
+ }
+
+ public void setWhichButton(int which) {
+ assert which >= 0 && which <= 7;
+
+ this.keyToCheck = which;
+ }
+
+ public void setWaitForUp(boolean wait) {
+ this.waitForUp = wait;
+ }
+
+ @Override
+ public boolean handle(MouseDownEvent e) {
+ if (this.keyToCheck == 7 || (e.key & this.keyToCheck) != 0) {
+ if (this.waitForUp) {
+ this.mouseDownTime = System.currentTimeMillis();
+ } else {
+ this.trigger(e);
+ }
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean handle(MouseUpEvent e) {
+ if (this.waitForUp && (this.keyToCheck == 7 || (e.key & this.keyToCheck) != 0) && System.currentTimeMillis() - this.mouseDownTime < 750L) {
+ this.trigger(e);
+ }
+
+ return true;
+ }
+
+ public void triggerAction(String actionNamePrefix, Vector props, Event event) {
+ int len = this.actions.size();
+
+ for (int i = 0; i < len; i++) {
+ Action a = this.actions.elementAt(i);
+ if (a.getName().regionMatches(0, actionNamePrefix, 0, actionNamePrefix.length())) {
+ len = props.size();
+
+ for (int var10 = 0; var10 < len; var10 += 2) {
+ String prop = (String)props.elementAt(var10);
+ String val = (String)props.elementAt(var10 + 1);
+ SetPropertyAction.propHelper(2, val, prop, a);
+ }
+
+ RunningActionHandler.trigger(a, this.getWorld(), event);
+ return;
+ }
+ }
+ }
+
+ @Override
+ public void trigger(Event event) {
+ if (this.configTable != null && this.getOwner() instanceof WObject) {
+ WObject w = (WObject)this.getOwner();
+ Transform t = w.getObjectToWorldMatrix().invert();
+ Point3Temp p = Point3Temp.make(Camera.downAt).times(t);
+ p.x = p.x * this.width;
+ p.z = p.z * this.height;
+
+ for (int i = 0; i < this.configTable.length; i++) {
+ ClickSensor.Area a = this.configTable[i];
+ if (p.x > a.x && p.z > a.y && p.x - a.x < a.w && p.z - a.y < a.h) {
+ this.triggerAction(a.actionNamePrefix, a.props, event);
+ }
+ }
+
+ t.recycle();
+ } else {
+ super.trigger(event);
+ }
+ }
+
+ @Override
+ public Object asyncBackgroundLoad(String localName, URL remoteURL) {
+ return localName;
+ }
+
+ @Override
+ public boolean syncBackgroundLoad(Object obj, URL remoteURL) {
+ if (obj != null) {
+ this.loadConfig((String)obj);
+ }
+
+ return false;
+ }
+
+ @Override
+ public Room getBackgroundLoadRoom() {
+ return null;
+ }
+
+ public static String getString(StringTokenizer st) {
+ String s = st.nextToken();
+ if (s.length() > 0 && s.charAt(0) == '"') {
+ StringBuffer sb = new StringBuffer(s.substring(1));
+
+ while (sb.charAt(sb.length() - 1) != '"') {
+ sb.append(" ");
+ sb.append(st.nextToken());
+ }
+
+ sb.setLength(sb.length() - 1);
+ s = sb.toString();
+ }
+
+ return s;
+ }
+
+ public void loadConfig(String name) {
+ ClickSensor.Area[] result = (ClickSensor.Area[])null;
+ DataInputStream in = null;
+ int line = 1;
+
+ try {
+ in = new DataInputStream(new FileInputStream(name));
+ StringTokenizer st = new StringTokenizer(in.readLine());
+ int numLines = Integer.parseInt(st.nextToken());
+ this.width = Integer.parseInt(st.nextToken());
+ this.height = Integer.parseInt(st.nextToken());
+ result = new ClickSensor.Area[numLines];
+
+ for (int i = 0; i < numLines; i++) {
+ ClickSensor.Area a = new ClickSensor.Area();
+ line++;
+ st = new StringTokenizer(in.readLine());
+ a.x = Integer.parseInt(st.nextToken());
+ a.y = Integer.parseInt(st.nextToken());
+ a.w = Integer.parseInt(st.nextToken());
+ a.h = Integer.parseInt(st.nextToken());
+ a.actionNamePrefix = getString(st);
+ Vector props = new Vector();
+
+ while (st.hasMoreTokens()) {
+ props.addElement(getString(st));
+ props.addElement(getString(st));
+ }
+
+ a.props = props;
+ result[i] = a;
+ }
+
+ this.configTable = result;
+ } catch (Exception var18) {
+ Object[] arguments = new Object[]{new String(name), new String("" + line)};
+ Console.println(MessageFormat.format(Console.message("Error-config-table"), arguments));
+ } finally {
+ try {
+ if (in != null) {
+ in.close();
+ }
+ } catch (IOException var17) {
+ }
+ }
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Left Button"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean((this.keyToCheck & 1) != 0);
+ } else if (mode == 2) {
+ if ((Boolean)value) {
+ this.keyToCheck |= 1;
+ } else {
+ this.keyToCheck &= -2;
+ }
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Right Button"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean((this.keyToCheck & 2) != 0);
+ } else if (mode == 2) {
+ if ((Boolean)value) {
+ this.keyToCheck |= 2;
+ } else {
+ this.keyToCheck &= -3;
+ }
+ }
+ break;
+ case 2:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Center Button"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean((this.keyToCheck & 4) != 0);
+ } else if (mode == 2) {
+ if ((Boolean)value) {
+ this.keyToCheck |= 4;
+ } else {
+ this.keyToCheck &= -5;
+ }
+ }
+ break;
+ case 3:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Wait for up-click"), "Down", "Up");
+ } else if (mode == 1) {
+ ret = new Boolean(this.waitForUp);
+ } else if (mode == 2) {
+ this.waitForUp = (Boolean)value;
+ }
+ break;
+ case 4:
+ if (mode == 0) {
+ ret = URLPropertyEditor.make(new Property(this, index, "Config File").allowSetNull(), "clk");
+ } else if (mode == 1) {
+ ret = this.config;
+ } else if (mode == 2) {
+ this.config = (URL)value;
+ if (this.config != null) {
+ BackgroundLoader.get(this, this.config);
+ } else {
+ this.configTable = null;
+ }
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 5, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(2, classCookie);
+ super.saveState(s);
+ s.saveInt(this.keyToCheck);
+ s.saveBoolean(this.waitForUp);
+ URL.save(s, this.config);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ this.keyToCheck = (char)r.restoreInt();
+ break;
+ case 1:
+ super.restoreState(r);
+ this.keyToCheck = (char)r.restoreInt();
+ this.waitForUp = r.restoreBoolean();
+ break;
+ case 2:
+ super.restoreState(r);
+ this.keyToCheck = (char)r.restoreInt();
+ this.waitForUp = r.restoreBoolean();
+ this.config = URL.restore(r);
+ break;
+ default:
+ throw new TooNewException();
+ }
+
+ if (this.config == null) {
+ this.configTable = null;
+ } else {
+ BackgroundLoader.get(this, this.config);
+ }
+ }
+
+ @Override
+ public String toString() {
+ String rval = super.toString() + "[";
+ if ((this.keyToCheck & 1) != 0) {
+ rval = rval + "*";
+ } else {
+ rval = rval + " ";
+ }
+
+ if ((this.keyToCheck & 4) != 0) {
+ rval = rval + "*";
+ } else {
+ rval = rval + " ";
+ }
+
+ if ((this.keyToCheck & 2) != 0) {
+ rval = rval + "*";
+ } else {
+ rval = rval + " ";
+ }
+
+ if (this.waitForUp) {
+ rval = rval + "u]";
+ } else {
+ rval = rval + "d]";
+ }
+
+ return rval;
+ }
+
+ class Area {
+ int x;
+ int y;
+ int w;
+ int h;
+ String actionNamePrefix;
+ Vector props;
+ }
+}
diff --git a/NET/worlds/scape/ClickWidget.java b/NET/worlds/scape/ClickWidget.java
new file mode 100644
index 0000000..e234aa9
--- /dev/null
+++ b/NET/worlds/scape/ClickWidget.java
@@ -0,0 +1,17 @@
+package NET.worlds.scape;
+
+abstract class ClickWidget extends WidgetButton {
+ ClickWidget(ToolBar toolbar, String name, String prompt) {
+ super(toolbar, name, prompt);
+ }
+
+ @Override
+ public boolean usesDrag() {
+ return false;
+ }
+
+ @Override
+ public boolean available() {
+ return true;
+ }
+}
diff --git a/NET/worlds/scape/ClipboardEntry.java b/NET/worlds/scape/ClipboardEntry.java
new file mode 100644
index 0000000..86a2d46
--- /dev/null
+++ b/NET/worlds/scape/ClipboardEntry.java
@@ -0,0 +1,44 @@
+package NET.worlds.scape;
+
+class ClipboardEntry {
+ private SuperRoot original;
+ private byte[] copy;
+ private boolean canPasteOriginal;
+
+ boolean copy(SuperRoot obj) {
+ this.original = obj;
+ this.copy = obj.getByteCopy();
+ this.canPasteOriginal = false;
+ return this.copy != null;
+ }
+
+ boolean cut(SuperRoot obj) {
+ boolean var3;
+ try {
+ var3 = this.copy(obj);
+ } finally {
+ this.canPasteOriginal = true;
+ }
+
+ return var3;
+ }
+
+ SuperRoot paste() {
+ if (this.copy != null) {
+ if (this.canPasteOriginal) {
+ this.canPasteOriginal = false;
+ return this.original;
+ } else {
+ return SuperRoot.getCopyFromBytes(this.copy);
+ }
+ } else {
+ return null;
+ }
+ }
+
+ void unPaste(SuperRoot obj) {
+ if (obj == this.original) {
+ this.canPasteOriginal = true;
+ }
+ }
+}
diff --git a/NET/worlds/scape/ColorAttribute.java b/NET/worlds/scape/ColorAttribute.java
new file mode 100644
index 0000000..8255062
--- /dev/null
+++ b/NET/worlds/scape/ColorAttribute.java
@@ -0,0 +1,81 @@
+package NET.worlds.scape;
+
+import java.awt.Color;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class ColorAttribute extends Attribute {
+ private Color value = Color.black;
+ private static Object classCookie = new Object();
+
+ public ColorAttribute(int attrID) {
+ super(attrID);
+ }
+
+ public ColorAttribute() {
+ }
+
+ public void set(Color x) {
+ this.value = x;
+ this.noteChange();
+ }
+
+ public Color get() {
+ return this.value;
+ }
+
+ @Override
+ public void generateNetData(DataOutputStream s) throws IOException {
+ s.writeInt(this.value.getRGB());
+ }
+
+ @Override
+ public void setFromNetData(DataInputStream ds, int len) throws IOException {
+ this.value = new Color(ds.readInt());
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = ColorPropertyEditor.make(new Property(this, index, "value"));
+ } else if (mode == 1) {
+ ret = this.get();
+ } else if (mode == 2) {
+ this.set((Color)value);
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 1, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(0, classCookie);
+ super.saveState(s);
+ s.saveInt(this.value.getRGB());
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ this.value = new Color(r.restoreInt());
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + "[" + this.get() + "]";
+ }
+}
diff --git a/NET/worlds/scape/ColorEditorDialog.java b/NET/worlds/scape/ColorEditorDialog.java
new file mode 100644
index 0000000..99c23a6
--- /dev/null
+++ b/NET/worlds/scape/ColorEditorDialog.java
@@ -0,0 +1,68 @@
+package NET.worlds.scape;
+
+import java.awt.Color;
+import java.util.StringTokenizer;
+
+class ColorEditorDialog extends ListEditorDialog {
+ protected Property property;
+ protected Color c;
+
+ ColorEditorDialog(EditTile parent, String title, Property property) {
+ super(parent, title);
+ this.property = property;
+ this.ready();
+ }
+
+ @Override
+ protected void build() {
+ this.c = (Color)this.property.get();
+ super.build();
+ }
+
+ @Override
+ protected int getElementCount() {
+ return 3;
+ }
+
+ @Override
+ protected String getElement(int index) {
+ if (this.c == null) {
+ return "null";
+ } else {
+ switch (index) {
+ case 0:
+ return "" + this.c.getRed();
+ case 1:
+ return "" + this.c.getGreen();
+ default:
+ return "" + this.c.getBlue();
+ }
+ }
+ }
+
+ @Override
+ protected boolean setElements(StringTokenizer e) {
+ int[] c = new int[3];
+ int count = 0;
+
+ while (e.hasMoreTokens()) {
+ try {
+ int tmp = Integer.valueOf(e.nextToken());
+ if (tmp < 0 || tmp > 255) {
+ return false;
+ }
+
+ c[count++] = tmp;
+ } catch (Exception var5) {
+ return false;
+ }
+ }
+
+ if (count == 3) {
+ this.parent.addUndoableSet(this.property, new Color(c[0], c[1], c[2]));
+ return true;
+ } else {
+ return false;
+ }
+ }
+}
diff --git a/NET/worlds/scape/ColorPropertyEditor.java b/NET/worlds/scape/ColorPropertyEditor.java
new file mode 100644
index 0000000..2abef3c
--- /dev/null
+++ b/NET/worlds/scape/ColorPropertyEditor.java
@@ -0,0 +1,19 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.PolledDialog;
+
+public class ColorPropertyEditor extends PropEditor {
+ private ColorPropertyEditor(Property property) {
+ super(property);
+ }
+
+ @Override
+ public PolledDialog edit(EditTile parent, String title) {
+ return new ColorEditorDialog(parent, title, this.property);
+ }
+
+ public static Property make(Property property) {
+ property.setPropertyType(4);
+ return property.setEditor(new ColorPropertyEditor(property));
+ }
+}
diff --git a/NET/worlds/scape/CopyWidget.java b/NET/worlds/scape/CopyWidget.java
new file mode 100644
index 0000000..121c1b1
--- /dev/null
+++ b/NET/worlds/scape/CopyWidget.java
@@ -0,0 +1,14 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+
+class CopyWidget extends ClickWidget {
+ public CopyWidget(ToolBar toolbar) {
+ super(toolbar, Console.message("copy.gif"), Console.message("Copy"));
+ }
+
+ @Override
+ public void perform() {
+ Console.getFrame().getEditTile().copy();
+ }
+}
diff --git a/NET/worlds/scape/CrashAction.java b/NET/worlds/scape/CrashAction.java
new file mode 100644
index 0000000..c8a23ce
--- /dev/null
+++ b/NET/worlds/scape/CrashAction.java
@@ -0,0 +1,56 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+public class CrashAction extends Action {
+ private String message = "CrashAction";
+ private static Object classCookie = new Object();
+
+ public void setMessage(String m) {
+ this.message = m;
+ }
+
+ @Override
+ public Persister trigger(Event e, Persister seqId) {
+ throw new Error(this.message);
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Message"));
+ } else if (mode == 1) {
+ ret = new String(this.message);
+ } else if (mode == 2) {
+ this.message = (String)value;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 1, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(1, classCookie);
+ super.saveState(s);
+ s.saveString(this.message);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 1:
+ super.restoreState(r);
+ this.message = r.restoreString();
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/CutWidget.java b/NET/worlds/scape/CutWidget.java
new file mode 100644
index 0000000..d28aa54
--- /dev/null
+++ b/NET/worlds/scape/CutWidget.java
@@ -0,0 +1,14 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+
+class CutWidget extends ClickWidget {
+ public CutWidget(ToolBar toolbar) {
+ super(toolbar, "cut.gif", Console.message("Cut"));
+ }
+
+ @Override
+ public void perform() {
+ Console.getFrame().getEditTile().cut();
+ }
+}
diff --git a/NET/worlds/scape/DPAction.java b/NET/worlds/scape/DPAction.java
new file mode 100644
index 0000000..a3bb3f8
--- /dev/null
+++ b/NET/worlds/scape/DPAction.java
@@ -0,0 +1,220 @@
+package NET.worlds.scape;
+
+import NET.worlds.core.Std;
+import java.io.IOException;
+import java.util.Enumeration;
+
+public class DPAction extends Action {
+ private static final int INFINITY = 60000;
+ protected int loadDist = 2;
+ protected int unloadDist = 4;
+ protected DPState state = null;
+ private static Object classCookie = new Object();
+
+ public int getLoadDist() {
+ return this.loadDist;
+ }
+
+ public int getUnloadDist() {
+ return this.unloadDist;
+ }
+
+ public void setLoadDist(int v) {
+ assert v > 0;
+
+ if (v > 0) {
+ this.loadDist = v;
+ if (this.unloadDist <= this.loadDist) {
+ this.unloadDist = v + 1;
+ }
+ }
+ }
+
+ public void setUnloadDist(int v) {
+ assert v > 1;
+
+ if (v <= this.loadDist) {
+ this.unloadDist = this.loadDist + 1;
+ } else {
+ this.unloadDist = v;
+ }
+ }
+
+ @Override
+ public Persister trigger(Event e, Persister seqID) {
+ if (this.state == null) {
+ return null;
+ } else {
+ if (e != null) {
+ this.state.setDist(0, e.time);
+ } else {
+ this.state.setDist(0, Std.getFastTime());
+ }
+
+ return null;
+ }
+ }
+
+ public void handleDist(int dist, int time) {
+ assert this.loadDist < this.unloadDist;
+
+ if (this.getOwner() instanceof Portal) {
+ if (dist <= this.loadDist) {
+ ((Portal)this.getOwner()).triggerLoad();
+ if (((Portal)this.getOwner()).active()) {
+ this.informOtherSide(dist + 1, time);
+ } else {
+ new DPLoadTracker(this, dist + 1, time);
+ }
+ } else if (dist > this.unloadDist) {
+ ((Portal)this.getOwner()).reset();
+ } else if (((Portal)this.getOwner()).active()) {
+ this.informOtherSide(dist + 1, time);
+ }
+ }
+ }
+
+ void informOtherSide(int distance, int triggerTime) {
+ DPState s = null;
+ Portal p = ((Portal)this.getOwner()).farSide();
+ Enumeration e = p.getActions();
+
+ while (e.hasMoreElements()) {
+ Object a = e.nextElement();
+ if (a instanceof DPAction) {
+ s = ((DPAction)a).getState();
+
+ assert s != null;
+ }
+ }
+
+ if (s != null) {
+ s.setDist(distance, triggerTime);
+ }
+ }
+
+ @Override
+ protected void noteAddingTo(SuperRoot owner) {
+ super.noteAddingTo(owner);
+ if (this.state == null) {
+ if (owner instanceof Portal) {
+ Portal p = (Portal)owner;
+ World w = owner.getWorld();
+ if (w != null) {
+ this.state = this.findState(w);
+ }
+
+ if (this.state == null) {
+ this.state = new DPState(60000, this);
+ } else {
+ this.state.addConnection(this);
+ }
+ }
+ }
+ }
+
+ protected DPState findState(SuperRoot root) {
+ DPState rVal = null;
+ Enumeration e = root.getDeepOwned();
+
+ while (e.hasMoreElements() && rVal == null) {
+ SuperRoot sr = (SuperRoot)e.nextElement();
+ if (sr instanceof DPAction) {
+ rVal = ((DPAction)sr).getState();
+ }
+ }
+
+ return rVal;
+ }
+
+ public DPState getState() {
+ return this.state;
+ }
+
+ @Override
+ public void detach() {
+ if (this.state != null) {
+ this.state.dropConnection(this);
+ this.state = null;
+ }
+
+ super.detach();
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = IntegerPropertyEditor.make(new Property(this, index, "Load Distance"));
+ } else if (mode == 1) {
+ ret = new Integer(this.loadDist);
+ } else if (mode == 2) {
+ this.setLoadDist((Integer)value);
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = IntegerPropertyEditor.make(new Property(this, index, "Unload Distance"));
+ } else if (mode == 1) {
+ ret = new Integer(this.unloadDist);
+ } else if (mode == 2) {
+ this.setUnloadDist((Integer)value);
+ }
+ break;
+ case 2:
+ if (mode == 0) {
+ ret = new Property(this, index, "Cell State");
+ } else if (mode == 1) {
+ ret = this.state;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 3, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(2, classCookie);
+ super.saveState(s);
+ s.saveInt(this.loadDist);
+ s.saveInt(this.unloadDist);
+ s.saveMaybeNull(this.state);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ this.loadDist = r.restoreInt();
+ this.unloadDist = r.restoreInt();
+ this.state = (DPState)r.restore();
+ r.restoreInt();
+ break;
+ case 1:
+ super.restoreState(r);
+ this.loadDist = r.restoreInt();
+ this.unloadDist = r.restoreInt();
+ this.state = (DPState)r.restore();
+ break;
+ case 2:
+ super.restoreState(r);
+ this.loadDist = r.restoreInt();
+ this.unloadDist = r.restoreInt();
+ this.state = (DPState)r.restoreMaybeNull();
+ break;
+ default:
+ throw new TooNewException();
+ }
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + "[" + this.getOwner().getWorld().getName() + "|" + this.getOwner().getName() + "]";
+ }
+}
diff --git a/NET/worlds/scape/DPLoadTracker.java b/NET/worlds/scape/DPLoadTracker.java
new file mode 100644
index 0000000..657739b
--- /dev/null
+++ b/NET/worlds/scape/DPLoadTracker.java
@@ -0,0 +1,44 @@
+package NET.worlds.scape;
+
+class DPLoadTracker extends WObject implements FrameHandler, NonPersister {
+ protected DPAction src;
+ protected int distance;
+ protected int triggerTime = 0;
+
+ public DPLoadTracker(DPAction a, int dist, int time) {
+ this.src = a;
+ this.setDistance(dist, time);
+ ((Portal)this.src.getOwner()).addHandler(this);
+ }
+
+ public DPLoadTracker() {
+ }
+
+ public void setDistance(int dist, int time) {
+ if (time > this.triggerTime) {
+ this.distance = dist;
+ this.triggerTime = time;
+ }
+ }
+
+ @Override
+ public boolean handle(FrameEvent ev) {
+ if (((Portal)this.src.getOwner()).active()) {
+ this.src.informOtherSide(this.distance, this.triggerTime);
+ this.finish();
+ } else if (((Portal)this.src.getOwner()).unconnected()) {
+ this.finish();
+ }
+
+ return true;
+ }
+
+ public void finish() {
+ ((Portal)this.src.getOwner()).removeHandler(this);
+ }
+
+ @Override
+ public String toString() {
+ return super.toString();
+ }
+}
diff --git a/NET/worlds/scape/DPState.java b/NET/worlds/scape/DPState.java
new file mode 100644
index 0000000..f4502eb
--- /dev/null
+++ b/NET/worlds/scape/DPState.java
@@ -0,0 +1,118 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Vector;
+
+public class DPState extends SuperRoot {
+ public static final int INFINITY = 60000;
+ protected Vector connections = new Vector();
+ protected int currentDist = 60000;
+ protected long currentTime = 0L;
+ private static Object classCookie = new Object();
+
+ public DPState(int dist, DPAction conn) {
+ this.currentDist = dist;
+ this.currentTime = 0L;
+ this.addConnection(conn);
+ }
+
+ public DPState() {
+ }
+
+ public void setDist(int d, int t) {
+ if (this.currentTime <= t) {
+ if (this.currentDist > d || this.currentTime != t) {
+ this.currentDist = d;
+ this.currentTime = t;
+ Enumeration e = this.connections.elements();
+
+ while (e.hasMoreElements()) {
+ ((DPAction)e.nextElement()).handleDist(d, t);
+ }
+ }
+ }
+ }
+
+ public int getDist() {
+ return this.currentDist;
+ }
+
+ public Enumeration getConnections() {
+ return this.connections.elements();
+ }
+
+ public Enumeration getPortals() {
+ Vector v = new Vector(this.connections.size());
+ Enumeration e = this.connections.elements();
+
+ while (e.hasMoreElements()) {
+ v.addElement(((DPAction)e.nextElement()).getOwner());
+ }
+
+ return v.elements();
+ }
+
+ public void addConnection(DPAction conn) {
+ if (!this.connections.contains(conn)) {
+ this.connections.addElement(conn);
+ }
+ }
+
+ public void dropConnection(DPAction conn) {
+ this.connections.removeElement(conn);
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = IntegerPropertyEditor.make(new Property(this, index, "Current Distance"));
+ } else if (mode == 1) {
+ ret = new Integer(this.currentDist);
+ } else if (mode == 2) {
+ this.currentDist = (Integer)value;
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = new VectorProperty(this, index, "Connections");
+ } else if (mode == 1) {
+ ret = this.connections.clone();
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 2, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(0, classCookie);
+ super.saveState(s);
+ s.saveVector(this.connections);
+ s.saveInt(this.currentDist);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ this.connections = r.restoreVector();
+ this.currentDist = r.restoreInt();
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+
+ @Override
+ public String toString() {
+ return super.getName();
+ }
+}
diff --git a/NET/worlds/scape/DeepEnumeration.java b/NET/worlds/scape/DeepEnumeration.java
new file mode 100644
index 0000000..060d71e
--- /dev/null
+++ b/NET/worlds/scape/DeepEnumeration.java
@@ -0,0 +1,114 @@
+package NET.worlds.scape;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+public class DeepEnumeration<K> implements Enumeration<K> {
+ Vector<SuperRoot> roots = new Vector<SuperRoot>();
+ Vector<Vector<K>> vectors = new Vector<Vector<K>>();
+ Vector<K> currentVector = null;
+ int currentIndex = -1;
+ SuperRoot nextValue = null;
+ protected boolean valueRetrieved = true;
+
+ public DeepEnumeration(SuperRoot o) {
+ this.addChildElement(o);
+ }
+
+ public DeepEnumeration(Vector<K> v) {
+ this.addChildVector(v);
+ }
+
+ public DeepEnumeration(Enumeration<K> e) {
+ this.addChildEnumeration(e);
+ }
+
+ public DeepEnumeration() {
+ }
+
+ @Override
+ public boolean hasMoreElements() {
+ if (this.valueRetrieved) {
+ this.getNextElement();
+ }
+
+ return this.nextValue != null;
+ }
+
+ @Override
+ public K nextElement() {
+ if (this.valueRetrieved) {
+ this.getNextElement();
+ }
+
+ this.valueRetrieved = true;
+ return (K)this.nextValue;
+ }
+
+ protected void getNextElement() {
+ this.valueRetrieved = false;
+ if (!this.roots.isEmpty()) {
+ this.nextValue = this.roots.elementAt(this.roots.size() - 1);
+ this.roots.removeElementAt(this.roots.size() - 1);
+
+ assert this.nextValue != null;
+
+ this.nextValue.getChildren(this);
+ } else if (this.currentIndex >= 0) {
+ try {
+ this.nextValue = (SuperRoot)this.currentVector.elementAt(this.currentIndex--);
+ } catch (ArrayIndexOutOfBoundsException var2) {
+ this.currentIndex = this.currentVector.size() - 1;
+ this.getNextElement();
+ }
+
+ assert this.nextValue != null;
+
+ this.nextValue.getChildren(this);
+ } else if (!this.vectors.isEmpty()) {
+ this.currentVector = this.vectors.elementAt(this.vectors.size() - 1);
+ this.currentIndex = this.currentVector.size() - 1;
+ this.vectors.removeElementAt(this.vectors.size() - 1);
+ this.getNextElement();
+ } else {
+ this.nextValue = null;
+ }
+ }
+
+ public void addChildVector(Vector<K> eventHandlers) {
+ assert eventHandlers != null;
+
+ this.vectors.addElement(eventHandlers);
+ }
+
+ public void addChildEnumeration(Enumeration<K> e) {
+ assert e != null;
+
+ while (e.hasMoreElements()) {
+ this.addChildElement(e.nextElement());
+ }
+ }
+
+ public void addChildVectorWithNulls(Vector<K> v) {
+ assert v != null;
+
+ for (int i = v.size() - 1; i >= 0; i--) {
+ Object obj = v.elementAt(i--);
+ if (obj != null) {
+ this.addChildElement(obj);
+ }
+ }
+ }
+
+ public void addChildElement(Object o) {
+ assert o != null;
+
+ this.roots.addElement((SuperRoot)o);
+ }
+
+ public void addChildVectorAction(Vector<K> actions) {
+ assert actions != null;
+
+ this.vectors.addElement(actions);
+ }
+}
diff --git a/NET/worlds/scape/DialogAction.java b/NET/worlds/scape/DialogAction.java
new file mode 100644
index 0000000..b0092be
--- /dev/null
+++ b/NET/worlds/scape/DialogAction.java
@@ -0,0 +1,118 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.DialogReceiver;
+import NET.worlds.console.PolledDialog;
+import java.io.IOException;
+
+public abstract class DialogAction extends Action implements DialogReceiver {
+ boolean showDialog = true;
+ boolean cancelOnly = false;
+ private static PolledDialog dialogUp = null;
+ private PolledDialog thisDialog;
+ protected static boolean doCancel = false;
+ private static Object classCookie = new Object();
+
+ @Override
+ public void dialogDone(Object who, boolean confirmed) {
+ if (dialogUp == who) {
+ doCancel = true;
+ if (confirmed) {
+ this.doIt();
+ }
+ }
+ }
+
+ public abstract void doIt();
+
+ public abstract PolledDialog getDialog();
+
+ @Override
+ public Persister trigger(Event e, Persister seqID) {
+ Console console = Console.getActive();
+ if (console == null) {
+ return null;
+ } else if (!this.showDialog && !this.cancelOnly) {
+ if (console != null) {
+ this.doIt();
+ }
+
+ return null;
+ } else if (dialogUp == null) {
+ if (this.cancelOnly) {
+ return null;
+ } else {
+ this.thisDialog = dialogUp = this.getDialog();
+ doCancel = false;
+ return this;
+ }
+ } else {
+ if (this.thisDialog == dialogUp && seqID != null) {
+ if (doCancel) {
+ dialogUp.closeIt(false);
+ dialogUp = null;
+ this.thisDialog = null;
+ return null;
+ }
+ } else {
+ doCancel = true;
+ }
+
+ return this;
+ }
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Display Dialog Box"), "Don't ask", "Ask user to ok choice");
+ } else if (mode == 1) {
+ ret = new Boolean(this.showDialog);
+ } else if (mode == 2) {
+ this.showDialog = (Boolean)value;
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Cancel only"), "Regular operation", "Cancels dialog, doesn't do action");
+ } else if (mode == 1) {
+ ret = new Boolean(this.cancelOnly);
+ } else if (mode == 2) {
+ this.cancelOnly = (Boolean)value;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 2, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(0, classCookie);
+ super.saveState(s);
+ s.saveBoolean(this.showDialog);
+ s.saveBoolean(this.cancelOnly);
+ }
+
+ protected void dialogActionSkipRestore(Restorer r) throws IOException, TooNewException {
+ super.restoreState(r);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ this.showDialog = r.restoreBoolean();
+ this.cancelOnly = r.restoreBoolean();
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/DiffRoomSensor.java b/NET/worlds/scape/DiffRoomSensor.java
new file mode 100644
index 0000000..141b76e
--- /dev/null
+++ b/NET/worlds/scape/DiffRoomSensor.java
@@ -0,0 +1,49 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+public class DiffRoomSensor extends Sensor implements FrameHandler {
+ private Room lastCamRoom;
+ private static Object classCookie = new Object();
+
+ @Override
+ public void detach() {
+ this.lastCamRoom = null;
+ super.detach();
+ }
+
+ @Override
+ public boolean handle(FrameEvent e) {
+ Object owner = this.getOwner();
+ if (owner != null && owner instanceof WObject) {
+ WObject o = (WObject)owner;
+ Room thisRoom = o.getRoom();
+ Room thisCamRoom = Pilot.getActiveRoom();
+ if (thisCamRoom != thisRoom && this.lastCamRoom == thisRoom) {
+ this.trigger(e);
+ }
+
+ this.lastCamRoom = thisCamRoom;
+ return true;
+ } else {
+ return true;
+ }
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(0, classCookie);
+ super.saveState(s);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/DirectShow.java b/NET/worlds/scape/DirectShow.java
new file mode 100644
index 0000000..9af989b
--- /dev/null
+++ b/NET/worlds/scape/DirectShow.java
@@ -0,0 +1,51 @@
+package NET.worlds.scape;
+
+public class DirectShow implements TextureSurfaceRenderer {
+ static final int nUnitialized = 0;
+ static final int nStopped = 1;
+ static final int nPaused = 2;
+ static final int nPlaying = 3;
+ private int mediaRendererInstancePtr;
+ private int m_hwnd;
+
+ public DirectShow() {
+ nativeInit();
+ this.nInit(0);
+ }
+
+ public DirectShow(int hwnd) {
+ this.m_hwnd = hwnd;
+ nativeInit();
+ this.nInit(hwnd);
+ }
+
+ @Override
+ public void finalize() {
+ this.nTick();
+ this.nStop();
+ this.nShutdown();
+ }
+
+ @Override
+ public void renderTo(int dc) {
+ this.nRenderTo(this.m_hwnd, dc);
+ }
+
+ public static native void nativeInit();
+
+ protected native void nInit(int var1);
+
+ protected native void nShutdown();
+
+ public native void nOpen(String var1);
+
+ public native void nPlay(int var1);
+
+ public native void nStop();
+
+ public native void nPause();
+
+ public native void nRenderTo(int var1, int var2);
+
+ public native int nTick();
+}
diff --git a/NET/worlds/scape/DiskShadow.java b/NET/worlds/scape/DiskShadow.java
new file mode 100644
index 0000000..603ad75
--- /dev/null
+++ b/NET/worlds/scape/DiskShadow.java
@@ -0,0 +1,61 @@
+package NET.worlds.scape;
+
+import java.awt.Color;
+
+public class DiskShadow extends Polygon implements NonPersister, Shadow {
+ private static int numSides = 8;
+ private static float[] diskVertices = new float[5 * numSides];
+
+ static {
+ float radius = 0.5F;
+ int end = 5 * numSides;
+ double angle = 0.0;
+ double angleInc = (float)((Math.PI * 2) / numSides);
+
+ for (int i = 0; i < end; angle += angleInc) {
+ float x = (float)Math.cos(angle);
+ float y = (float)Math.sin(angle);
+ diskVertices[i + 0] = radius * x;
+ diskVertices[i + 1] = radius * y;
+ diskVertices[i + 2] = 0.0F;
+ diskVertices[i + 3] = 0.5F + 0.5F * x;
+ diskVertices[i + 4] = 0.5F + 0.5F * y;
+ i += 5;
+ }
+ }
+
+ public DiskShadow(WObject caster) {
+ super(diskVertices, new Material(0.0F, 0.0F, 0.0F, Color.black, null, 0.5F, false, false));
+ this.setBumpable(false);
+ this.adjustShadow(caster);
+ }
+
+ @Override
+ public void adjustShadow(WObject caster) {
+ Room r = caster.getRoom();
+ if (caster.getVisible() && r != null) {
+ float defSize = 0.0F;
+ float size = caster.getMinXYExtent();
+ BoundBoxTemp box = caster.getBoundBox();
+ if (!(size <= 0.0F) && !(size > 10000.0F) && !(box.hi.z < 0.0F) && !(box.lo.z >= 250.0F)) {
+ float shadowFrac = 1.0F;
+ if (box.lo.z > 0.0F) {
+ shadowFrac = 1.0F - box.lo.z / 250.0F;
+ }
+
+ if (this.getOwner() == null && r != null) {
+ r.getEnvironment().add(this);
+ }
+
+ Point3Temp xyz = caster.getWorldPosition();
+ this.moveTo(xyz.x, xyz.y, r.floorHeight(xyz.x, xyz.y, xyz.z) + 0.5F);
+ this.yaw(this.getYaw() - caster.getYaw());
+ this.scale(size * shadowFrac / this.getScaleX());
+ } else {
+ this.detach();
+ }
+ } else {
+ this.detach();
+ }
+ }
+}
diff --git a/NET/worlds/scape/DispenserAction.java b/NET/worlds/scape/DispenserAction.java
new file mode 100644
index 0000000..082336a
--- /dev/null
+++ b/NET/worlds/scape/DispenserAction.java
@@ -0,0 +1,98 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.network.URL;
+import java.io.IOException;
+
+public class DispenserAction extends Action {
+ URL wobName;
+ Point3 center = new Point3(200.0F, 200.0F, 0.0F);
+ float radius = 50.0F;
+ private static Object classCookie = new Object();
+
+ @Override
+ public Persister trigger(Event arg, Persister seqID) {
+ WObject w = (WObject)this.getOwner();
+ SuperRoot ob = SuperRoot.readFile(this.wobName);
+ if (!(ob instanceof WObject)) {
+ Console.println(Console.message("Cant-find") + this.wobName);
+ return null;
+ } else {
+ WObject wob = (WObject)ob;
+ Point3Temp pos = Point3Temp.make(
+ this.radius - (float)Math.random() * 2.0F * this.radius, this.radius - (float)Math.random() * 2.0F * this.radius, 0.0F
+ )
+ .plus(this.center);
+ pos.z = wob.getZ();
+ wob.moveTo(pos);
+ w.getRoom().add(wob);
+ return null;
+ }
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = URLPropertyEditor.make(new Property(this, index, "wob File Name"), "wob");
+ } else if (mode == 1) {
+ ret = this.wobName;
+ } else if (mode == 2) {
+ this.wobName = (URL)value;
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = Point3PropertyEditor.make(new Property(this, index, "Center Position For Drop"));
+ } else if (mode == 1) {
+ ret = new Point3(this.center);
+ } else if (mode == 2) {
+ this.center = new Point3((Point3)value);
+ }
+ break;
+ case 2:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Drop-position Radius"));
+ } else if (mode == 1) {
+ ret = new Float(this.radius);
+ } else if (mode == 2) {
+ this.radius = (Float)value;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 3, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(0, classCookie);
+ super.saveState(s);
+ URL.save(s, this.wobName);
+ s.save(this.center);
+ s.saveFloat(this.radius);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ this.wobName = URL.restore(r);
+ this.center = (Point3)r.restore();
+ this.radius = r.restoreFloat();
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + "[" + this.wobName + "]";
+ }
+}
diff --git a/NET/worlds/scape/DoorBasedFilter.java b/NET/worlds/scape/DoorBasedFilter.java
new file mode 100644
index 0000000..3a46069
--- /dev/null
+++ b/NET/worlds/scape/DoorBasedFilter.java
@@ -0,0 +1,142 @@
+package NET.worlds.scape;
+
+public class DoorBasedFilter extends AudibilityFilter {
+ float stopDistance;
+ public static final double log10 = Math.log(10.0);
+
+ DoorBasedFilter(Sound s, WObject o, int maxHops, float stopDist) {
+ super(s, o, maxHops, stopDist);
+ this.debugOut(6, "DoorBasedFilter");
+ this.stopDistance = stopDist;
+ }
+
+ private void debugOut(int level, String s) {
+ if (Sound.debugLevel > level) {
+ System.out.println(s);
+ }
+ }
+
+ @Override
+ void fillOwnerEntry() {
+ this.debugOut(9, "door fillOwnerEntry called " + this.sound.getURL());
+ DoorBasedParams dbp = new DoorBasedParams();
+ dbp.room = this.owner.getRoom();
+ dbp.transform = Transform.make();
+ dbp.hopcount = 0;
+ dbp.portalCenter = new Point3(this.owner.getPosition());
+ dbp.localPortalCenter = new Point3(dbp.portalCenter);
+ dbp.nextLastApparent = new Point3(dbp.portalCenter);
+ dbp.position = new Point3(dbp.portalCenter);
+ dbp.portalWidth = 0.0F;
+ dbp.next = null;
+ dbp.distance = 0.0;
+ this.ownerPos = dbp;
+ this.roomList.addElement(this.ownerPos);
+ }
+
+ @Override
+ void fillNewAP(AudibleParams connectingRoom, Portal bestPortal, int bestCount) {
+ this.debugOut(9, "fillNewAP from " + bestPortal.farSideRoom().getName());
+ DoorBasedParams conRoom = (DoorBasedParams)connectingRoom;
+ this.debugOut(9, " to conRoom " + conRoom.room.getName());
+ DoorBasedParams newAP = new DoorBasedParams();
+ newAP.room = bestPortal.farSideRoom();
+ newAP.hopcount = bestCount;
+ if (bestPortal.p2pXform() == null) {
+ bestPortal.setTransform();
+ }
+
+ if (bestPortal.p2pXform() != null) {
+ newAP.transform = bestPortal.p2pXform().getTransform();
+ } else {
+ newAP.transform = Transform.make();
+ }
+
+ newAP.portalWidth = bestPortal.getScaleX();
+ newAP.portalCenter = new Point3(bestPortal.getPosition());
+ newAP.portalCenter.plus(bestPortal.getFarCorner()).times(0.5F);
+ newAP.localPortalCenter = new Point3(newAP.portalCenter);
+ newAP.localPortalCenter.times(newAP.transform);
+ newAP.next = conRoom;
+ newAP.nextLastApparent = new Point3(newAP.next.position);
+ newAP.nextLastApparent.times(newAP.transform);
+ newAP.position = newAP.nextLastApparent;
+ newAP.distance = Point3Temp.make(newAP.portalCenter).minus(newAP.next.localPortalCenter).length() + newAP.next.distance;
+ this.roomList.addElement(newAP);
+ this.localPos = newAP;
+ }
+
+ @Override
+ public void adjustEmitterLocation() {
+ this.debugOut(6, "DoorBasedFilter::adjustEmitterLocation");
+ if (this.ownerPos.room != this.owner.getRoom()) {
+ this.moveEmitter();
+ } else {
+ this.recursiveFindAttenuation((DoorBasedParams)this.localPos);
+ }
+ }
+
+ public void recursiveFindAttenuation(DoorBasedParams dbp) {
+ this.debugOut(9, "recursiveFindAttenuation on " + dbp.room.getName());
+ if (dbp.next == null) {
+ dbp.portalCenter.copy(this.owner.getPosition());
+ dbp.localPortalCenter.copy(dbp.portalCenter);
+ dbp.nextLastApparent.copy(dbp.portalCenter);
+ dbp.position.copy(dbp.portalCenter);
+ } else {
+ this.recursiveFindAttenuation(dbp.next);
+ dbp.nextLastApparent.copy(dbp.next.position);
+ dbp.nextLastApparent.times(dbp.transform);
+ dbp.distance = Point3Temp.make(dbp.portalCenter).minus(dbp.next.localPortalCenter).length() + dbp.next.distance;
+ this.calculateEmitterPosition(dbp);
+ }
+ }
+
+ public double calculateTau(Point3Temp listener, Point3Temp portalPos, float portalWidth) {
+ assert portalWidth > 0.0F;
+
+ double tau = (Point3Temp.make(listener).minus(portalPos).length() - portalWidth) / portalWidth;
+ tau = Math.max(Math.min(tau, 1.0), 0.0);
+
+ assert tau >= 0.0;
+
+ assert tau <= 1.0;
+
+ return tau;
+ }
+
+ @Override
+ public void getEmitterPosition(Point3Temp pos) {
+ this.debugOut(9, "getEmitterPosition");
+ this.calculateEmitterPosition((DoorBasedParams)this.localPos);
+ pos.copy(((DoorBasedParams)this.localPos).position);
+ }
+
+ private void calculateEmitterPosition(DoorBasedParams dbp) {
+ if (dbp.next != null) {
+ float tau = (float)this.calculateTau(Pilot.getActive().getPosition(), dbp.localPortalCenter, dbp.portalWidth);
+ Point3Temp far = Point3Temp.make(dbp.nextLastApparent);
+ Point3Temp local = Point3Temp.make(dbp.localPortalCenter);
+ Point3Temp apparent = local.times(tau).plus(far.times(1.0F - tau));
+ dbp.position.copy(apparent);
+ }
+ }
+
+ @Override
+ public float getEmitterVolume() {
+ float rv = 1.0F;
+
+ assert this.localPos != null;
+
+ DoorBasedParams dbp = (DoorBasedParams)this.localPos;
+ if (dbp.next == null) {
+ return 1.0F;
+ } else {
+ Point3Temp apparent = Point3Temp.make(dbp.position);
+ double atten = apparent.minus(dbp.localPortalCenter).length();
+ double atten1 = dbp.distance - atten;
+ double atten2 = -2.0 / this.stopDistance * atten1;
+ return (float)Math.exp(atten2 * log10);
+ }
+ }
+}
diff --git a/NET/worlds/scape/DoorBasedParams.java b/NET/worlds/scape/DoorBasedParams.java
new file mode 100644
index 0000000..2fd3eab
--- /dev/null
+++ b/NET/worlds/scape/DoorBasedParams.java
@@ -0,0 +1,10 @@
+package NET.worlds.scape;
+
+class DoorBasedParams extends AudibleParams {
+ public Point3 portalCenter;
+ public Point3 localPortalCenter;
+ public Point3 nextLastApparent;
+ public float portalWidth;
+ public DoorBasedParams next;
+ public double distance;
+}
diff --git a/NET/worlds/scape/Drone.java b/NET/worlds/scape/Drone.java
new file mode 100644
index 0000000..d930b61
--- /dev/null
+++ b/NET/worlds/scape/Drone.java
@@ -0,0 +1,864 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.BBAppearDroneCommand;
+import NET.worlds.console.BBDisappearDroneCommand;
+import NET.worlds.console.BBDroneBitmapCommand;
+import NET.worlds.console.BBDroneDeltaPosCommand;
+import NET.worlds.console.BBMoveDroneCommand;
+import NET.worlds.console.BlackBox;
+import NET.worlds.console.Console;
+import NET.worlds.console.FriendsListPart;
+import NET.worlds.console.Main;
+import NET.worlds.console.MainCallback;
+import NET.worlds.console.MuteListPart;
+import NET.worlds.core.IniFile;
+import NET.worlds.core.ServerTableManager;
+import NET.worlds.core.Std;
+import NET.worlds.network.FilthFilter;
+import NET.worlds.network.Galaxy;
+import NET.worlds.network.InfiniteWaitException;
+import NET.worlds.network.NetworkObject;
+import NET.worlds.network.ObjID;
+import NET.worlds.network.OldPropertyList;
+import NET.worlds.network.PacketTooLargeException;
+import NET.worlds.network.PropertyList;
+import NET.worlds.network.URL;
+import NET.worlds.network.WorldServer;
+import NET.worlds.network.net2Property;
+import NET.worlds.network.netProperty;
+import NET.worlds.network.propReqCmd;
+import java.awt.Color;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+public abstract class Drone extends WObject implements NetworkObject, WobLoaded, MouseDownHandler, FrameHandler {
+ private int _last_FrameTime;
+ private int _last_PosTime;
+ private int _vel_x;
+ private int _vel_y;
+ private int _vel_z;
+ private int _vel_yaw;
+ private int _last_x;
+ private int _last_y;
+ private int _last_z;
+ private int _last_yaw;
+ private int _x;
+ private int _y;
+ private int _z;
+ private int _yaw;
+ private boolean inited = false;
+ protected WObject tag;
+ protected WObject tagbg;
+ private Console console;
+ private float tagHeight;
+ private Shape sleepBox;
+ static boolean showNametags = IniFile.gamma().getIniInt("SHOWNAMETAGS", 1) == 1;
+ private static String[] employeeAccounts = ServerTableManager.instance().getTable("employeeAccounts");
+ private static Hashtable<String, String> employeeHash = null;
+ public static Vector<Drone> usableDrones = new Vector<Drone>();
+ private int lastUsed;
+ protected WorldServer _server;
+ private String sleepMode;
+ private static Object classCookie = new Object();
+ private static Object classCookieInterpolatedDrone = new Object();
+
+ static {
+ Main.register(new Drone.Flusher());
+ }
+
+ public Drone(ObjID id, WorldServer serv) {
+ if (serv != null) {
+ assert id != null;
+
+ this.attachToServer(serv.getLongID(id), serv);
+ }
+ }
+
+ protected Drone(String longID, WorldServer serv) {
+ assert longID != null;
+
+ if (serv != null) {
+ this.attachToServer(longID, serv);
+ }
+ }
+
+ private void attachToServer(String longID, WorldServer serv) {
+ if (serv != null) {
+ assert Main.isMainThread();
+
+ String nameWas = null;
+ if (this.tag != null) {
+ nameWas = this.getLongID();
+ }
+
+ this.getSharer().createDynamicFromNet();
+ this.setName(longID);
+ String nameIs = this.getLongID();
+ this._server = serv;
+ this._server.incRefCnt(this);
+ this._server.regObject(nameIs, this);
+
+ try {
+ this._server.sendNetworkMsg(new propReqCmd(new ObjID(this.getLongID())));
+ } catch (InfiniteWaitException var6) {
+ } catch (PacketTooLargeException var7) {
+ assert false;
+ }
+
+ if (nameIs.equals(nameWas)) {
+ this.avatarHeightChangedTo(189.0F);
+ } else {
+ this.makeTag(false);
+ }
+
+ Main.register(new Drone.MakeSleepBox());
+ }
+ }
+
+ private static void flushUnusedDrones() {
+ synchronized (usableDrones) {
+ int now = Std.getFastTime();
+ int i = usableDrones.size();
+
+ while (--i >= 0) {
+ Drone d = usableDrones.elementAt(i);
+ if (now > d.lastUsed + 2000) {
+ usableDrones.removeElementAt(i);
+ d.discard();
+ }
+ }
+ }
+ }
+
+ public static boolean isEmployeeAccount(String name) {
+ if (employeeHash == null) {
+ employeeHash = new Hashtable<String, String>();
+
+ for (int i = 0; i < employeeAccounts.length; i++) {
+ employeeHash.put(employeeAccounts[i], employeeAccounts[i]);
+ }
+ }
+
+ return employeeHash.get(name) != null;
+ }
+
+ public void makeTag(boolean force) {
+ this.tagHeight = 195.0F;
+ if (this.tag != null) {
+ this.tagHeight = this.tag.getPosition().z;
+ this.tag.detach();
+ this.tag = null;
+ }
+
+ if (this.tagbg != null) {
+ this.tagbg.detach();
+ this.tagbg = null;
+ }
+
+ if ((this._server != null || force) && !(this instanceof MutedDrone) && showNametags) {
+ String unfilteredName = this.getLongID();
+ String name = FilthFilter.get().filterName(unfilteredName);
+ if (name != null && !name.equals("")) {
+ Texture[] tagText = new Texture[1];
+ boolean hw = RenderWare.get3DHardwareInUse();
+ boolean isHost = name.toLowerCase().startsWith(Console.message("host")) || name.toLowerCase().startsWith("host");
+ if (isHost) {
+ name = Console.message("host-upper") + name.substring(4);
+ }
+
+ boolean isSpecialGuest = name.toLowerCase().startsWith(Console.message("guest-")) || name.toLowerCase().startsWith("guest-");
+ if (isSpecialGuest) {
+ name = Console.message("guest-upper") + name.substring(5);
+ }
+
+ boolean isEmployee = isEmployeeAccount(name);
+ Color bgColor;
+ if (isSpecialGuest) {
+ bgColor = Color.pink;
+ } else if (isHost) {
+ bgColor = Color.yellow;
+ } else if (isEmployee) {
+ bgColor = Color.cyan;
+ } else {
+ bgColor = Color.lightGray;
+ }
+
+ tagText[0] = new StringTexture(name, Console.message("TagFont"), 48, Color.black, hw ? new Color(254, 254, 254) : bgColor);
+ int height = 14;
+ int width = name.length() * 10;
+ Hologram h = new Hologram(width, height, tagText);
+ h.setViewplaneAligned(true);
+ h.raise(this.tagHeight);
+ h.setScaleDist(300.0F);
+ this.tag = h;
+ this.tag.setVisible(true);
+ this.tag.setBumpable(false);
+ this.tag.setLocalShadowed(false);
+ this.tag.setShadowedLocally(true);
+ this.add(this.tag);
+ if (hw) {
+ Texture[] bgText = new Texture[]{new StringTexture(name, Console.message("TagFont"), 48, Color.black, bgColor)};
+ Hologram h2 = new Hologram(width, height, bgText);
+ h2.setViewplaneAligned(true);
+ h2.raise(this.tagHeight);
+ h2.setScaleDist(300.0F);
+ h2.setMaterial(new Material(0.75F, 0.0F, 0.0F, Color.white, null, 0.5F, false, false));
+ this.tagbg = h2;
+ this.tagbg.setVisible(true);
+ this.tagbg.setBumpable(false);
+ this.tagbg.setLocalShadowed(false);
+ this.tagbg.setShadowedLocally(true);
+ this.add(this.tagbg);
+ }
+ }
+ }
+ }
+
+ protected void avatarHeightChangedTo(float h) {
+ if (this.tag != null) {
+ this.tag.raise(h + 1.0F + 5.0F - this.tag.getPosition().z);
+ }
+
+ if (this.tagbg != null) {
+ this.tagbg.raise(h + 1.0F + 5.0F - this.tagbg.getPosition().z);
+ }
+ }
+
+ public void detachFromServer(boolean reuse) {
+ assert Main.isMainThread();
+
+ if (this._server != null) {
+ this._server.delObject(new ObjID(this.getLongID()));
+ this._server.decRefCnt(this);
+ this._server = null;
+ }
+
+ if (reuse) {
+ this.lastUsed = Std.getFastTime();
+ synchronized (usableDrones) {
+ usableDrones.addElement(this);
+ }
+ }
+ }
+
+ public static Drone make(ObjID id, WorldServer serv) {
+ synchronized (usableDrones) {
+ if (!usableDrones.isEmpty() && id != null && serv != null) {
+ String name = "!" + serv.getLongID(id);
+
+ int i;
+ for (i = usableDrones.size() - 1; i > 0; i--) {
+ Drone d = usableDrones.elementAt(i);
+ if (d.getName().equals(name)) {
+ break;
+ }
+ }
+
+ Drone d = usableDrones.elementAt(i);
+ if (!d.getName().equals(name) && usableDrones.size() < 5) {
+ return new HoloDrone(id, serv);
+ } else {
+ usableDrones.removeElementAt(i);
+ d.attachToServer(serv.getLongID(id), serv);
+ return d;
+ }
+ } else {
+ return new HoloDrone(id, serv);
+ }
+ }
+ }
+
+ public Drone() {
+ }
+
+ @Override
+ public boolean handle(MouseDownEvent event) {
+ if (this._server != null && (event.key & 1) == 1) {
+ FriendsListPart.droneClick(this, event);
+ }
+
+ return true;
+ }
+
+ public float animate(String action) {
+ if (action.equalsIgnoreCase("_hdb")) {
+ new Drone.BounceNametag();
+ }
+
+ return 0.0F;
+ }
+
+ public Vector<String> getAnimationList() {
+ return new Vector<String>();
+ }
+
+ public void muteStateChanged() {
+ this.setAvatarNow(this.getCurrentURL());
+ }
+
+ public boolean shouldBeMuted() {
+ return MuteListPart.isMuted(this._server, this.getLongID());
+ }
+
+ private World getOwnerWorld() {
+ WObject o = (WObject)this.getOwner();
+ Room room = o == null ? null : o.getRoom();
+ return room == null ? null : room.getWorld();
+ }
+
+ public boolean shouldBeForcedHuman() {
+ World w = this.getOwnerWorld();
+ return w != null && w.getForceHuman();
+ }
+
+ public URL getCurrentURL() {
+ return this instanceof PosableDrone ? ((PosableDrone)this).getPosableShapeURL() : this.getSourceURL();
+ }
+
+ public Drone setAvatarNow(URL url) {
+ if (url == null) {
+ return this;
+ } else {
+ if (this.shouldBeForcedHuman()) {
+ url = PosableShape.getHuman(url);
+ if (Console.getActive() != null) {
+ Console.getActive().pendingPilot = url.toString();
+ }
+ }
+
+ url = PosableShape.getPermitted(url, this.getWorld());
+ boolean muted = this.shouldBeMuted();
+ if (url.equals(this.getCurrentURL()) && muted == (this instanceof MutedDrone)) {
+ return this;
+ } else if (!url.endsWith(".rwx") && !url.endsWith(".rwg") && !url.endsWith(".mov")) {
+ String s = url.getInternal();
+ if (s.endsWith(".pilot")) {
+ s = s.substring(0, s.length() - 6) + ".drone";
+ } else if (!s.endsWith(".drone")) {
+ s = s + ".drone";
+ }
+
+ url = URL.make(s);
+ if (url.equals(this.getSourceURL())) {
+ return this;
+ } else {
+ new WobLoader(url, this);
+ return this;
+ }
+ } else {
+ WObject o = (WObject)this.getOwner();
+ if (o == null) {
+ return this;
+ } else {
+ WorldServer serv = this._server;
+ String longID = this.getLongID();
+ this.detachFromServer(false);
+ this.detach();
+ Drone d;
+ if (muted) {
+ d = new MutedDrone(new ObjID(longID), serv, url);
+ } else if (url.endsWith(".mov")) {
+ d = new HoloDrone(new ObjID(longID), serv);
+ d.setAvatarNow(url);
+ } else {
+ d = new PosableDrone(new ObjID(longID), serv, url);
+ }
+
+ if (serv != null) {
+ d.transferFrom(this);
+ d.addTo(o.getRoom());
+ } else {
+ d.makeIdentity().post(this);
+ d.setName(this.getLongID());
+ o.add(d);
+ }
+
+ return d;
+ }
+ }
+ }
+ }
+
+ @Override
+ public void wobLoaded(WobLoader loader, SuperRoot w) {
+ if (w instanceof Drone) {
+ assert w != null;
+
+ Drone d = (Drone)w;
+ d.setName(this.getLongID());
+ if (this._server == null) {
+ WObject o = (WObject)this.getOwner();
+ this.detach();
+ d.makeIdentity().post(this);
+ o.add(d);
+ } else {
+ WorldServer serv = this._server;
+ String longID = this.getLongID();
+ this.detachFromServer(false);
+ Room r = this.getRoom();
+ this.detach();
+ d.addTo(r);
+ d.attachToServer(longID, serv);
+ d.transferFrom(this);
+ }
+ }
+ }
+
+ public void addTo(Room r) {
+ if (r != null) {
+ Console c = r.getWorld().getConsole();
+ if (this.console == null) {
+ this.console = c;
+ if (c != null) {
+ Pilot.copySoul(c.getDroneSoulTemplate(), this);
+ }
+ }
+
+ r.add(this);
+ }
+ }
+
+ @Override
+ public void add(WObject w) {
+ super.add(w);
+ }
+
+ @Override
+ protected void noteUnadding(SuperRoot child) {
+ if (child instanceof WObject) {
+ WObject w = (WObject)child;
+ if (w.isDynamic()) {
+ w.setVisible(true);
+ }
+ }
+
+ super.noteUnadding(child);
+ }
+
+ public void setSleepMode(String mode) {
+ if (!mode.equals(this.sleepMode)) {
+ this.sleepMode = mode;
+ Main.register(new Drone.MakeSleepBox());
+ }
+ }
+
+ private void handleVAR_ASLEEP(String s) {
+ if (s != null && s.length() > 2 && s.charAt(0) == 0) {
+ s = s.substring(2);
+ }
+
+ this.setSleepMode(s);
+ }
+
+ public Drone handleVAR_BITMAP(String s) {
+ if (s.equals("")) {
+ return this;
+ } else {
+ BlackBox.getInstance().submitEvent(new BBDroneBitmapCommand(this.getName(), s));
+ if (s.charAt(0) == 0) {
+ s = s.substring(2);
+ }
+
+ try {
+ return this.setAvatarNow(new URL(URL.getAvatar(), s));
+ } catch (MalformedURLException var3) {
+ Console.println(Console.message("Invalid-av") + s);
+ return this;
+ }
+ }
+ }
+
+ public Point3Temp getVelocity() {
+ return Point3Temp.make(this._vel_x, this._vel_y, this._vel_z);
+ }
+
+ public int getYawRate() {
+ return this._vel_yaw;
+ }
+
+ @Override
+ public boolean handle(FrameEvent fe) {
+ if (this._server == null) {
+ return true;
+ } else {
+ int timeNow = fe.time;
+ this.interpolate(timeNow, this._server.getUpdateTime(), this);
+ return true;
+ }
+ }
+
+ public void interpolate(int timeNow, int updateTime, Transform target) {
+ if (this.inited) {
+ if (timeNow - this._last_PosTime > updateTime) {
+ this._last_PosTime = timeNow;
+ this._vel_x = this._last_x - this._x;
+ this._vel_y = this._last_y - this._y;
+ this._vel_z = this._last_z - this._z;
+ this._vel_yaw = ((this._last_yaw - this._yaw) % 360 + 360) % 360;
+
+ assert this._vel_yaw >= 0;
+
+ if (this._vel_yaw > 180) {
+ this._vel_yaw -= 360;
+ }
+ }
+
+ double timeDiff = (double)(timeNow - this._last_FrameTime) / updateTime;
+ if (timeNow - this._last_FrameTime > updateTime) {
+ timeDiff = 0.0;
+ }
+
+ this._x = this._x + (int)(timeDiff * this._vel_x);
+ this._y = this._y + (int)(timeDiff * this._vel_y);
+ this._z = this._z + (int)(timeDiff * this._vel_z);
+ this._yaw = this._yaw + (int)(timeDiff * this._vel_yaw) % 360;
+ target.makeIdentity().moveBy(this._x, this._y, this._z).yaw(this._yaw);
+ this._last_FrameTime = timeNow;
+ }
+ }
+
+ public void reset(short x, short y, short z, short yaw) {
+ this._x = x;
+ this._y = y;
+ this._z = z;
+ this._yaw = yaw;
+ this._vel_x = this._vel_y = this._vel_z = 0;
+ this._vel_yaw = 0;
+ this._last_x = this._x;
+ this._last_y = this._y;
+ this._last_z = this._z;
+ this._last_yaw = this._yaw;
+ this._last_PosTime = this._last_FrameTime = Std.getRealTime();
+ this.inited = true;
+ }
+
+ protected void transferFrom(Drone i) {
+ this.makeIdentity().post(i);
+ this._x = i._x;
+ this._y = i._y;
+ this._z = i._z;
+ this._yaw = i._yaw;
+ this._vel_x = i._vel_x;
+ this._vel_y = i._vel_y;
+ this._vel_z = i._vel_z;
+ this._vel_yaw = i._vel_yaw;
+ this._last_x = i._last_x;
+ this._last_y = i._last_y;
+ this._last_z = i._last_z;
+ this._last_yaw = i._last_yaw;
+ this._last_PosTime = i._last_PosTime;
+ this._last_FrameTime = i._last_FrameTime;
+ this.inited = true;
+ }
+
+ public void appear(Room rm, short x, short y, short z, short yaw) {
+ assert rm != null;
+
+ BlackBox.getInstance().submitEvent(new BBAppearDroneCommand(rm.toString(), this.getName(), x, y, z, yaw));
+ if (this.getRoom() != rm) {
+ this.detach();
+ rm.add(this);
+ }
+
+ this.makeIdentity().moveBy(x, y, z).yaw(yaw);
+ this._x = x;
+ this._y = y;
+ this._z = z;
+ this._yaw = yaw;
+ this._vel_x = this._vel_y = this._vel_z = 0;
+ this._vel_yaw = 0;
+ this._last_x = x;
+ this._last_y = y;
+ this._last_z = z;
+ this._last_yaw = yaw;
+ this._last_PosTime = this._last_FrameTime = Std.getRealTime();
+ URL u = this.getCurrentURL();
+ if (u != null) {
+ this.setAvatarNow(u);
+ }
+
+ this.inited = true;
+ }
+
+ public void disappear() {
+ BlackBox.getInstance().submitEvent(new BBDisappearDroneCommand(this.getName()));
+ this.detachFromServer(true);
+ this.detach();
+ }
+
+ public void longLoc(short x, short y, short z, short yaw) {
+ if (!(this.getOwner() instanceof Pilot)) {
+ BlackBox.getInstance().submitEvent(new BBMoveDroneCommand(this.getName(), x, y, z, yaw));
+ }
+
+ this._last_x = x;
+ this._last_y = y;
+ this._last_z = z;
+ this._last_yaw = yaw;
+ this._vel_x = this._last_x - this._x;
+ this._vel_y = this._last_y - this._y;
+ this._vel_z = this._last_z - this._z;
+ this._vel_yaw = ((this._last_yaw - this._yaw) % 360 + 360) % 360;
+
+ assert this._vel_yaw >= 0;
+
+ if (this._vel_yaw > 180) {
+ this._vel_yaw -= 360;
+ }
+
+ this._last_PosTime = Std.getRealTime();
+ this.inited = true;
+ }
+
+ @Override
+ public void property(OldPropertyList propList) {
+ int end = propList.size();
+
+ for (int i = 0; i < end; i++) {
+ netProperty tmpProp = propList.elementAt(i);
+ switch (tmpProp.property()) {
+ case 5:
+ this.handleVAR_BITMAP(tmpProp.value());
+ break;
+ case 23:
+ this.handleVAR_ASLEEP(tmpProp.value());
+ break;
+ default:
+ byte[] data = new byte[tmpProp.value().length()];
+ tmpProp.value().getBytes(0, tmpProp.value().length(), data, 0);
+ this.getSharer().setFromNetData(tmpProp.property(), data);
+ }
+ }
+ }
+
+ @Override
+ public void propertyUpdate(PropertyList propList) {
+ int end = propList.size();
+
+ for (int i = 0; i < end; i++) {
+ net2Property tmpProp = propList.elementAt(i);
+ switch (tmpProp.property()) {
+ case 5:
+ this.handleVAR_BITMAP(tmpProp.value());
+ break;
+ case 23:
+ this.handleVAR_ASLEEP(tmpProp.value());
+ break;
+ default:
+ this.getSharer().setFromNetData(tmpProp.property(), tmpProp.data());
+ }
+ }
+ }
+
+ public void roomChange(Room newRoom, short x, short y, short z, short yaw) {
+ this.detach();
+ if (newRoom != null) {
+ this.appear(newRoom, x, y, z, yaw);
+ }
+ }
+
+ public void shortLoc(byte dx, byte dy, byte dyaw) {
+ if (!(this.getOwner() instanceof Pilot)) {
+ BlackBox.getInstance().submitEvent(new BBDroneDeltaPosCommand(this.getName(), dx, dy, dyaw));
+ }
+
+ this._last_x += dx;
+ this._last_y += dy;
+ this._last_yaw += dyaw;
+ this._last_yaw %= 360;
+ this._vel_x = this._last_x - this._x;
+ this._vel_y = this._last_y - this._y;
+ this._vel_z = 0;
+ this._vel_yaw = ((this._last_yaw - this._yaw) % 360 + 360) % 360;
+
+ assert this._vel_yaw >= 0;
+
+ if (this._vel_yaw > 180) {
+ this._vel_yaw -= 360;
+ }
+
+ this._last_PosTime = Std.getRealTime();
+ }
+
+ public void teleport(WorldServer serv, byte exitType, byte entryType, Room newRoom, short x, short y, short z, short yaw) {
+ assert serv.getObject(new ObjID(this.getLongID())) == this;
+
+ Room curRoom = this.getRoom();
+ switch (exitType) {
+ default:
+ if (curRoom != null) {
+ assert curRoom != null;
+
+ this.detach();
+ }
+ case 0:
+ switch (entryType) {
+ case 0:
+ this.detachFromServer(true);
+ this.detach();
+ break;
+ default:
+ if (newRoom == null) {
+ this.detach();
+ } else {
+ assert newRoom != null;
+
+ this.appear(newRoom, x, y, z, yaw);
+ }
+ }
+ }
+ }
+
+ @Override
+ public WorldServer getServer() {
+ return this._server;
+ }
+
+ @Override
+ public String getLongID() {
+ String name = this.getName();
+ if (name.startsWith("!")) {
+ name = name.substring(1);
+ }
+
+ return name;
+ }
+
+ @Override
+ public void register() {
+ assert false;
+ }
+
+ @Override
+ public void galaxyDisconnected() {
+ assert false;
+ }
+
+ @Override
+ public void reacquireServer(WorldServer oldServ) {
+ assert false;
+ }
+
+ @Override
+ public void changeChannel(Galaxy g, String oldChannel, String newChannel) {
+ assert false;
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ int var10000 = index - offset;
+ return super.properties(index, offset + 0, mode, value);
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ if (this.console != null) {
+ System.out.println("Warning: saving drone " + this.getName() + " WITH soul, which won't restore correctly!");
+ }
+
+ s.saveVersion(0, classCookieInterpolatedDrone);
+ s.saveVersion(0, classCookie);
+ super.saveState(s);
+ }
+
+ public void restoreStateDrone(Restorer r) throws IOException, TooNewException {
+ r.restoreVersion(classCookieInterpolatedDrone);
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ Enumeration e = this.getContents();
+
+ while (e.hasMoreElements()) {
+ WObject w = (WObject)e.nextElement();
+ if (w instanceof Hologram) {
+ Hologram h = (Hologram)w;
+ if (h.getMovieName() == null) {
+ this.tag = h;
+ }
+ }
+ }
+
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ this.restoreStateDrone(r);
+ }
+
+ class BounceNametag implements MainCallback {
+ int start;
+ WObject origTag;
+ WObject origTagbg;
+
+ BounceNametag() {
+ if (Drone.this.tag != null) {
+ this.start = Std.getFastTime();
+ this.origTag = Drone.this.tag;
+ this.origTagbg = Drone.this.tagbg;
+ Main.register(this);
+ }
+ }
+
+ @Override
+ public void mainCallback() {
+ int now = Std.getFastTime();
+ float h = Drone.this.tagHeight;
+ if (now > this.start + 6000 || this.origTag != Drone.this.tag || this.origTagbg != Drone.this.tagbg) {
+ Main.unregister(this);
+ } else if (now < this.start + 1500) {
+ h = Drone.this.tagHeight + 200.0F * ((now - this.start) / 1500.0F);
+ } else {
+ float t = (now - this.start) / 1500.0F;
+ h = (float)(200.0 * Math.pow(1.414F, t) * Math.cos(t * 3.14159F));
+ }
+
+ this.origTag.setZ(h);
+ if (this.origTagbg != null) {
+ this.origTagbg.setZ(h);
+ }
+ }
+ }
+
+ static class Flusher implements MainCallback {
+ int lastTime;
+
+ @Override
+ public void mainCallback() {
+ int now = Std.getFastTime();
+ if (now > this.lastTime + 1000) {
+ Drone.flushUnusedDrones();
+ this.lastTime = now;
+ }
+ }
+ }
+
+ class MakeSleepBox implements MainCallback {
+ @Override
+ public void mainCallback() {
+ if (Drone.this.sleepMode != null && Drone.this.sleepMode.equals(Console.message("asleep")) && !(Drone.this instanceof MutedDrone)) {
+ if (Drone.this.sleepBox == null) {
+ Drone.this.sleepBox = new Shape();
+ Drone.this.sleepBox.setURL(URL.make("home:idle.rwg"));
+ Drone.this.sleepBox.setBumpable(false);
+ Drone.this.sleepBox.scale(100.0F);
+ Drone.this.sleepBox.spin(0.0F, 1.0F, 1.0F, 180.0F);
+ Drone.this.sleepBox.raise(189.0F);
+ Drone.this.add(Drone.this.sleepBox);
+ }
+ } else if (Drone.this.sleepBox != null) {
+ Drone.this.sleepBox.detach();
+ Drone.this.sleepBox = null;
+ }
+
+ Main.unregister(this);
+ }
+ }
+}
diff --git a/NET/worlds/scape/DroneAnimator.java b/NET/worlds/scape/DroneAnimator.java
new file mode 100644
index 0000000..c50d926
--- /dev/null
+++ b/NET/worlds/scape/DroneAnimator.java
@@ -0,0 +1,92 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Gamma;
+import NET.worlds.console.Main;
+import NET.worlds.console.MainCallback;
+import NET.worlds.core.Std;
+import java.util.Vector;
+
+public class DroneAnimator implements MainCallback {
+ public static final int INVALID_INDEX = -1;
+ private static Vector<Integer> deltypeList;
+ protected int _rep = 0;
+
+ static {
+ init(".");
+ if (Gamma.loadProgress != null) {
+ Gamma.loadProgress.setMessage("Loading avatar definitions...");
+ Gamma.loadProgress.advance();
+ }
+
+ loadconfig(PendingCacheDrone.getAvatarDatPath());
+ }
+
+ public static native void init(String var0);
+
+ public static native void loadconfig(String var0);
+
+ public static native int getnameindex(String var0);
+
+ public static native String getindexgeom(int var0);
+
+ public static native void prepFigure(WObject var0, boolean var1);
+
+ public static native void addtype(int var0);
+
+ public static native void deltype(int var0);
+
+ public void delayedDeltype(int type) {
+ if (deltypeList == null) {
+ deltypeList = new Vector<Integer>();
+ Main.register(this);
+ }
+
+ deltypeList.addElement(new Integer(type));
+ deltypeList.addElement(new Integer(Std.getFastTime()));
+ }
+
+ @Override
+ public void mainCallback() {
+ int eraseTime = Std.getFastTime() - 20000;
+
+ while (deltypeList.size() > 1) {
+ int nextTime = deltypeList.elementAt(1);
+ if (nextTime > eraseTime) {
+ break;
+ }
+
+ int type = deltypeList.elementAt(0);
+ deltype(type);
+ deltypeList.removeElementAt(0);
+ deltypeList.removeElementAt(0);
+ }
+ }
+
+ public DroneAnimator() {
+ this._rep = CreateRep();
+ }
+
+ @Override
+ public void finalize() throws Throwable {
+ DestroyRep(this._rep);
+ super.finalize();
+ }
+
+ public native void endanimations();
+
+ public native void moveto(int var1, short var2, short var3, short var4, short var5, int var6);
+
+ public native void moveby(int var1, short var2, short var3, short var4, int var5);
+
+ public native void update(WObject var1, WObject var2, int var3, float var4, boolean var5);
+
+ public native float animate(int var1, String var2, int var3);
+
+ public native float getAnimationTime(int var1, String var2);
+
+ public static synchronized native Vector<String> getActionList(int var0);
+
+ protected static native int CreateRep();
+
+ protected static native void DestroyRep(int var0);
+}
diff --git a/NET/worlds/scape/DroneLoader.java b/NET/worlds/scape/DroneLoader.java
new file mode 100644
index 0000000..1b8052c
--- /dev/null
+++ b/NET/worlds/scape/DroneLoader.java
@@ -0,0 +1,80 @@
+package NET.worlds.scape;
+
+import NET.worlds.core.IniFile;
+import NET.worlds.network.URL;
+import java.util.Enumeration;
+import java.util.Vector;
+
+class DroneLoader {
+ private int MaxDroneLoadingRate = 2000;
+ static final boolean debug = false;
+
+ DroneLoader() {
+ int numAvs = IniFile.gamma().getIniInt("avatars", 24);
+ int droneRate = IniFile.gamma().getIniInt("droneLoadRate", 8000);
+ this.MaxDroneLoadingRate = droneRate / numAvs;
+ }
+
+ public synchronized void load(Vector droneList) {
+ try {
+ if (droneList.size() > 0) {
+ Vector listCopy = (Vector)droneList.clone();
+ Enumeration enums = listCopy.elements();
+
+ while (enums.hasMoreElements()) {
+ PendingDrone pd = (PendingDrone)enums.nextElement();
+ if (pd.getDrone().discarded) {
+ droneList.removeElement(pd);
+ } else {
+ loadDrone(pd);
+ droneList.removeElement(pd);
+ }
+ }
+ }
+
+ this.wait();
+ } catch (InterruptedException var5) {
+ }
+ }
+
+ public synchronized void wakeUp() {
+ this.notify();
+ }
+
+ private static void loadDrone(PendingDrone pd) {
+ if (!pd.getLoaded()) {
+ Enumeration e = PosableShape.getComponentAvatars(pd.getUrl());
+ if (e != null) {
+ while (e.hasMoreElements()) {
+ String avURL = (String)e.nextElement();
+ pd.download(URL.make(avURL));
+ }
+ }
+
+ PosableShape ps;
+ if (VehicleShape.isVehicle(pd.getUrl())) {
+ ps = new VehicleShape();
+ } else {
+ ps = new PosableShape();
+ }
+
+ boolean prog = ProgressiveAdder.get().enabled();
+ if (prog) {
+ ProgressiveAdder.get().scheduleForAdd(pd.getDrone(), ps);
+ }
+
+ ps.setURL(pd.getUrl());
+ ps.setVisible(true);
+ ps.setBumpable(false);
+ if (!pd.getDrone().isPilotDrone(pd.getUrl())) {
+ ps.enableLOD(true);
+ }
+
+ if (!prog) {
+ pd.getDrone().SetPendingShape(ps);
+ }
+
+ pd.setLoaded();
+ }
+ }
+}
diff --git a/NET/worlds/scape/DropInfo.java b/NET/worlds/scape/DropInfo.java
new file mode 100644
index 0000000..b955456
--- /dev/null
+++ b/NET/worlds/scape/DropInfo.java
@@ -0,0 +1,19 @@
+package NET.worlds.scape;
+
+import NET.worlds.network.URL;
+import java.awt.Component;
+import java.awt.Point;
+
+class DropInfo {
+ public URL url;
+ public String propertyName;
+ public Component comp;
+ public Point location;
+
+ DropInfo(URL url, String propertyName, Component comp, Point location) {
+ this.url = url;
+ this.propertyName = propertyName;
+ this.comp = comp;
+ this.location = location;
+ }
+}
diff --git a/NET/worlds/scape/DynamicForwardAttribute.java b/NET/worlds/scape/DynamicForwardAttribute.java
new file mode 100644
index 0000000..696a18e
--- /dev/null
+++ b/NET/worlds/scape/DynamicForwardAttribute.java
@@ -0,0 +1,172 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.network.URL;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.text.MessageFormat;
+import java.util.Enumeration;
+
+public class DynamicForwardAttribute extends Attribute implements NonPersister, WobLoaded {
+ WObject wob = null;
+ static int DYNAMIC_CODE = 21990;
+ WobLoader wobLoader;
+ DataInputStream wobLoaderProps;
+ private ByteArrayOutputStream _bs = new ByteArrayOutputStream();
+
+ DynamicForwardAttribute(int attrID) {
+ super(attrID);
+ }
+
+ private URL getDynamicHeader(DataInputStream ds) {
+ try {
+ return ds.readUnsignedShort() != DYNAMIC_CODE ? null : new URL(this, ds.readUTF());
+ } catch (IOException var3) {
+ return null;
+ }
+ }
+
+ @Override
+ public void setFromNetData(DataInputStream ds, int len) throws IOException {
+ URL wobName = this.getDynamicHeader(ds);
+ if (wobName != null && this.wob != null && wobName.equals(this.wob.getSourceURL())) {
+ this.setProps(ds);
+ } else {
+ if (this.wob != null) {
+ WObject w = this.wob;
+ this.wob = null;
+ w.detach();
+ }
+
+ if (wobName == null) {
+ ((Sharer)this.getOwner()).removeAttribute(this);
+ return;
+ }
+
+ if (this.wobLoader == null || !this.wobLoader.getWobName().equals(wobName)) {
+ this.wobLoader = new WobLoader(wobName, this);
+ }
+
+ this.wobLoaderProps = ds;
+ }
+ }
+
+ @Override
+ public void wobLoaded(WobLoader loader, SuperRoot w) {
+ if (loader == this.wobLoader) {
+ Object[] arguments = new Object[]{new String(loader.getWobName().toString())};
+ if (w == null) {
+ Console.println(MessageFormat.format(Console.message("Couldnt-load"), arguments));
+ this.wobLoaderProps = null;
+ } else if (!(w instanceof WObject)) {
+ Console.println(MessageFormat.format(Console.message("not-WObject"), arguments));
+ this.wobLoaderProps = null;
+ } else {
+ this.wob = (WObject)w;
+ this.wob.getSharer().createDynamicForwardedFromNet(this);
+ ((WObject)this.getOwner().getOwner()).add(this.wob);
+ this.setProps(this.wobLoaderProps);
+ this.wobLoaderProps = null;
+ }
+ }
+ }
+
+ void connect(WObject w) {
+ assert this.wob == null;
+
+ this.wob = w;
+ this.noteChange();
+ }
+
+ void unconnect() {
+ if (this.wob != null) {
+ this.wob = null;
+ this.noteChange();
+ }
+ }
+
+ public void setProps(DataInputStream ds) {
+ while (true) {
+ byte[] b;
+ int id;
+ try {
+ if ((id = ds.read()) == -1) {
+ return;
+ }
+
+ int len = ds.readByte();
+ b = new byte[len];
+ ds.readFully(b, 0, len);
+ } catch (IOException var6) {
+ Object[] arguments = new Object[]{new String("" + this.getAttrID())};
+ Console.println(MessageFormat.format(Console.message("Early-EOF"), arguments));
+ return;
+ }
+
+ this.wob.getSharer().setFromNetData(id, b);
+ }
+ }
+
+ @Override
+ public void generateNetData(DataOutputStream s) throws IOException {
+ if (this.wob != null && this.wob.getSourceURL() != null) {
+ s.writeShort(DYNAMIC_CODE);
+ s.writeUTF(this.wob.getSourceURL().getRelativeTo(this));
+ Enumeration e = this.wob.getSharer().getAttributes();
+
+ while (e.hasMoreElements()) {
+ Attribute a = (Attribute)e.nextElement();
+ s.writeByte(a.getAttrID());
+ this._bs.reset();
+
+ try {
+ a.generateNetData(new DataOutputStream(this._bs));
+ } catch (IOException var5) {
+ System.err.println(var5);
+ throw new Error("Fatal in generateNetData");
+ }
+
+ s.writeByte(this._bs.size());
+ this._bs.writeTo(s);
+ }
+ }
+ }
+
+ @Override
+ protected void noteAddingTo(SuperRoot owner) {
+ WObject w = (WObject)owner.getOwner();
+ if ((w.getSharer().getMode() & 1) != 0) {
+ throw new ClassCastException("Must forward to unforwarded object");
+ }
+ }
+
+ @Override
+ public void detach() {
+ if (this.wob == null && !this._waitingForFeedback) {
+ this.wobLoader = null;
+ super.detach();
+ } else {
+ Console.println(Console.message("Shutting-down"));
+ if (this.wob != null) {
+ this.wob.detach();
+ }
+ }
+ }
+
+ @Override
+ public void setAttrID(int newID) {
+ Console.println(Console.message("Cant-change-ID"));
+ }
+
+ @Override
+ public String toString() {
+ return this.wob == null ? super.toString() : super.toString() + "[forwarding wob " + this.wob.getName() + "]";
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ assert false;
+ }
+}
diff --git a/NET/worlds/scape/EditMusicDialog.java b/NET/worlds/scape/EditMusicDialog.java
new file mode 100644
index 0000000..a5720b0
--- /dev/null
+++ b/NET/worlds/scape/EditMusicDialog.java
@@ -0,0 +1,166 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.DialogReceiver;
+import NET.worlds.console.FileSysDialog;
+import NET.worlds.console.PolledDialog;
+import java.awt.Button;
+import java.awt.Checkbox;
+import java.awt.Font;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Label;
+import java.awt.Panel;
+import java.awt.TextField;
+
+class EditMusicDialog extends PolledDialog implements DialogReceiver {
+ private TextField nameField = new TextField(20);
+ private TextField trackField = new TextField(3);
+ private TextField midiField = new TextField(30);
+ private Button browseButton = new Button(Console.message("Browse"));
+ private Checkbox loopBox = new Checkbox(Console.message("Loop-cont"));
+ private Button okButton = new Button(Console.message("OK"));
+ private Button cancelButton = new Button(Console.message("Cancel"));
+ private MusicManagerDialog parent;
+ private MusicTrack music;
+ private String oldName;
+ private String path;
+ private static Font font = new Font(Console.message("MenuFont"), 0, 12);
+ private static Font bfont = new Font(Console.message("ButtonFont"), 0, 12);
+
+ public EditMusicDialog(MusicManagerDialog parent, MusicTrack music) {
+ super(parent, parent, music == null ? Console.message("Add-Music") : Console.message("Edit-Music"), true);
+ this.parent = parent;
+ this.music = music;
+ if (music != null) {
+ this.oldName = music.getName();
+ }
+
+ this.path = parent.getManager().getFileName().toLowerCase().replace('/', '\\');
+ this.path = this.path.substring(0, this.path.lastIndexOf(92) + 1);
+ this.ready();
+ }
+
+ @Override
+ protected void build() {
+ GridBagLayout gbag = new GridBagLayout();
+ this.setLayout(gbag);
+ GridBagConstraints c = new GridBagConstraints();
+ c.fill = 0;
+ c.anchor = 13;
+ this.add(gbag, new Label(Console.message("Name"), 2), c);
+ c.gridwidth = 0;
+ c.anchor = 17;
+ this.nameField.setFont(font);
+ this.trackField.setFont(font);
+ this.midiField.setFont(font);
+ this.browseButton.setFont(bfont);
+ this.loopBox.setFont(font);
+ this.add(gbag, this.nameField, c);
+ c.gridwidth = 1;
+ c.anchor = 13;
+ Label vt = new Label(Console.message("Virtual-track"), 2);
+ vt.setFont(font);
+ this.add(gbag, vt, c);
+ c.gridwidth = 0;
+ c.anchor = 17;
+ this.add(gbag, this.trackField, c);
+ c.gridwidth = 1;
+ c.anchor = 13;
+ Label am = new Label(Console.message("Alternate-MIDI"), 2);
+ am.setFont(font);
+ this.add(gbag, am, c);
+ c.fill = 2;
+ c.weightx = 1.0;
+ c.anchor = 17;
+ this.add(gbag, this.midiField, c);
+ c.fill = 0;
+ c.weightx = 0.0;
+ c.gridwidth = 0;
+ this.add(gbag, this.browseButton, c);
+ this.add(gbag, this.loopBox, c);
+ c.fill = 0;
+ c.anchor = 10;
+ Panel p = new Panel();
+ this.okButton.setFont(bfont);
+ this.cancelButton.setFont(bfont);
+ p.add(this.okButton);
+ p.add(this.cancelButton);
+ this.add(gbag, p, c);
+ if (this.music != null) {
+ this.nameField.setText(this.music.getName());
+ this.trackField.setText("" + this.music.getVirtTrackNumber());
+ this.midiField.setText(this.music.getMIDIFileName());
+ this.loopBox.setState(this.music.getLooping());
+ }
+ }
+
+ @Override
+ public boolean action(java.awt.Event event, Object what) {
+ Object target = event.target;
+ if (target == this.okButton && this.nameField.getText().trim().length() != 0) {
+ return this.done(true);
+ } else if (target == this.cancelButton) {
+ return this.done(false);
+ } else {
+ if (target == this.browseButton) {
+ this.dialogDisable(true);
+ new FileSysDialog(
+ Console.getFrame(),
+ this,
+ Console.message("Browse-MIDI"),
+ 0,
+ "MIDI Files|*.mid;*.midi|All Files|*.*",
+ this.path + this.midiField.getText(),
+ false
+ );
+ }
+
+ return false;
+ }
+ }
+
+ @Override
+ public synchronized void dialogDone(Object who, boolean confirmed) {
+ this.dialogDisable(false);
+ if (confirmed && who instanceof FileSysDialog) {
+ String name = ((FileSysDialog)who).fileName().toLowerCase();
+ if (name.startsWith(this.path)) {
+ this.midiField.setText(name.substring(this.path.length()));
+ }
+ }
+ }
+
+ public boolean isEditor() {
+ return this.music != null;
+ }
+
+ public MusicTrack getMusicTrack() {
+ String name = this.nameField.getText().trim();
+ int track = 0;
+
+ try {
+ track = Integer.parseInt(this.trackField.getText());
+ } catch (NumberFormatException var5) {
+ }
+
+ String midi = this.midiField.getText().trim();
+ boolean loop = this.loopBox.getState();
+ if (this.music == null) {
+ return new MusicTrack(name, track, midi, loop);
+ } else {
+ this.music.setName(name);
+ if (track != -1) {
+ this.music.setVirtTrackNumber(track);
+ }
+
+ this.music.setMIDIFileName(midi);
+ this.music.setLooping(loop);
+ return this.music;
+ }
+ }
+
+ public String getOldName() {
+ return this.oldName;
+ }
+}
diff --git a/NET/worlds/scape/EditRoomDialog.java b/NET/worlds/scape/EditRoomDialog.java
new file mode 100644
index 0000000..eca4180
--- /dev/null
+++ b/NET/worlds/scape/EditRoomDialog.java
@@ -0,0 +1,122 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.PolledDialog;
+import NET.worlds.core.Sort;
+import java.awt.Button;
+import java.awt.Choice;
+import java.awt.Font;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Label;
+import java.awt.Panel;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+class EditRoomDialog extends PolledDialog {
+ private Choice roomChoice = new Choice();
+ private Choice musicChoice = new Choice();
+ private Button okButton = new Button(Console.message("OK"));
+ private Button cancelButton = new Button(Console.message("Cancel"));
+ private MusicManagerDialog parent;
+ private MusicRoom room;
+ private String startSelect;
+ private static String lastMusic;
+ private static Font font = new Font(Console.message("MenuFont"), 0, 12);
+ private static Font bfont = new Font(Console.message("ButtonFont"), 0, 12);
+
+ public EditRoomDialog(MusicManagerDialog parent, MusicRoom room, String startSelect) {
+ super(parent, parent, Console.message("Assign-Music"), true);
+ this.parent = parent;
+ this.room = room;
+ this.startSelect = startSelect;
+ this.ready();
+ }
+
+ @Override
+ protected void build() {
+ GridBagLayout gbag = new GridBagLayout();
+ this.setLayout(gbag);
+ GridBagConstraints c = new GridBagConstraints();
+ c.fill = 0;
+ c.anchor = 13;
+ Label lName = new Label(Console.message("Room-name"), 2);
+ lName.setFont(font);
+ this.add(gbag, lName, c);
+ c.gridwidth = 0;
+ c.anchor = 17;
+ this.roomChoice.setFont(font);
+ this.add(gbag, this.roomChoice, c);
+ c.gridwidth = 1;
+ c.anchor = 13;
+ Label lMusic = new Label(Console.message("Music"), 2);
+ lMusic.setFont(font);
+ this.add(gbag, lMusic, c);
+ c.gridwidth = 0;
+ c.anchor = 17;
+ this.musicChoice.setFont(font);
+ this.add(gbag, this.musicChoice, c);
+ c.anchor = 10;
+ Panel p = new Panel();
+ p.setFont(bfont);
+ p.add(this.okButton);
+ p.add(this.cancelButton);
+ this.add(gbag, p, c);
+ this.roomChoice.setFont(font);
+ this.musicChoice.setFont(font);
+ if (this.room != null) {
+ this.roomChoice.add(this.room.getRoomName());
+ }
+
+ Enumeration e = this.parent.getAllRooms().elements();
+ Hashtable roomsWithMusic = this.parent.getManager().getRooms();
+ Vector v = new Vector();
+
+ while (e.hasMoreElements()) {
+ String name = (String)e.nextElement();
+ if (!roomsWithMusic.containsKey(name)) {
+ v.addElement(name);
+ }
+ }
+
+ Sort.sortInto(this.roomChoice, v);
+ Sort.sortInto(this.musicChoice, this.parent.getManager().getMusic());
+ if (this.room != null) {
+ this.roomChoice.select(this.room.getRoomName());
+ this.musicChoice.select(this.room.getMusicName());
+ } else {
+ this.roomChoice.select(this.startSelect);
+ if (lastMusic != null) {
+ this.musicChoice.select(lastMusic);
+ }
+ }
+ }
+
+ @Override
+ public boolean action(java.awt.Event event, Object what) {
+ Object target = event.target;
+ if (target == this.okButton) {
+ return this.done(true);
+ } else {
+ return target == this.cancelButton ? this.done(false) : false;
+ }
+ }
+
+ public boolean isEditor() {
+ return this.room != null;
+ }
+
+ public MusicRoom getMusicRoom() {
+ String roomName = this.roomChoice.getSelectedItem();
+ String musicName = this.musicChoice.getSelectedItem();
+ lastMusic = musicName;
+ if (this.room == null) {
+ return new MusicRoom(roomName, musicName);
+ } else {
+ this.room.setRoomName(roomName);
+ this.room.setMusicName(musicName);
+ return this.room;
+ }
+ }
+}
diff --git a/NET/worlds/scape/EditTile.java b/NET/worlds/scape/EditTile.java
new file mode 100644
index 0000000..d0ab600
--- /dev/null
+++ b/NET/worlds/scape/EditTile.java
@@ -0,0 +1,664 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.DialogDisabled;
+import NET.worlds.console.DialogReceiver;
+import NET.worlds.console.ExposedPanel;
+import NET.worlds.console.Main;
+import NET.worlds.console.MainCallback;
+import NET.worlds.console.PolledDialog;
+import NET.worlds.console.RenderCanvas;
+import NET.worlds.console.SnapTool;
+import NET.worlds.console.Tree;
+import NET.worlds.console.TreeCallback;
+import NET.worlds.network.URL;
+import java.awt.Button;
+import java.awt.Component;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Label;
+import java.awt.Point;
+import java.io.IOException;
+import java.text.MessageFormat;
+import java.util.Enumeration;
+import java.util.Vector;
+
+public class EditTile extends ExposedPanel implements DialogReceiver, TreeCallback, MainCallback, DialogDisabled {
+ private Button editButton = new Button(Console.message("Edit"));
+ private Button addButton = new Button(Console.message("Add"));
+ private Button delButton = new Button(Console.message("Delete"));
+ private Button helpButton = new Button(Console.message("Help"));
+ private ToolBar toolbar = new ToolBar();
+ private Label title = new Label();
+ private String titleText = "";
+ private boolean usingTitleAsPrompt;
+ private PropList props = new PropList();
+ private int queuedFunction = 0;
+ private Object queuedObject;
+ private Tree tree;
+ private PolledDialog activePopup;
+ private boolean startup = true;
+ private World rootWorld = null;
+ private boolean isDialogDisabled;
+ private static final int NONE = 0;
+ private static final int DELETE = 1;
+ private static final int ADD = 2;
+ private static final int CHANGE = 3;
+ private static final int UPDATE = 4;
+ private static final int CUT = 5;
+ private static final int COPY = 6;
+ private static final int PASTE = 7;
+ private static final int UNDO = 8;
+ private static final int EDIT = 9;
+ private static final int DROP = 10;
+ private static final int HELP = 11;
+ private static ClipboardEntry clipboard;
+ private static UndoStack undoStack = new UndoStack();
+ private Undoable preAddStackTop;
+ private boolean isAdd;
+ private SendURLAction helpAction = new SendURLAction();
+ private Persister helpBrowser;
+
+ public void viewProperties(Object obj) {
+ Console.getFrame().setShaperVisible(true);
+ this.queue(3, obj);
+ }
+
+ public void libraryDrop(URL url, String propertyName, Component comp, Point location) {
+ this.queue(10, new DropInfo(url, propertyName, comp, location));
+ }
+
+ public EditTile(Tree tree) {
+ this.tree = tree;
+ tree.setOwner(this);
+ GridBagLayout gbag = new GridBagLayout();
+ this.setLayout(gbag);
+ GridBagConstraints c = new GridBagConstraints();
+ c.fill = 2;
+ c.gridwidth = 0;
+ c.weightx = 1.0;
+ c.weighty = 0.0;
+ c.anchor = 18;
+ this.add(gbag, this.toolbar, c);
+ this.add(gbag, this.title, c);
+ c.weighty = 1.0;
+ c.fill = 1;
+ c.gridwidth = 2;
+ c.gridheight = 0;
+ this.add(gbag, this.props, c);
+ c.weightx = 0.0;
+ c.weighty = 0.0;
+ c.gridwidth = 0;
+ c.gridheight = 1;
+ c.fill = 2;
+ this.add(gbag, this.editButton, c);
+ this.add(gbag, this.addButton, c);
+ this.add(gbag, this.delButton, c);
+ this.add(gbag, this.helpButton, c);
+ Main.register(this);
+ }
+
+ public void update() {
+ this.queue(4);
+ }
+
+ private void add(GridBagLayout gbag, Component comp, GridBagConstraints c) {
+ gbag.setConstraints(comp, c);
+ this.add(comp);
+ }
+
+ private boolean queue(int function) {
+ return this.queue(function, null);
+ }
+
+ private synchronized boolean queue(int function, Object obj) {
+ if (this.queuedFunction == 0 && this.activePopup == null) {
+ this.queuedFunction = function;
+ this.queuedObject = obj;
+ this.disable();
+ }
+
+ return true;
+ }
+
+ @Override
+ public synchronized void mainCallback() {
+ if (this.startup) {
+ World w = Pilot.getActiveWorld();
+ if (w != null) {
+ this.change(w);
+ this.startup = false;
+ }
+ }
+
+ if (this.rootWorld != null) {
+ this.rootWorld.incRef();
+ }
+
+ boolean enable = true;
+ switch (this.queuedFunction) {
+ case 0:
+ return;
+ case 1:
+ this.delete(false);
+ break;
+ case 2:
+ enable = this.doAdd();
+ break;
+ case 3:
+ this.change(this.queuedObject);
+ break;
+ case 4:
+ this.tree.update();
+ break;
+ case 5:
+ this.delete(true);
+ break;
+ case 6:
+ this.doCopy();
+ break;
+ case 7:
+ this.doPaste();
+ break;
+ case 8:
+ this.doUndo();
+ break;
+ case 9:
+ enable = this.doEdit();
+ break;
+ case 10:
+ if (!this.drop((DropInfo)this.queuedObject)) {
+ Object[] arguments = new Object[]{new String("" + ((DropInfo)this.queuedObject).url)};
+ Console.println(MessageFormat.format(Console.message("Target-doesnt"), arguments));
+ }
+ break;
+ case 11:
+ this.doHelp();
+ }
+
+ this.enable(enable);
+ this.queuedFunction = 0;
+ this.queuedObject = null;
+ }
+
+ private void delete(boolean isCut) {
+ if (this.delButton.isEnabled()) {
+ PropTreeNode e = (PropTreeNode)this.tree.getSelectedNode();
+ if (e != null && this.tree.hasFocus()) {
+ this.addUndoable(e.delete(isCut));
+ } else {
+ Property p = this.props.getSelectedProperty();
+
+ assert p.canSetNull() && p.get() != null;
+
+ this.addUndoableSet(p, null);
+ }
+
+ this.tree.update();
+ }
+ }
+
+ public static void adjustDroppedSource(SuperRoot sr) {
+ if (sr != null && (!(sr instanceof WObject) || !((WObject)sr).isDynamic())) {
+ sr.setSourceURL(null);
+ }
+ }
+
+ private boolean drop(DropInfo info) {
+ Object dropped = info.url;
+ if (info.url.endsWith(".class") || info.url.endsWith("." + WObject.getSaveExtension())) {
+ SuperRoot sr = WobLoader.immediateLoad(info.url);
+ adjustDroppedSource(sr);
+ dropped = sr;
+ }
+
+ return this.drop(dropped, info.propertyName, false, info.comp, info.location);
+ }
+
+ private boolean drop(Object obj, String propertyName, boolean isPaste) {
+ return this.drop(obj, propertyName, isPaste, null, null);
+ }
+
+ private boolean drop(Object obj, String propertyName, boolean isPaste, Component comp, Point location) {
+ if (obj == null) {
+ return false;
+ } else {
+ PropTreeNode e = null;
+ Point3Temp dropPoint = null;
+ if (comp == null && this.tree.hasFocus()) {
+ e = (PropTreeNode)this.tree.getSelectedNode();
+ } else if (comp == this.tree) {
+ e = (PropTreeNode)this.tree.elementAt(location);
+ } else if (comp instanceof RenderCanvas) {
+ Camera c = ((RenderCanvas)comp).getCamera();
+ dropPoint = Point3Temp.make();
+ WObject picked = c.getObjectAt(location.x, location.y, false, dropPoint);
+ if (picked != null) {
+ if (obj instanceof WObject) {
+ picked = picked.getRoom();
+ }
+ } else {
+ Pilot pilot = Pilot.getActive();
+ picked = pilot.getRoom();
+ dropPoint.set(0.0F, 180.0F, 0.0F);
+ dropPoint.times(pilot);
+ }
+
+ if (picked != null) {
+ this.change(picked);
+ e = (PropTreeNode)this.tree.getSelectedNode();
+ }
+ }
+
+ if (e == null) {
+ return false;
+ } else {
+ boolean success = false;
+ VectorProperty vp;
+ PropAdder adder;
+ if ((vp = e.getContainingVectorProperty()) != null && (adder = vp.getAdder()) != null) {
+ success = adder.libraryDrop(this, obj, isPaste, true);
+ }
+
+ if (!success) {
+ Object top;
+ for (top = null; e != null; e = (PropTreeNode)e.getParent()) {
+ top = e.getObject();
+ if (top instanceof Properties) {
+ break;
+ }
+
+ if (top instanceof Property) {
+ Property prop = (Property)top;
+ top = ((Property)top).get();
+ if (top instanceof Properties) {
+ break;
+ }
+ }
+ }
+
+ if (e != null) {
+ Vector targets = new Vector();
+ int topLevelTargets = this.recurseFindDropTargets(targets, obj, propertyName, isPaste, new EnumProperties(top), 0, 10);
+ if (topLevelTargets == 1 || topLevelTargets == 0 && targets.size() == 1) {
+ success = ((LibraryDrop)targets.elementAt(0)).libraryDrop(this, obj, isPaste, true);
+ }
+ }
+ }
+
+ if (success) {
+ if (obj instanceof Properties) {
+ this.change(obj);
+ } else {
+ this.tree.update();
+ }
+ }
+
+ WObject wobj;
+ if (dropPoint != null && obj instanceof WObject && !(obj instanceof Room) && (wobj = (WObject)obj).isActive()) {
+ dropPoint.z = wobj.getZ();
+ wobj.moveTo(SnapTool.snapTool().snapTo(dropPoint));
+ }
+
+ return success;
+ }
+ }
+ }
+
+ private int recurseFindDropTargets(Vector targets, Object obj, String propertyName, boolean isPaste, Enumeration props, int level, int maxLevel) {
+ int firstLevelMatches = 0;
+ if (level > maxLevel) {
+ return 0;
+ } else {
+ while (props.hasMoreElements()) {
+ Property p = (Property)props.nextElement();
+ boolean propMatch = propertyName == null || propertyName.equals(p.getName());
+ if (propMatch) {
+ LibraryDrop target = null;
+ if (p instanceof VectorProperty) {
+ target = ((VectorProperty)p).getAdder();
+ } else {
+ target = p.getEditor();
+ }
+
+ if (target != null && target.libraryDrop(this, obj, isPaste, false)) {
+ if (level == 0) {
+ targets.insertElementAt(target, firstLevelMatches++);
+ } else {
+ targets.addElement(target);
+ }
+ continue;
+ }
+ }
+
+ if (!(p instanceof VectorProperty)) {
+ int err = this.recurseFindDropTargets(targets, obj, propertyName, isPaste, new EnumProperties(p.get()), level + 1, maxLevel);
+ if (err != 0) {
+ return err;
+ }
+ }
+ }
+
+ return firstLevelMatches;
+ }
+ }
+
+ private boolean change(Object obj) {
+ Object parent = obj;
+ Vector lineage = new Vector();
+
+ Object p;
+ while (parent instanceof Properties && (p = ((Properties)parent).propertyParent()) != null) {
+ if (lineage != null) {
+ Enumeration e = new EnumProperties(p);
+ boolean found = false;
+
+ while (e.hasMoreElements()) {
+ Property prop = (Property)e.nextElement();
+ Object o = prop.get();
+ boolean isVector = prop instanceof VectorProperty;
+ if (o == parent || isVector && o != null && ((Vector)o).indexOf(parent) != -1) {
+ if (isVector) {
+ lineage.insertElementAt(parent, 0);
+ }
+
+ lineage.insertElementAt(prop, 0);
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ lineage = null;
+ }
+ }
+
+ parent = p;
+ }
+
+ this.rootWorld = null;
+ if (parent instanceof World) {
+ this.rootWorld = (World)parent;
+ }
+
+ PropTreeNode root = new PropTreeNode(parent);
+ if (lineage != null) {
+ this.tree.change(root, lineage);
+ } else {
+ this.tree.change(root, obj);
+ }
+
+ return true;
+ }
+
+ @Override
+ public void treeFocusChanged(boolean hasFocus) {
+ if (hasFocus) {
+ this.props.deselect(this.props.getSelectedIndex());
+ this.adjustButtons();
+ }
+ }
+
+ @Override
+ public void treeChange(Object obj) {
+ if (obj instanceof Property && !(obj instanceof VectorProperty)) {
+ obj = ((Property)obj).get();
+ }
+
+ this.props.setObject(obj);
+ this.toolbar.setCurrentObject(obj);
+ String name = obj.getClass().getName();
+ int index;
+ if ((index = name.lastIndexOf(46)) != -1) {
+ name = name.substring(index + 1);
+ }
+
+ this.setTitle(name + " " + Console.message("Properties"));
+ this.adjustButtons();
+ }
+
+ private void setTitle(String titleText) {
+ this.titleText = titleText;
+ if (!this.usingTitleAsPrompt) {
+ this.title.setText(titleText);
+ }
+ }
+
+ public void setPrompt(String promptText) {
+ this.title.setText((this.usingTitleAsPrompt = promptText != null) ? promptText : this.titleText);
+ }
+
+ private void adjustButtons() {
+ PropTreeNode e = (PropTreeNode)this.tree.getSelectedNode();
+ if (e != null && this.tree.hasFocus()) {
+ this.editButton.enable(e.canEdit());
+ this.delButton.enable(e.canDelete());
+ this.addButton.enable(e.canAdd());
+ this.helpButton.enable(true);
+ } else {
+ Property p = this.props.getSelectedProperty();
+ if (p != null) {
+ Object obj = p.get();
+ this.editButton.enable(p.getEditor() != null);
+ this.delButton.enable(p.canSetNull() && obj != null);
+ this.addButton.enable(p.canSetNull() && p.getEditor() != null && obj == null);
+ this.helpButton.enable(p.helpExists);
+ } else {
+ this.editButton.disable();
+ this.delButton.disable();
+ this.addButton.disable();
+ this.helpButton.disable();
+ }
+ }
+ }
+
+ @Override
+ public void dialogDisable(boolean disable) {
+ this.isDialogDisabled = disable;
+ this.toolbar.dialogDisable(disable);
+ }
+
+ @Override
+ public boolean handleEvent(java.awt.Event event) {
+ if (event.id == 701) {
+ if (event.target == this.props) {
+ this.tree.setFocus(false);
+ }
+
+ this.adjustButtons();
+ }
+
+ return this.isDialogDisabled ? false : super.handleEvent(event);
+ }
+
+ @Override
+ public boolean action(java.awt.Event event, Object what) {
+ Object target = event.target;
+ if (target == this.delButton) {
+ return this.queue(1);
+ } else if (target == this.addButton) {
+ return this.queue(2);
+ } else if (target != this.editButton && (target != this.props || !this.editButton.isEnabled())) {
+ return target == this.helpButton ? this.queue(11) : false;
+ } else {
+ return this.queue(9);
+ }
+ }
+
+ @Override
+ public void dialogDone(Object who, boolean confirmed) {
+ if (who == this.activePopup) {
+ this.activePopup = null;
+ this.tree.enable();
+ if (confirmed) {
+ Undoable u;
+ Object obj;
+ if (this.isAdd
+ && (u = undoStack.peek()) != this.preAddStackTop
+ && u instanceof UndoablAdd
+ && (obj = ((UndoablAdd)u).getObject()) instanceof Properties) {
+ this.change(obj);
+ } else {
+ this.tree.update();
+ }
+ }
+
+ this.enable();
+ }
+ }
+
+ private boolean doEdit() {
+ Property p = this.props.getSelectedProperty();
+ PropEditor editor;
+ if (p != null && (editor = p.getEditor()) != null) {
+ this.isAdd = false;
+ this.activePopup = editor.edit(this, "Edit " + p.getName());
+ this.tree.disable();
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ private boolean doAdd() {
+ PropTreeNode e = (PropTreeNode)this.tree.getSelectedNode();
+ PropAdder adder;
+ if (e != null && this.tree.hasFocus() && (adder = e.getAdder()) != null) {
+ this.preAddStackTop = undoStack.peek();
+ this.isAdd = true;
+ this.activePopup = adder.add(this, "Add to " + e.getContainerName());
+ this.tree.disable();
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ public void cut() {
+ this.queue(5);
+ }
+
+ public void paste() {
+ this.queue(7);
+ }
+
+ private boolean doPaste() {
+ if (clipboard != null) {
+ SuperRoot obj = clipboard.paste();
+ if (this.drop(obj, null, true)) {
+ return true;
+ }
+
+ clipboard.unPaste(obj);
+ Console.println(Console.message("Clip-contents"));
+ } else {
+ Console.println(Console.message("Clip-empty"));
+ }
+
+ return false;
+ }
+
+ private boolean doHelp() {
+ this.helpAction.showDialog = false;
+ if (this.tree.hasFocus() && this.props.getSelectedProperty() == null) {
+ try {
+ SuperRoot s = (SuperRoot)((PropTreeNode)this.tree.getSelectedNode()).getObject();
+ if (s != null) {
+ this.helpAction.setDestination(s.getHelpURL());
+ }
+ } catch (ClassCastException var5) {
+ Console.println(Console.message("No-help"));
+ }
+ } else {
+ Property p = this.props.getSelectedProperty();
+ if (p != null && p.helpExists) {
+ try {
+ SuperRoot s = (SuperRoot)((PropTreeNode)this.tree.getSelectedNode()).getObject();
+ if (s != null) {
+ this.helpAction.setDestination(s.getHelpURL(p));
+ }
+ } catch (ClassCastException var4) {
+ Console.println(Console.message("No-help"));
+ }
+ }
+ }
+
+ this.helpBrowser = this.helpAction.trigger(null, this.helpBrowser);
+ return true;
+ }
+
+ public void copy() {
+ this.queue(6);
+ }
+
+ private void doCopy() {
+ SuperRoot item = this.getCurSuperRoot(true);
+ if (item != null) {
+ ClipboardEntry newClip = new ClipboardEntry();
+ if (newClip.copy(item)) {
+ this.addUndoable(new UndoabCopy(newClip));
+ }
+ }
+ }
+
+ public boolean save(String fileName) {
+ SuperRoot item = this.getCurSuperRoot(true);
+
+ try {
+ item.saveFile(new URL(URL.getCurDir(), fileName));
+ return true;
+ } catch (IOException var4) {
+ return false;
+ }
+ }
+
+ private SuperRoot getCurSuperRoot(boolean allowContainers) {
+ Object obj = this.props.getObject();
+ return obj instanceof SuperRoot ? (SuperRoot)obj : null;
+ }
+
+ public void addUndoable(Undoable u) {
+ undoStack.push(u);
+ }
+
+ public void addUndoableSet(Property prop, Object obj) {
+ this.addUndoable(new UndoablSet(prop, obj));
+ }
+
+ public void addUndoableAdd(VectorProperty prop, Object obj, boolean changeTree) {
+ this.addUndoable(new UndoablAdd(prop, obj));
+ if (!changeTree) {
+ this.preAddStackTop = undoStack.peek();
+ }
+ }
+
+ public void addUndoablePaste(VectorProperty prop, Object obj) {
+ try {
+ this.addUndoable(new UndoablPaste(prop, clipboard, obj));
+ } catch (Error var4) {
+ Console.println(var4.getMessage());
+ }
+ }
+
+ public void undo() {
+ if (Main.isMainThread()) {
+ this.doUndo();
+ } else {
+ this.queue(8);
+ }
+ }
+
+ private void doUndo() {
+ if (undoStack.undo()) {
+ this.tree.update();
+ }
+ }
+
+ public static void setClipboard(ClipboardEntry clip) {
+ clipboard = clip;
+ }
+
+ public static ClipboardEntry getClipboard() {
+ return clipboard;
+ }
+}
diff --git a/NET/worlds/scape/EnumFieldEditorDialog.java b/NET/worlds/scape/EnumFieldEditorDialog.java
new file mode 100644
index 0000000..0fccdc7
--- /dev/null
+++ b/NET/worlds/scape/EnumFieldEditorDialog.java
@@ -0,0 +1,23 @@
+package NET.worlds.scape;
+
+class EnumFieldEditorDialog extends CheckboxEditorDialog {
+ private Property property;
+ private int[] numbers;
+
+ EnumFieldEditorDialog(EditTile parent, String title, Property property, String[] choices, int[] values) {
+ super(parent, title, choices);
+ this.property = property;
+ this.numbers = values;
+ this.ready();
+ }
+
+ @Override
+ protected int getValue() {
+ return (Integer)this.property.get();
+ }
+
+ @Override
+ protected void setValue(int choice) {
+ this.parent.addUndoableSet(this.property, new Integer(this.numbers[choice]));
+ }
+}
diff --git a/NET/worlds/scape/EnumProperties.java b/NET/worlds/scape/EnumProperties.java
new file mode 100644
index 0000000..a6fbdc9
--- /dev/null
+++ b/NET/worlds/scape/EnumProperties.java
@@ -0,0 +1,46 @@
+package NET.worlds.scape;
+
+import java.util.Enumeration;
+import java.util.NoSuchElementException;
+
+public class EnumProperties implements Enumeration<Object> {
+ private Properties props;
+ private Property next;
+ private int index = 0;
+
+ public EnumProperties(Object obj) {
+ if (obj instanceof Properties) {
+ this.props = (Properties)obj;
+ }
+ }
+
+ @Override
+ public boolean hasMoreElements() {
+ if (this.props != null && this.next == null) {
+ try {
+ this.next = (Property)this.props.properties(this.index++, 0, 0, null);
+
+ assert this.next.index == this.index - 1;
+ } catch (NoSuchPropertyException var2) {
+ }
+ }
+
+ return this.next != null;
+ }
+
+ @Override
+ public Object nextElement() {
+ if (this.hasMoreElements()) {
+ Property var2;
+ try {
+ var2 = this.next;
+ } finally {
+ this.next = null;
+ }
+
+ return var2;
+ } else {
+ throw new NoSuchElementException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/EnumPropertyEditor.java b/NET/worlds/scape/EnumPropertyEditor.java
new file mode 100644
index 0000000..07a363a
--- /dev/null
+++ b/NET/worlds/scape/EnumPropertyEditor.java
@@ -0,0 +1,47 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.PolledDialog;
+
+public class EnumPropertyEditor extends PropEditor {
+ private String[] choices;
+ private int[] numbers;
+
+ private EnumPropertyEditor(Property property, String[] names, int[] values) {
+ super(property);
+
+ assert names != null;
+
+ assert values != null;
+
+ int len = Math.max(names.length, values.length);
+
+ assert len > 1;
+
+ this.choices = new String[len];
+ this.numbers = new int[len];
+
+ for (int i = 0; i < len; i++) {
+ if (i < names.length) {
+ this.choices[i] = names[i];
+ } else {
+ this.choices[i] = names[names.length - 1] + i;
+ }
+
+ if (i < values.length) {
+ this.numbers[i] = values[i];
+ } else {
+ this.numbers[i] = values[values.length - 1] + i - values.length;
+ }
+ }
+ }
+
+ @Override
+ public PolledDialog edit(EditTile parent, String title) {
+ return new EnumFieldEditorDialog(parent, title, this.property, this.choices, this.numbers);
+ }
+
+ public static Property make(Property property, String[] names, int[] values) {
+ property.setPropertyType(5);
+ return property.setEditor(new EnumPropertyEditor(property, names, values));
+ }
+}
diff --git a/NET/worlds/scape/EquipAction.java b/NET/worlds/scape/EquipAction.java
new file mode 100644
index 0000000..b196e1b
--- /dev/null
+++ b/NET/worlds/scape/EquipAction.java
@@ -0,0 +1,35 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import java.io.IOException;
+import java.util.Vector;
+
+public class EquipAction extends Action {
+ private static Object classCookie = new Object();
+
+ @Override
+ public Persister trigger(Event arg, Persister seqID) {
+ Vector equippableItems = InventoryManager.getInventoryManager().getEquippableItems();
+ new Vector();
+ InventoryDialog invDialog = new InventoryDialog(Console.getFrame());
+ invDialog.show();
+ return null;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(0, classCookie);
+ super.saveState(s);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/EquippableItem.java b/NET/worlds/scape/EquippableItem.java
new file mode 100644
index 0000000..c8385b1
--- /dev/null
+++ b/NET/worlds/scape/EquippableItem.java
@@ -0,0 +1,136 @@
+package NET.worlds.scape;
+
+public class EquippableItem extends InventoryItem {
+ private String modelLocation_;
+ private float xPos_;
+ private float yPos_;
+ private float zPos_;
+ private float scale_;
+ private int pitch_;
+ private int roll_;
+ private int yaw_;
+ private Shape shape_;
+ private int bodyLocation_;
+
+ public EquippableItem(String id, String name, int qty, String modelLoc, float scale, int bodyLoc) {
+ super(id, name, qty);
+ this.modelLocation_ = modelLoc;
+ this.scale_ = scale;
+ this.bodyLocation_ = bodyLoc;
+ this.shape_ = null;
+ }
+
+ public EquippableItem(String id, String name, int qty, String modelLoc, float scale, int bodyLoc, float xPos, float yPos, float zPos) {
+ super(id, name, qty);
+ this.modelLocation_ = modelLoc;
+ this.scale_ = scale;
+ this.bodyLocation_ = bodyLoc;
+ this.xPos_ = xPos;
+ this.yPos_ = yPos;
+ this.zPos_ = zPos;
+ this.shape_ = null;
+ }
+
+ public EquippableItem(
+ String id, String name, int qty, String modelLoc, float scale, int bodyLoc, float xPos, float yPos, float zPos, int pitch, int roll, int yaw
+ ) {
+ super(id, name, qty);
+ this.modelLocation_ = modelLoc;
+ this.scale_ = scale;
+ this.bodyLocation_ = bodyLoc;
+ this.xPos_ = xPos;
+ this.yPos_ = yPos;
+ this.zPos_ = zPos;
+ this.pitch_ = pitch;
+ this.roll_ = roll;
+ this.yaw_ = yaw;
+ this.shape_ = null;
+ }
+
+ public EquippableItem(EquippableItem in) {
+ super(in);
+ this.modelLocation_ = in.modelLocation_;
+ this.scale_ = in.scale_;
+ this.bodyLocation_ = in.bodyLocation_;
+ this.xPos_ = in.xPos_;
+ this.yPos_ = in.yPos_;
+ this.zPos_ = in.zPos_;
+ this.pitch_ = in.pitch_;
+ this.roll_ = in.roll_;
+ this.yaw_ = in.yaw_;
+ this.shape_ = null;
+ }
+
+ @Override
+ public InventoryItem cloneItem() {
+ return new EquippableItem(this);
+ }
+
+ public String getModelLocation() {
+ return this.modelLocation_;
+ }
+
+ public void setModelLocation(String loc) {
+ this.modelLocation_ = loc;
+ }
+
+ public int getBodyLocation() {
+ return this.bodyLocation_;
+ }
+
+ public void setBodyLocation(int loc) {
+ this.bodyLocation_ = loc;
+ }
+
+ public float getScale() {
+ return this.scale_;
+ }
+
+ public void setScale(float scale) {
+ this.scale_ = scale;
+ }
+
+ public float getXPos() {
+ return this.xPos_;
+ }
+
+ public float getYPos() {
+ return this.yPos_;
+ }
+
+ public float getZPos() {
+ return this.zPos_;
+ }
+
+ public void setPosition(float xPos, float yPos, float zPos) {
+ this.xPos_ = xPos;
+ this.yPos_ = yPos;
+ this.zPos_ = zPos;
+ }
+
+ public int getPitch() {
+ return this.pitch_;
+ }
+
+ public int getRoll() {
+ return this.roll_;
+ }
+
+ public int getYaw() {
+ return this.yaw_;
+ }
+
+ public void setRotation(int pitch, int roll, int yaw) {
+ this.pitch_ = pitch;
+ this.roll_ = roll;
+ this.yaw_ = yaw;
+ }
+
+ public void setOwnedShape(Shape s) {
+ this.shape_ = s;
+ }
+
+ public Shape getOwnedShape() {
+ return this.shape_;
+ }
+}
diff --git a/NET/worlds/scape/Event.java b/NET/worlds/scape/Event.java
new file mode 100644
index 0000000..69c9c6a
--- /dev/null
+++ b/NET/worlds/scape/Event.java
@@ -0,0 +1,74 @@
+package NET.worlds.scape;
+
+public class Event implements Cloneable {
+ public static final Class eventSuperclass = new Object().getClass();
+ public int time;
+ public Object source;
+ public WObject target;
+ public WObject receiver;
+
+ public Event(int time, Object source, WObject target) {
+ this.time = time;
+ this.source = source;
+ this.target = target;
+ }
+
+ @Override
+ public Object clone() {
+ try {
+ return super.clone();
+ } catch (CloneNotSupportedException var2) {
+ System.out.println("Clone of Object not supported!");
+ return null;
+ }
+ }
+
+ public boolean isA(Class c) {
+ for (Class t = this.getClass(); t != eventSuperclass; t = t.getSuperclass()) {
+ if (t == c) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public boolean deliver(Object o) {
+ return o instanceof Handler && ((Handler)o).handle(this);
+ }
+
+ @Override
+ public String toString() {
+ String result = "Event at " + this.time;
+ String sname = null;
+ if (this.source instanceof SuperRoot) {
+ sname = ((SuperRoot)this.source).getName();
+ } else if (this.source != null) {
+ sname = this.source.toString();
+ }
+
+ if (sname != null) {
+ result = result + " from " + sname;
+ }
+
+ String tname = null;
+ if (this.target != null) {
+ this.target.getName();
+ }
+
+ if (tname != null) {
+ result = result + " to " + tname;
+ }
+
+ String rname = null;
+ if (this.receiver != null) {
+ this.receiver.getName();
+ }
+
+ if (rname != null) {
+ result = result + " handled by " + rname;
+ }
+
+ return result;
+ }
+}
diff --git a/NET/worlds/scape/EventQueue.java b/NET/worlds/scape/EventQueue.java
new file mode 100644
index 0000000..83008d3
--- /dev/null
+++ b/NET/worlds/scape/EventQueue.java
@@ -0,0 +1,125 @@
+package NET.worlds.scape;
+
+import NET.worlds.core.Std;
+
+public class EventQueue {
+ private static final int keyDown = 1;
+ private static final int keyUp = 2;
+ private static final int keyChar = 3;
+ private static final int mouseDown = 4;
+ private static final int mouseUp = 5;
+ private static final int mouseMove = 6;
+ private static final int mouseDelta = 7;
+ private static final int mouseEnter = 8;
+ private static final int mouseExit = 9;
+ private static final int teleport = 10;
+ private char key;
+ private int type;
+ private int time;
+ private int x;
+ private int y;
+ private static EventQueue dequeueInfo = new EventQueue();
+
+ static {
+ nativeInit();
+ }
+
+ public static void pollForEvents(Camera eventEater) {
+ if (eventEater != null) {
+ int eventCount = getEventCount();
+
+ Event e;
+ while (eventCount-- > 0 && (e = dequeueInfo.dequeue()) != null) {
+ if (e.target == null) {
+ e.target = eventEater;
+ }
+
+ eventEater.deliver(e);
+ }
+ }
+ }
+
+ public static boolean redirectDrivingKeys(java.awt.Event e) {
+ boolean press;
+ if (!(press = e.id == 403) && e.id != 404) {
+ return false;
+ } else {
+ char newKey;
+ switch (e.key) {
+ case 27:
+ newKey = '\ue31b';
+ break;
+ case 1000:
+ newKey = '\ue324';
+ break;
+ case 1001:
+ newKey = '\ue323';
+ break;
+ case 1002:
+ newKey = '\ue321';
+ break;
+ case 1003:
+ newKey = '\ue322';
+ break;
+ case 1004:
+ newKey = '\ue326';
+ break;
+ case 1005:
+ newKey = '\ue328';
+ break;
+ case 1006:
+ newKey = '\ue325';
+ break;
+ case 1007:
+ newKey = '\ue327';
+ break;
+ default:
+ return false;
+ }
+
+ addEvent(newKey, press ? 1 : 2, Std.getTimeZero() + Std.getRealTime(), e.x, e.y);
+ return true;
+ }
+ }
+
+ private EventQueue() {
+ }
+
+ private Event dequeue() {
+ if (this.getNextEvent()) {
+ this.time = this.time - Std.getTimeZero();
+ switch (this.type) {
+ case 1:
+ return new KeyDownEvent(this.time, null, this.key);
+ case 2:
+ return new KeyUpEvent(this.time, null, this.key);
+ case 3:
+ return new KeyCharEvent(this.time, null, this.key);
+ case 4:
+ return new MouseDownEvent(this.time, null, this.key, this.x, this.y);
+ case 5:
+ return new MouseUpEvent(this.time, null, this.key, this.x, this.y);
+ case 6:
+ return new MouseMoveEvent(this.time, null, this.x, this.y);
+ case 7:
+ return new MouseDeltaEvent(this.time, null, this.x, this.y);
+ case 8:
+ return new MouseEnterEvent(this.time, null, this.x, this.y);
+ case 9:
+ return new MouseExitEvent(this.time, null, this.x, this.y);
+ default:
+ throw new Error("Illegal internal event type");
+ }
+ } else {
+ return null;
+ }
+ }
+
+ public static native void nativeInit();
+
+ private native boolean getNextEvent();
+
+ private static native int getEventCount();
+
+ private static native void addEvent(char var0, int var1, int var2, int var3, int var4);
+}
diff --git a/NET/worlds/scape/ExtensionFilter.java b/NET/worlds/scape/ExtensionFilter.java
new file mode 100644
index 0000000..b02bcfc
--- /dev/null
+++ b/NET/worlds/scape/ExtensionFilter.java
@@ -0,0 +1,17 @@
+package NET.worlds.scape;
+
+import java.io.File;
+import java.io.FilenameFilter;
+
+public class ExtensionFilter implements FilenameFilter {
+ private String _ext;
+
+ public ExtensionFilter(String ext) {
+ this._ext = ext;
+ }
+
+ @Override
+ public boolean accept(File dir, String name) {
+ return name.endsWith(this._ext);
+ }
+}
diff --git a/NET/worlds/scape/Facer.java b/NET/worlds/scape/Facer.java
new file mode 100644
index 0000000..913fc96
--- /dev/null
+++ b/NET/worlds/scape/Facer.java
@@ -0,0 +1,14 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+class Facer extends SwitchableBehavior {
+ @Override
+ public void saveState(Saver s) throws IOException {
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException {
+ System.out.println("WARNING! Facers are obsolete. Use 1-image Holograms instead.");
+ }
+}
diff --git a/NET/worlds/scape/FieldEditorDialog.java b/NET/worlds/scape/FieldEditorDialog.java
new file mode 100644
index 0000000..04e496c
--- /dev/null
+++ b/NET/worlds/scape/FieldEditorDialog.java
@@ -0,0 +1,47 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.OkCancelDialog;
+import java.awt.Font;
+import java.awt.GridBagConstraints;
+import java.awt.TextField;
+
+public abstract class FieldEditorDialog extends OkCancelDialog {
+ private TextField strField = new TextField(40);
+ protected EditTile parent;
+ private static Font font = new Font(Console.message("GammaTextFont"), 0, 12);
+
+ protected FieldEditorDialog(EditTile parent, String title) {
+ super(Console.getFrame(), parent, title);
+ this.parent = parent;
+ }
+
+ @Override
+ protected void build() {
+ GridBagConstraints c = new GridBagConstraints();
+ c.fill = 2;
+ c.weightx = 1.0;
+ c.weighty = 1.0;
+ c.gridwidth = 0;
+ this.strField.setFont(font);
+ this.add(this.gbag, this.strField, c);
+ super.build();
+ }
+
+ protected abstract String getValue();
+
+ protected abstract boolean setValue(String var1);
+
+ @Override
+ protected boolean setValue() {
+ return this.setValue(this.strField.getText().trim());
+ }
+
+ @Override
+ public void show() {
+ super.show();
+ this.strField.setText(this.getValue());
+ this.strField.requestFocus();
+ this.strField.selectAll();
+ }
+}
diff --git a/NET/worlds/scape/FieldWithListEditorDialog.java b/NET/worlds/scape/FieldWithListEditorDialog.java
new file mode 100644
index 0000000..26c0a37
--- /dev/null
+++ b/NET/worlds/scape/FieldWithListEditorDialog.java
@@ -0,0 +1,83 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.OkCancelDialog;
+import java.awt.Font;
+import java.awt.GridBagConstraints;
+import java.awt.List;
+import java.awt.TextField;
+import java.util.Enumeration;
+import java.util.Vector;
+
+public abstract class FieldWithListEditorDialog extends OkCancelDialog {
+ private TextField strField = new TextField(40);
+ private List list = new List();
+ private Vector choices;
+ protected EditTile parent;
+ private static Font font = new Font(Console.message("GammaTextFont"), 0, 12);
+
+ protected FieldWithListEditorDialog(EditTile parent, String title, Vector choices) {
+ super(Console.getFrame(), parent, title);
+ this.choices = choices;
+ this.parent = parent;
+ }
+
+ @Override
+ protected void build() {
+ Enumeration e = this.choices.elements();
+
+ while (e.hasMoreElements()) {
+ this.list.addItem((String)e.nextElement());
+ }
+
+ GridBagConstraints c = new GridBagConstraints();
+ c.fill = 2;
+ c.weightx = 0.0;
+ c.weighty = 0.0;
+ c.gridwidth = 0;
+ this.strField.setFont(font);
+ this.add(this.gbag, this.strField, c);
+ c.fill = 1;
+ c.weightx = 1.0;
+ c.weighty = 1.0;
+ c.gridheight = 6;
+ this.add(this.gbag, this.list, c);
+ super.build();
+ }
+
+ @Override
+ public boolean handleEvent(java.awt.Event event) {
+ if (event.id == 701) {
+ this.strField.setText(this.list.getSelectedItem());
+ this.strField.selectAll();
+ }
+
+ return super.handleEvent(event);
+ }
+
+ @Override
+ public boolean action(java.awt.Event event, Object what) {
+ if (event.target == this.list) {
+ event.target = this.okButton;
+ }
+
+ return super.action(event, what);
+ }
+
+ protected abstract String getValue();
+
+ protected abstract boolean setValue(String var1);
+
+ @Override
+ protected boolean setValue() {
+ return this.setValue(this.strField.getText().trim());
+ }
+
+ @Override
+ public void show() {
+ super.show();
+ this.strField.setText(this.getValue());
+ this.strField.requestFocus();
+ this.strField.selectAll();
+ }
+}
diff --git a/NET/worlds/scape/FileList.java b/NET/worlds/scape/FileList.java
new file mode 100644
index 0000000..c7c8a24
--- /dev/null
+++ b/NET/worlds/scape/FileList.java
@@ -0,0 +1,132 @@
+package NET.worlds.scape;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.util.Enumeration;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+public class FileList implements FilenameFilter {
+ private String dirList;
+ private String extList;
+ private Vector<String> exts;
+ private boolean keepPathInfo;
+ private boolean sort = true;
+
+ public FileList(String dirList, String extList) {
+ this.dirList = dirList;
+ this.extList = extList;
+ }
+
+ public String getExtList() {
+ return this.extList;
+ }
+
+ private static Vector<String> breakUp(String list) {
+ StringTokenizer t = new StringTokenizer(list, File.pathSeparator, false);
+ Vector<String> v = new Vector<String>();
+
+ while (t.hasMoreTokens()) {
+ v.addElement(t.nextToken());
+ }
+
+ return v;
+ }
+
+ @Override
+ public boolean accept(File dir, String name) {
+ return extMatches(name, this.exts);
+ }
+
+ public static boolean extMatches(String name, Vector<String> exts) {
+ int index = name.lastIndexOf(".");
+ if (index != -1) {
+ String ext = name.substring(index + 1);
+ Enumeration<String> e = exts.elements();
+
+ while (e.hasMoreElements()) {
+ if (ext.equalsIgnoreCase(e.nextElement())) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ public static boolean extMatches(String name, String exts) {
+ return extMatches(name, breakUp(exts));
+ }
+
+ public boolean extMatches(String name) {
+ return extMatches(name, this.extList);
+ }
+
+ public FileList keepPathInfo() {
+ this.keepPathInfo = true;
+ return this;
+ }
+
+ public FileList dontSort() {
+ this.sort = false;
+ return this;
+ }
+
+ public static String removeTrailingSlash(String dir) {
+ if (dir != null) {
+ int len = dir.length();
+ if (len > 0) {
+ char c = dir.charAt(len - 1);
+ if (c == '/' || c == '\\') {
+ dir = dir.substring(0, len - 1);
+ }
+ }
+ }
+
+ return dir;
+ }
+
+ public Vector<String> getList() {
+ this.exts = breakUp(this.extList);
+ Vector<String> dirs = breakUp(this.dirList);
+ Vector<String> v = new Vector<String>();
+ Enumeration<String> edirs = dirs.elements();
+
+ while (edirs.hasMoreElements()) {
+ String dir = removeTrailingSlash(edirs.nextElement());
+ File f = new File(dir);
+ if (f.exists()) {
+ String[] list = f.list(this);
+ if (this.keepPathInfo && !dir.equals(".")) {
+ dir = dir + File.separator;
+ } else {
+ dir = "";
+ }
+
+ for (int i = 0; i < list.length; i++) {
+ String name = dir + list[i];
+ if (!this.sort) {
+ v.addElement(name);
+ } else {
+ int count = v.size();
+ String lname = name.toLowerCase();
+
+ int j;
+ for (j = 0; j < count; j++) {
+ if (lname.compareTo(v.elementAt(j).toLowerCase()) < 0) {
+ v.insertElementAt(name, j);
+ break;
+ }
+ }
+
+ if (j == count) {
+ v.addElement(name);
+ }
+ }
+ }
+ }
+ }
+
+ return v;
+ }
+}
diff --git a/NET/worlds/scape/FileTexture.java b/NET/worlds/scape/FileTexture.java
new file mode 100644
index 0000000..52a3441
--- /dev/null
+++ b/NET/worlds/scape/FileTexture.java
@@ -0,0 +1,50 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+public class FileTexture extends Texture implements Persister {
+ private String _urlName;
+ private static Object classCookie = new Object();
+
+ static {
+ nativeInit();
+ }
+
+ public FileTexture(String urlName, String filename) {
+ this.makeTexture(urlName, filename);
+ }
+
+ protected FileTexture() {
+ }
+
+ public static native void nativeInit();
+
+ public static native FileTexture dictLookup(String var0);
+
+ private native void makeTexture(String var1, String var2);
+
+ @Override
+ public String getName() {
+ return this._urlName;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(0, classCookie);
+ super.saveState(s);
+ s.saveString(this._urlName);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ String name = r.restoreString();
+ this.makeTexture(name, name);
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/FileTextureDecoder.java b/NET/worlds/scape/FileTextureDecoder.java
new file mode 100644
index 0000000..6f226a4
--- /dev/null
+++ b/NET/worlds/scape/FileTextureDecoder.java
@@ -0,0 +1,15 @@
+package NET.worlds.scape;
+
+class FileTextureDecoder extends TextureDecoder {
+ private String exts = "bmp;ras";
+
+ @Override
+ protected String getExts() {
+ return this.exts;
+ }
+
+ @Override
+ protected Texture read(String urlName, String filename) {
+ return new FileTexture(urlName, filename);
+ }
+}
diff --git a/NET/worlds/scape/FloatArrayEditorDialog.java b/NET/worlds/scape/FloatArrayEditorDialog.java
new file mode 100644
index 0000000..4172da1
--- /dev/null
+++ b/NET/worlds/scape/FloatArrayEditorDialog.java
@@ -0,0 +1,50 @@
+package NET.worlds.scape;
+
+import java.util.StringTokenizer;
+
+class FloatArrayEditorDialog extends ListEditorDialog {
+ protected Property property;
+ protected float[] arr;
+
+ FloatArrayEditorDialog(EditTile parent, String title, Property property) {
+ super(parent, title);
+ this.property = property;
+ this.ready();
+ }
+
+ @Override
+ protected void build() {
+ this.arr = (float[])this.property.get();
+ super.build();
+ }
+
+ @Override
+ protected int getElementCount() {
+ return this.arr.length;
+ }
+
+ @Override
+ protected String getElement(int index) {
+ return "" + this.arr[index];
+ }
+
+ @Override
+ protected boolean setElements(StringTokenizer e) {
+ int count = 0;
+
+ while (e.hasMoreTokens()) {
+ try {
+ this.arr[count++] = Float.valueOf(e.nextToken());
+ } catch (Exception var4) {
+ return false;
+ }
+ }
+
+ if (count == this.arr.length) {
+ this.parent.addUndoableSet(this.property, this.arr);
+ return true;
+ } else {
+ return false;
+ }
+ }
+}
diff --git a/NET/worlds/scape/FloatArrayPropertyEditor.java b/NET/worlds/scape/FloatArrayPropertyEditor.java
new file mode 100644
index 0000000..49de010
--- /dev/null
+++ b/NET/worlds/scape/FloatArrayPropertyEditor.java
@@ -0,0 +1,19 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.PolledDialog;
+
+public class FloatArrayPropertyEditor extends PropEditor {
+ private FloatArrayPropertyEditor(Property property) {
+ super(property);
+ }
+
+ @Override
+ public PolledDialog edit(EditTile parent, String title) {
+ return new FloatArrayEditorDialog(parent, title, this.property);
+ }
+
+ public static Property make(Property property) {
+ property.setPropertyType(6);
+ return property.setEditor(new FloatArrayPropertyEditor(property));
+ }
+}
diff --git a/NET/worlds/scape/FloatFieldEditorDialog.java b/NET/worlds/scape/FloatFieldEditorDialog.java
new file mode 100644
index 0000000..7ad36cc
--- /dev/null
+++ b/NET/worlds/scape/FloatFieldEditorDialog.java
@@ -0,0 +1,34 @@
+package NET.worlds.scape;
+
+class FloatFieldEditorDialog extends FieldEditorDialog {
+ Property property;
+ FloatPropertyEditor limits;
+
+ FloatFieldEditorDialog(EditTile parent, String title, Property property, FloatPropertyEditor limits) {
+ super(parent, title);
+ this.property = property;
+ this.limits = limits;
+ this.ready();
+ }
+
+ @Override
+ protected String getValue() {
+ return "" + this.property.get();
+ }
+
+ @Override
+ protected boolean setValue(String text) {
+ if (text.length() != 0) {
+ try {
+ Float val = Float.valueOf(text);
+ if (!this.limits.rangeLimits || val >= this.limits.minVal && val <= this.limits.maxVal) {
+ this.parent.addUndoableSet(this.property, val);
+ return true;
+ }
+ } catch (NumberFormatException var3) {
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/NET/worlds/scape/FloatPropertyEditor.java b/NET/worlds/scape/FloatPropertyEditor.java
new file mode 100644
index 0000000..90a6099
--- /dev/null
+++ b/NET/worlds/scape/FloatPropertyEditor.java
@@ -0,0 +1,35 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.PolledDialog;
+
+public class FloatPropertyEditor extends PropEditor {
+ boolean rangeLimits = false;
+ float minVal;
+ float maxVal;
+
+ private FloatPropertyEditor(Property property) {
+ super(property);
+ }
+
+ private FloatPropertyEditor(Property property, float minVal, float maxVal) {
+ super(property);
+ this.rangeLimits = true;
+ this.minVal = minVal;
+ this.maxVal = maxVal;
+ }
+
+ @Override
+ public PolledDialog edit(EditTile parent, String title) {
+ return new FloatFieldEditorDialog(parent, title, this.property, this);
+ }
+
+ public static Property make(Property property) {
+ property.setPropertyType(2);
+ return property.setEditor(new FloatPropertyEditor(property));
+ }
+
+ public static Property make(Property property, float minVal, float maxVal) {
+ property.setPropertyType(2);
+ return property.setEditor(new FloatPropertyEditor(property, minVal, maxVal));
+ }
+}
diff --git a/NET/worlds/scape/FloorPatch.java b/NET/worlds/scape/FloorPatch.java
new file mode 100644
index 0000000..3c3795e
--- /dev/null
+++ b/NET/worlds/scape/FloorPatch.java
@@ -0,0 +1,9 @@
+package NET.worlds.scape;
+
+public interface FloorPatch {
+ boolean inPatch(float var1, float var2);
+
+ float floorHeight(float var1, float var2);
+
+ Point3 surfaceNormal(float var1, float var2);
+}
diff --git a/NET/worlds/scape/ForwardAttribute.java b/NET/worlds/scape/ForwardAttribute.java
new file mode 100644
index 0000000..fd2a830
--- /dev/null
+++ b/NET/worlds/scape/ForwardAttribute.java
@@ -0,0 +1,61 @@
+package NET.worlds.scape;
+
+import NET.worlds.core.Std;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class ForwardAttribute extends Attribute implements NonPersister {
+ private Attribute _from;
+
+ ForwardAttribute(Attribute forwarder, int attrID) {
+ super(attrID);
+ this._from = forwarder;
+ }
+
+ @Override
+ protected void noteAddingTo(SuperRoot owner) {
+ WObject w = (WObject)owner.getOwner();
+ if ((w.getSharer().getMode() & 1) != 0) {
+ throw new ClassCastException("Must forward to unforwarded object");
+ }
+ }
+
+ @Override
+ public void detach() {
+ super.detach();
+ this._from.unforward();
+ }
+
+ @Override
+ public int getFlags() {
+ return this._from.getFlags();
+ }
+
+ @Override
+ public void setFlag(int flag, boolean onoff) {
+ this._from.setFlag(flag, onoff);
+ }
+
+ @Override
+ public void generateNetData(DataOutputStream s) throws IOException {
+ this._from.generateNetData(s);
+ }
+
+ @Override
+ public void setFromNetData(DataInputStream ds, int len) throws IOException {
+ this._from.setFromNetData(ds, len);
+ ValueEvent e = new ValueEvent(Std.getFastTime(), this._from.getOwner(), (WObject)this._from.getOwner().getOwner(), this._from);
+ this._from.trigger(e);
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + "[forwarded from " + this._from.getName() + "]";
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ assert false;
+ }
+}
diff --git a/NET/worlds/scape/FrameEvent.java b/NET/worlds/scape/FrameEvent.java
new file mode 100644
index 0000000..c4e6131
--- /dev/null
+++ b/NET/worlds/scape/FrameEvent.java
@@ -0,0 +1,44 @@
+package NET.worlds.scape;
+
+import NET.worlds.core.Std;
+
+public class FrameEvent extends Event {
+ private static int lastFrameTime;
+ private static int deltaFrameTime;
+ public int dt;
+
+ public FrameEvent(WObject target) {
+ super(lastFrameTime, null, target);
+ this.dt = deltaFrameTime;
+ }
+
+ public FrameEvent(WObject source, WObject target) {
+ super(lastFrameTime, source, target);
+ this.dt = deltaFrameTime;
+ }
+
+ public void newFrameTime() {
+ this.time = Std.getRealTime();
+ if (lastFrameTime == 0) {
+ deltaFrameTime = 0;
+ } else {
+ deltaFrameTime = this.time - lastFrameTime;
+
+ assert this.time >= lastFrameTime && deltaFrameTime >= 0;
+ }
+
+ lastFrameTime = this.time;
+ this.dt = deltaFrameTime;
+ }
+
+ @Override
+ public boolean deliver(Object o) {
+ return o instanceof FrameHandler && ((FrameHandler)o).handle(this) ? true : true;
+ }
+
+ public void retargetAndDeliver(FrameHandler h, WObject o) {
+ this.target = o;
+ this.receiver = o;
+ h.handle(this);
+ }
+}
diff --git a/NET/worlds/scape/FrameHandler.java b/NET/worlds/scape/FrameHandler.java
new file mode 100644
index 0000000..bf4f38f
--- /dev/null
+++ b/NET/worlds/scape/FrameHandler.java
@@ -0,0 +1,5 @@
+package NET.worlds.scape;
+
+public interface FrameHandler {
+ boolean handle(FrameEvent var1);
+}
diff --git a/NET/worlds/scape/FrameSensor.java b/NET/worlds/scape/FrameSensor.java
new file mode 100644
index 0000000..47c57d7
--- /dev/null
+++ b/NET/worlds/scape/FrameSensor.java
@@ -0,0 +1,18 @@
+package NET.worlds.scape;
+
+public class FrameSensor extends Sensor implements FrameHandler {
+ public FrameSensor(Action a) {
+ if (a != null) {
+ this.addAction(a);
+ }
+ }
+
+ public FrameSensor() {
+ }
+
+ @Override
+ public boolean handle(FrameEvent e) {
+ this.trigger(e);
+ return true;
+ }
+}
diff --git a/NET/worlds/scape/GravityAction.java b/NET/worlds/scape/GravityAction.java
new file mode 100644
index 0000000..f77e645
--- /dev/null
+++ b/NET/worlds/scape/GravityAction.java
@@ -0,0 +1,189 @@
+package NET.worlds.scape;
+
+import NET.worlds.core.Std;
+import java.io.IOException;
+
+public class GravityAction extends Action {
+ public float cycleTime = 0.0F;
+ int startTime;
+ public int force = 300;
+ public float xDest = 0.0F;
+ public float yDest = 0.0F;
+ public float zDest = 0.0F;
+ static final float epsilon = 2.0F;
+ int lastFrameTime;
+ float initialDistance = 0.0F;
+ Point3 initialPoint;
+ protected boolean gravityEnd = true;
+ private static Object classCookie = new Object();
+
+ public void startGravity() {
+ this.startTime = Std.getRealTime();
+ this.gravityEnd = false;
+ this.lastFrameTime = 0;
+ }
+
+ private float distance(float tx, float ty, float tz, float cx, float cy, float cz) {
+ float dx = tx - cx;
+ float dy = ty - cy;
+ float dz = tz - cz;
+ return (float)Math.sqrt(dx * dx + dy * dy + dz * dz);
+ }
+
+ public void doGravity(Pilot pilotObject, WObject o) {
+ int currentFrameTime = Std.getRealTime();
+ float r = this.distance(pilotObject.getX(), pilotObject.getY(), pilotObject.getZ(), o.getX(), o.getY(), o.getZ());
+ if (this.lastFrameTime == 0) {
+ this.lastFrameTime = currentFrameTime;
+ }
+
+ float distanceTraveled = this.distance(
+ this.initialPoint.x, this.initialPoint.y, this.initialPoint.z, pilotObject.getX(), pilotObject.getY(), pilotObject.getZ()
+ );
+ this.initialDistance = this.distance(this.initialPoint.x, this.initialPoint.y, this.initialPoint.z, o.getX(), o.getY(), o.getZ());
+ if (r > 2.0F && distanceTraveled <= this.initialDistance) {
+ float dx = o.getX() - pilotObject.getX();
+ if (dx != 0.0) {
+ float new_dx = (currentFrameTime - this.lastFrameTime) * this.force * dx / (r * r);
+ if (Math.abs(new_dx) < Math.abs(dx)) {
+ dx = new_dx;
+ }
+ }
+
+ float dy = o.getY() - pilotObject.getY();
+ if (dy != 0.0) {
+ float new_dy = (currentFrameTime - this.lastFrameTime) * this.force * dy / (r * r);
+ if (Math.abs(new_dy) < Math.abs(dy)) {
+ dy = new_dy;
+ }
+ }
+
+ float dz = o.getZ() - pilotObject.getZ();
+ if (dz != 0.0) {
+ float new_dz = (currentFrameTime - this.lastFrameTime) * this.force * dz / (r * r);
+ if (Math.abs(new_dz) < Math.abs(dz)) {
+ dz = new_dz;
+ }
+ }
+
+ pilotObject.moveBy(dx, dy, dz);
+ } else {
+ pilotObject.moveTo(o.getX(), o.getY(), o.getZ());
+ this.gravityEnd = true;
+ }
+
+ this.lastFrameTime = currentFrameTime;
+ }
+
+ @Override
+ public Persister trigger(Event e, Persister seqID) {
+ Object owner = this.getOwner();
+ if (owner != null && owner instanceof WObject) {
+ WObject o = (WObject)owner;
+ Pilot pilot = Pilot.getActive();
+ if (pilot == null) {
+ return null;
+ } else if (pilot.getRoom() != o.getRoom()) {
+ if (this.gravityEnd && pilot instanceof HoloPilot) {
+ HoloPilot hp = (HoloPilot)pilot;
+ hp.returnSmoothDriver();
+ }
+
+ return null;
+ } else {
+ if (this.gravityEnd) {
+ this.startGravity();
+ if (pilot instanceof HoloPilot) {
+ HoloPilot hp = (HoloPilot)pilot;
+ hp.removeSmoothDriver();
+ this.initialPoint = new Point3(pilot.getPosition());
+ this.initialDistance = this.distance(this.initialPoint.x, this.initialPoint.y, this.initialPoint.z, o.getX(), o.getY(), o.getZ());
+ }
+ }
+
+ this.doGravity(pilot, o);
+ if (this.gravityEnd) {
+ if (pilot instanceof HoloPilot) {
+ HoloPilot hp = (HoloPilot)pilot;
+ hp.returnSmoothDriver();
+ }
+
+ return null;
+ } else {
+ return this;
+ }
+ }
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = IntegerPropertyEditor.make(new Property(this, index, "Force"));
+ } else if (mode == 1) {
+ ret = new Integer(this.force);
+ } else if (mode == 2) {
+ this.force = (Integer)value;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 1, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + "[Force " + this.force + "]";
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(4, classCookie);
+ super.saveState(s);
+ s.saveInt(this.force);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ r.restore();
+ this.cycleTime = r.restoreFloat();
+ this.force = r.restoreInt();
+ break;
+ case 1:
+ super.restoreState(r);
+ this.cycleTime = r.restoreFloat();
+ this.force = r.restoreInt();
+ break;
+ case 2:
+ super.restoreState(r);
+ this.cycleTime = r.restoreFloat();
+ this.force = r.restoreInt();
+ this.xDest = r.restoreFloat();
+ this.yDest = r.restoreFloat();
+ break;
+ case 3:
+ super.restoreState(r);
+ this.force = r.restoreInt();
+ this.xDest = r.restoreFloat();
+ this.yDest = r.restoreFloat();
+ this.zDest = r.restoreFloat();
+ break;
+ case 4:
+ super.restoreState(r);
+ this.force = r.restoreInt();
+ break;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/HTransWidget.java b/NET/worlds/scape/HTransWidget.java
new file mode 100644
index 0000000..51aae9e
--- /dev/null
+++ b/NET/worlds/scape/HTransWidget.java
@@ -0,0 +1,20 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.SnapTool;
+
+class HTransWidget extends WidgetButton {
+ public HTransWidget(ToolBar toolbar) {
+ super(toolbar, "htrans.gif", Console.message("Move-horiz"));
+ }
+
+ @Override
+ public String drag(boolean initialDrag, float deltax, float deltay) {
+ Transform t = Transform.make();
+ this.applyWorldTransform(
+ initialDrag, t.moveBy(SnapTool.snapTool().snapTo(this.getWorldAxis(1, 0, 0).times(deltax).plus(this.getWorldAxis(0, 1, 0).times(deltay))))
+ );
+ t.recycle();
+ return "" + this.getWObject().getPosition();
+ }
+}
diff --git a/NET/worlds/scape/Handler.java b/NET/worlds/scape/Handler.java
new file mode 100644
index 0000000..9a2a725
--- /dev/null
+++ b/NET/worlds/scape/Handler.java
@@ -0,0 +1,5 @@
+package NET.worlds.scape;
+
+public interface Handler {
+ boolean handle(Event var1);
+}
diff --git a/NET/worlds/scape/HandsOffDriver.java b/NET/worlds/scape/HandsOffDriver.java
new file mode 100644
index 0000000..ede28ae
--- /dev/null
+++ b/NET/worlds/scape/HandsOffDriver.java
@@ -0,0 +1,175 @@
+package NET.worlds.scape;
+
+public class HandsOffDriver extends SwitchableBehavior implements FrameHandler, AnimatedActionHandler, KeyDownHandler, KeyUpHandler {
+ Point2 _destPoint;
+ float _destYaw;
+ float _velocity;
+ int _lastFrameTime = 0;
+ AnimatedActionHandlerImp handler;
+ int _state = 0;
+ Transform target = null;
+ float cameraPan = 0.0F;
+ float cameraZoom = 0.0F;
+ int cameraPanning = 0;
+ int cameraZooming = 0;
+ static final float cameraPanRate = 45.0F;
+ static final float cameraZoomRate = 100.0F;
+ static final int noState = 0;
+ static final int turnToDestination = 1;
+ static final int moveToDestination = 2;
+ static final int faceDestination = 3;
+
+ public HandsOffDriver() {
+ this.handler = new AnimatedActionHandlerImp();
+ }
+
+ public float getCameraPan() {
+ return this.cameraPan;
+ }
+
+ public float getCameraZoom() {
+ return this.cameraZoom;
+ }
+
+ public void setTarget(Transform t) {
+ this.target = t;
+ }
+
+ @Override
+ public void addCallback(AnimatedActionCallback c) {
+ this.handler.addCallback(c);
+ }
+
+ @Override
+ public void removeCallback(AnimatedActionCallback c) {
+ this.handler.removeCallback(c);
+ }
+
+ @Override
+ public void notifyCallbacks(int completionCode) {
+ this.handler.notifyCallbacks(completionCode);
+ }
+
+ public void setDestPos(Point2 point, float yaw, float velocity) {
+ if (point == null) {
+ System.out.println("Point is null");
+ }
+
+ this._destPoint = point;
+ this._destYaw = yaw;
+ this._velocity = velocity;
+ this._state = 1;
+ }
+
+ @Override
+ public boolean handle(FrameEvent e) {
+ int now = e.time;
+ float dt = (now - this._lastFrameTime) / 1000.0F;
+ this._lastFrameTime = now;
+ this.cameraZoom = this.cameraZoom + dt * 100.0F * this.cameraZooming;
+ this.cameraPan = this.cameraPan + dt * 45.0F * this.cameraPanning;
+ Transform tgt;
+ if (this.target == null) {
+ if (!(e.receiver instanceof Pilot)) {
+ System.out.println("Receiver not pilot...");
+ return true;
+ }
+
+ Pilot pilot = (Pilot)e.receiver;
+ if (!pilot.isActive()) {
+ System.out.println("Pilot not active...");
+ return true;
+ }
+
+ tgt = pilot;
+ } else {
+ tgt = this.target;
+ }
+
+ if (dt <= 0.0F) {
+ System.out.println("Negative dt");
+ return true;
+ } else {
+ if (dt > 0.33F) {
+ dt = 0.33F;
+ }
+
+ this.moveObject(tgt, dt);
+ return true;
+ }
+ }
+
+ private void yawLevel(Transform pilot, float theta) {
+ float currentYaw = pilot.getYaw();
+ Point3Temp currentSpinAxis = Point3Temp.make();
+ float currentSpin = pilot.getSpin(currentSpinAxis);
+ Point3Temp currentPosition = pilot.getPosition();
+ pilot.makeIdentity().moveTo(currentPosition).yaw(-theta);
+ pilot.yaw(currentYaw);
+ pilot.spin(currentSpinAxis, currentSpin);
+ }
+
+ private void moveObject(Transform pilot, float dt) {
+ if (pilot != null && this._destPoint != null) {
+ switch (this._state) {
+ case 1: {
+ Point3Temp dest = Point3Temp.make(this._destPoint.x, this._destPoint.y, pilot.getZ());
+ Point3Temp src = pilot.getPosition();
+ double destYaw = Math.atan2(dest.y - src.y, dest.x - src.x);
+ destYaw = (Math.PI / 2) - destYaw;
+ destYaw *= 180.0 / Math.PI;
+ this.yawLevel(pilot, (float)destYaw);
+ this._state = 2;
+ break;
+ }
+ case 2: {
+ Point3Temp dest = Point3Temp.make(this._destPoint.x, this._destPoint.y, pilot.getZ());
+ Point3Temp pos = pilot.getPosition();
+ float cm = dt * this._velocity;
+ Point3Temp dP = Point3Temp.make(dest);
+ dP.minus(pilot.getPosition());
+ if (dP.length() <= cm) {
+ pilot.moveTo(dest);
+ this._state = 3;
+ } else {
+ dP.normalize();
+ pilot.moveBy(dP.times(cm));
+ }
+ break;
+ }
+ case 3:
+ this.yawLevel(pilot, this._destYaw);
+ this._state = 0;
+ this.notifyCallbacks(0);
+ }
+ }
+ }
+
+ @Override
+ public boolean handle(KeyDownEvent e) {
+ if (e.key == '\ue326') {
+ this.cameraZooming = -1;
+ } else if (e.key == '\ue328') {
+ this.cameraZooming = 1;
+ } else if (e.key == '\ue325') {
+ this.cameraPanning = -1;
+ } else if (e.key == '\ue327') {
+ this.cameraPanning = 1;
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean handle(KeyUpEvent e) {
+ if (e.key == '\ue326' || e.key == '\ue328') {
+ this.cameraZooming = 0;
+ } else if (e.key == '\ue325' || e.key == '\ue327') {
+ this.cameraPanning = 0;
+ } else if (e.key == '\ue31b') {
+ this.notifyCallbacks(0);
+ }
+
+ return true;
+ }
+}
diff --git a/NET/worlds/scape/HighJump.java b/NET/worlds/scape/HighJump.java
new file mode 100644
index 0000000..722a5ed
--- /dev/null
+++ b/NET/worlds/scape/HighJump.java
@@ -0,0 +1,78 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Main;
+import NET.worlds.console.MainCallback;
+import NET.worlds.core.Std;
+import java.util.Enumeration;
+
+public class HighJump extends InventoryAction implements MainCallback {
+ int start;
+ SmoothDriver sd;
+
+ public HighJump(String id, String name) {
+ super(id, name);
+ }
+
+ public HighJump(String id, String name, int qty) {
+ super(id, name, qty);
+ }
+
+ public HighJump(HighJump in) {
+ super(in);
+ }
+
+ @Override
+ public InventoryItem cloneItem() {
+ return new HighJump(this);
+ }
+
+ private SmoothDriver findSD(Pilot p) {
+ Enumeration e = p.getHandlers();
+
+ while (e.hasMoreElements()) {
+ Object o = e.nextElement();
+ if (o instanceof SmoothDriver) {
+ return (SmoothDriver)o;
+ }
+ }
+
+ return null;
+ }
+
+ @Override
+ public boolean doAction() {
+ if (this.itemQuantity_ > 0) {
+ Pilot p = Pilot.getActive();
+ if (p == null) {
+ return false;
+ } else {
+ this.sd = this.findSD(p);
+ if (this.sd == null) {
+ return false;
+ } else {
+ if (this.sd != null) {
+ Main.register(this);
+ this.start = Std.getRealTime();
+ this.itemQuantity_--;
+ }
+
+ return true;
+ }
+ }
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public void mainCallback() {
+ int now = Std.getFastTime();
+ if (now > this.start + 6000) {
+ Main.unregister(this);
+ this.sd.setEyeHeight(150.0F);
+ } else {
+ float t = 1.0F - (float)Math.pow(1.0F - (now - this.start) / 3000.0F, 4.0);
+ this.sd.setEyeHeight(150.0F + 150.0F * t);
+ }
+ }
+}
diff --git a/NET/worlds/scape/HoloCallback.java b/NET/worlds/scape/HoloCallback.java
new file mode 100644
index 0000000..3f16968
--- /dev/null
+++ b/NET/worlds/scape/HoloCallback.java
@@ -0,0 +1,5 @@
+package NET.worlds.scape;
+
+public interface HoloCallback {
+ void holoCallback(Hologram var1, boolean var2);
+}
diff --git a/NET/worlds/scape/HoloDrone.java b/NET/worlds/scape/HoloDrone.java
new file mode 100644
index 0000000..5dc17f8
--- /dev/null
+++ b/NET/worlds/scape/HoloDrone.java
@@ -0,0 +1,261 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.Main;
+import NET.worlds.core.IniFile;
+import NET.worlds.core.ServerTableManager;
+import NET.worlds.network.ObjID;
+import NET.worlds.network.URL;
+import NET.worlds.network.WorldServer;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+public class HoloDrone extends Drone implements HoloCallback {
+ private WObject _avatar;
+ private WObject _realAvatar = null;
+ private boolean _isConstructing = false;
+ private Hologram _proxyHCnewImage = null;
+ private boolean _proxyHCok = false;
+ private static int _debugLevel = IniFile.gamma().getIniInt("dronedebug", 0);
+ private boolean permitAnyAvatar = IniFile.gamma().getIniInt("permitAnyAvatar", 0) != 0;
+ private static String[] permittedList;
+ private static String[] humanList;
+ private static Hashtable permittedHash;
+ private static Hashtable humanHash;
+ private static Object classCookie;
+
+ static {
+ if (_debugLevel > 0) {
+ System.out.println("DRONE DEBUGGING LEVEL = " + _debugLevel);
+ }
+
+ permittedList = ServerTableManager.instance().getTable("permittedHoloList");
+ humanList = ServerTableManager.instance().getTable("humanHoloList");
+ permittedHash = new Hashtable();
+ humanHash = new Hashtable();
+
+ for (int i = 0; i < permittedList.length; i += 2) {
+ if (permittedList[i + 1] != null) {
+ permittedHash.put(permittedList[i], permittedList[i + 1]);
+ } else {
+ permittedHash.put(permittedList[i], permittedList);
+ }
+ }
+
+ for (int ix = 0; ix < humanList.length; ix++) {
+ humanHash.put(humanList[ix], humanList[ix]);
+ }
+
+ classCookie = new Object();
+ }
+
+ public HoloDrone() {
+ }
+
+ public HoloDrone(ObjID objID, WorldServer serv) {
+ super(objID, serv);
+
+ assert Main.isMainThread();
+
+ if (this._proxyHCnewImage != null) {
+ this.holoCallback(this._proxyHCnewImage, this._proxyHCok);
+ this._proxyHCnewImage = null;
+ }
+ }
+
+ public static String[] getPermittedList() {
+ String[] result = new String[permittedList.length / 2];
+
+ for (int i = 0; i < result.length; i++) {
+ result[i] = permittedList[2 * i];
+ }
+
+ return result;
+ }
+
+ static URL permission(URL url) {
+ String name = url.getAbsolute().toLowerCase();
+ if (name.startsWith("avatar:") && name.endsWith(".mov")) {
+ name = name.substring(7, name.length() - 4);
+ Object newName = permittedHash.get(name);
+ if (newName == null) {
+ return null;
+ } else {
+ return newName instanceof String ? URL.make((String)newName) : url;
+ }
+ } else {
+ return null;
+ }
+ }
+
+ public static URL getHuman(URL url) {
+ if (!url.endsWith(".mov")) {
+ return PosableShape.getHuman(url);
+ } else if (permission(url) == null) {
+ return URL.make("avatar:holden.mov");
+ } else {
+ String s = url.getAbsolute().toLowerCase();
+ int len = s.length();
+
+ for (int i = 7; i < len; i++) {
+ if ("0123456789.".indexOf(s.charAt(i)) >= 0) {
+ if (humanHash.get(s.substring(7, i)) != null) {
+ return url;
+ }
+
+ return URL.make(IniFile.override().getIniString("defaultHumanAv", "avatar:holden.mov"));
+ }
+ }
+
+ return url;
+ }
+ }
+
+ @Override
+ public Drone setAvatarNow(URL url) {
+ if (!this.shouldBeMuted() && url.endsWith(".mov")) {
+ if (this.shouldBeForcedHuman()) {
+ url = getHuman(url);
+ }
+
+ url = PosableShape.getPermitted(url, this.getWorld());
+ if (url.equals(this.getSourceURL())) {
+ return this;
+ } else {
+ this.setSourceURL(url);
+ URL replacementURL = permission(url);
+ if (replacementURL != null) {
+ url = replacementURL;
+ } else if (!this.permitAnyAvatar) {
+ url = Console.getDefaultURL();
+ }
+
+ this._realAvatar = this.makeAvatar(url);
+ if (this._proxyHCnewImage != null) {
+ if ((_debugLevel & 1) > 0) {
+ System.out.println("Holo.stAvNow(" + url + "): doing proxy");
+ }
+
+ this.holoCallback(this._proxyHCnewImage, this._proxyHCok);
+ this._proxyHCnewImage = null;
+ }
+
+ return this;
+ }
+ } else {
+ return super.setAvatarNow(url);
+ }
+ }
+
+ public WObject makeAvatar(URL url) {
+ if ((_debugLevel & 1) > 0) {
+ System.out.println("HoloDrone.makeAvatar(" + url + ")");
+ }
+
+ this._isConstructing = true;
+ WObject bgAvatar = new Hologram(url, this);
+ this._isConstructing = false;
+ bgAvatar.setVisible(true);
+ bgAvatar.setBumpable(false);
+ return bgAvatar;
+ }
+
+ @Override
+ public void holoCallback(Hologram newImage, boolean ok) {
+ if ((_debugLevel & 1) > 0) {
+ System.out.println("HoloDrone.holoCallback(" + newImage + "," + ok + ")");
+ }
+
+ if (this._isConstructing) {
+ assert this._proxyHCnewImage == null;
+
+ this._proxyHCnewImage = newImage;
+ this._proxyHCok = ok;
+ if ((_debugLevel & 1) > 0) {
+ System.out.println("holoCallback: requesting proxy");
+ }
+ } else if (this._realAvatar == this._avatar) {
+ if ((_debugLevel & 1) > 0) {
+ System.out.println("holoCb: real avatar already loaded");
+ }
+ } else if (!ok) {
+ if (newImage == this._realAvatar) {
+ this._realAvatar = null;
+ }
+
+ if ((_debugLevel & 1) > 0) {
+ System.out.println("holoCb: not ok");
+ }
+ } else {
+ if ((_debugLevel & 1) > 0) {
+ System.out.println("holoCb: swapping avatars");
+ }
+
+ if (this._avatar != null) {
+ this._avatar.detach();
+ }
+
+ float avatarW = newImage.getW();
+ float avatarH = newImage.getH();
+ float factor;
+ if (avatarH < avatarW) {
+ factor = (float)Math.sqrt(25600.0F / (avatarW * avatarH));
+ } else {
+ factor = 160.0F / avatarH;
+ }
+
+ avatarH *= factor;
+ avatarW *= factor;
+ float heightAdj = 0.0F;
+ if (newImage == this._avatar) {
+ heightAdj = -this._avatar.getZ();
+ }
+
+ this._avatar = (WObject)newImage.scale(factor).raise(avatarH / 2.0F + heightAdj);
+ this.add(this._avatar);
+ this.avatarHeightChangedTo(avatarH);
+ }
+ }
+
+ @Override
+ public float getMinXYExtent() {
+ return this._avatar == null ? 0.0F : this._avatar.getMinXYExtent();
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ int var10000 = index - offset;
+ return super.properties(index, offset + 0, mode, value);
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(0, classCookie);
+ super.saveState(s);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ Enumeration e = this.getContents();
+
+ while (e.hasMoreElements()) {
+ WObject w = (WObject)e.nextElement();
+ if (w instanceof Hologram) {
+ Hologram h = (Hologram)w;
+ if (h.getMovieName() != null) {
+ this._avatar = h;
+ }
+ }
+ }
+
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/HoloPilot.java b/NET/worlds/scape/HoloPilot.java
new file mode 100644
index 0000000..8f8a518
--- /dev/null
+++ b/NET/worlds/scape/HoloPilot.java
@@ -0,0 +1,579 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.core.Std;
+import NET.worlds.network.URL;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Vector;
+
+public class HoloPilot extends Pilot implements AnimatedActionHandler, AnimatedActionCallback {
+ private Camera cam;
+ private SmoothDriver smoothDriver;
+ private boolean cameraIsFree = false;
+ private AnimatedActionHandlerImp handler;
+ private HandsOffDriver hod;
+ String lastName;
+ Transform lastInverse;
+ Point3 lastCamWorldPos;
+ float lastCamRadius;
+ float lastCamYaw;
+ int lastDrawTime;
+ int framesSinceMoved = 0;
+ Room lastCamRoom;
+ Transform defaultTransform = Transform.make();
+ Point3 aimPoint = new Point3(0.0F, 0.0F, 0.0F);
+ float defaultCameraYaw = 0.0F;
+ float defaultCameraRadius = 0.0F;
+ public static final int CAM_MODE_VEHICLE = 99;
+ public static final int CAM_MODE_FIRST_PERSON = 1;
+ public static final int CAM_MODE_LOW_FIRST_PERSON = 2;
+ public static final int CAM_MODE_WAIST = 3;
+ public static final int CAM_MODE_SHOULDER = 4;
+ public static final int CAM_MODE_HEAD = 5;
+ public static final int CAM_MODE_OVERHEAD = 6;
+ public static final int CAM_MODE_BEHIND = 7;
+ public static final int CAM_MODE_WIDESHOT = 8;
+ public static final int CAM_MODE_ORTHOGRAPHIC = 9;
+ public static final int CAM_SPEED_SLOW = 1;
+ public static final int CAM_SPEED_MEDIUM = 2;
+ public static final int CAM_SPEED_FAST = 3;
+ public static final int CAM_SPEED_LOCKED = 4;
+ private boolean substWarned = false;
+ protected Point3 boxLo = new Point3();
+ protected Point3 boxHi = new Point3();
+ protected float stepHeight = 30.0F;
+ private static Object classCookie = new Object();
+
+ public HoloPilot(URL movURL) {
+ this.setSourceURL(movURL);
+ this.loadInit();
+ }
+
+ @Override
+ public void setSleepMode(String mode) {
+ Drone d = this.getInternalDrone();
+ if (d != null) {
+ d.setSleepMode(mode);
+ }
+ }
+
+ @Override
+ public float animate(String action) {
+ super.animate(action);
+ Drone d = this.getInternalDrone();
+ return d != null ? d.animate(action) : 0.0F;
+ }
+
+ @Override
+ public Vector getAnimationList() {
+ Vector v = super.getAnimationList();
+ Drone d = this.getInternalDrone();
+ if (d == null) {
+ return v;
+ } else {
+ Vector v2 = (Vector)d.getAnimationList().clone();
+
+ for (int i = 0; i < v.size(); i++) {
+ v2.addElement(v.elementAt(i));
+ }
+
+ return v2;
+ }
+ }
+
+ public HoloPilot() {
+ }
+
+ @Override
+ public void loadInit() {
+ this.smoothDriver = new SmoothDriver();
+ this.smoothDriver.setEyeHeight(0.0F);
+ this.cam = new Camera();
+ this.add(this.cam);
+ Drone selfImage = Drone.make(null, null);
+ this.add(selfImage);
+ selfImage.setAvatarNow(this.getSourceURL());
+ this.addHandler(this.smoothDriver);
+ this.addHandler(new PitchDriver());
+ this.handler = new AnimatedActionHandlerImp();
+ this.setEyeHeight(150.0F);
+ }
+
+ @Override
+ public void addCallback(AnimatedActionCallback c) {
+ assert this.handler != null;
+
+ this.handler.addCallback(c);
+ }
+
+ @Override
+ public void removeCallback(AnimatedActionCallback c) {
+ assert this.handler != null;
+
+ this.handler.removeCallback(c);
+ }
+
+ @Override
+ public void notifyCallbacks(int completionCode) {
+ assert this.handler != null;
+
+ this.handler.notifyCallbacks(completionCode);
+ }
+
+ public void walkTo(Point2 destPoint, float destYaw) {
+ this.walkTo(destPoint, destYaw, 80.0F);
+ }
+
+ public void walkTo(Point2 destPoint, float yaw, float velocity) {
+ this.removeHandler(this.smoothDriver);
+ this.hod = new HandsOffDriver();
+ this.hod.setDestPos(destPoint, yaw, velocity);
+ this.hod.addCallback(this);
+ this.addHandler(this.hod);
+ }
+
+ public void removeSmoothDriver() {
+ this.removeHandler(this.smoothDriver);
+ }
+
+ public void returnSmoothDriver() {
+ this.addHandler(this.smoothDriver);
+ }
+
+ public SmoothDriver getSmoothDriver() {
+ return this.smoothDriver;
+ }
+
+ public void removeHandsOffDriver() {
+ if (this.hod != null) {
+ this.removeHandler(this.hod);
+ this.hod = null;
+ }
+ }
+
+ public void returnHandsOffDriver() {
+ if (this.hod == null) {
+ this.hod = new HandsOffDriver();
+ this.addHandler(this.hod);
+ }
+ }
+
+ @Override
+ public void motionComplete(int completionCode) {
+ this.removeHandler(this.hod);
+ this.hod = null;
+ this.addHandler(this.smoothDriver);
+ this.notifyCallbacks(completionCode);
+ }
+
+ public void updateName() {
+ String name = this.getLongID();
+ if (name != null) {
+ if (this.lastName == null || !this.lastName.equals(name)) {
+ this.lastName = name;
+ Drone d = this.getInternalDrone();
+ if (d != null) {
+ d.setName(name);
+ }
+ }
+ }
+ }
+
+ public Drone getInternalDrone() {
+ Enumeration e = this.getContents();
+
+ while (e.hasMoreElements()) {
+ Object o = e.nextElement();
+ if (o instanceof Drone) {
+ return (Drone)o;
+ }
+ }
+
+ return null;
+ }
+
+ private void setLastInverse(Transform t) {
+ if (this.lastInverse != null) {
+ this.lastInverse.recycle();
+ }
+
+ this.lastInverse = t;
+ }
+
+ @Override
+ protected void transferFrom(Pilot old) {
+ if (old != null && old instanceof HoloPilot) {
+ HoloPilot o = (HoloPilot)old;
+ this.setOutsideCameraMode(o.getOutsideCameraMode(), o.getOutsideCameraSpeed());
+ super.transferFrom(old);
+ if (o.lastCamWorldPos != null) {
+ this.setLastInverse(o.lastInverse.getTransform());
+ this.lastCamWorldPos = new Point3(o.lastCamWorldPos);
+ }
+
+ this.lastCamRoom = o.lastCamRoom;
+ this.lastCamRadius = o.lastCamRadius;
+ this.lastCamYaw = o.lastCamYaw;
+ this.lastDrawTime = o.lastDrawTime;
+ this.framesSinceMoved = this.framesSinceMoved;
+ } else {
+ super.transferFrom(old);
+ }
+ }
+
+ @Override
+ public void aboutToDraw() {
+ if (this.cameraMode == 1 || this.cameraMode == 2) {
+ this.lastCamWorldPos = null;
+ this.cam.makeIdentity();
+ } else if (!this.cameraIsFree) {
+ Transform world = this.getObjectToWorldMatrix();
+ int thisDrawTime = Std.getRealTime();
+ Room thisCamRoom = this.getRoom();
+ Transform inv = world.getTransform().invert();
+ float radius;
+ float yaw;
+ if (this.lastCamWorldPos == null || this.cameraSpeed == 4 || this.cameraMode == 99) {
+ this.lastCamWorldPos = new Point3();
+ radius = this.defaultCameraRadius;
+ yaw = this.defaultCameraYaw;
+ } else if (thisCamRoom != this.lastCamRoom) {
+ yaw = this.lastCamYaw;
+ radius = this.lastCamRadius;
+ } else {
+ Point3 p = this.lastCamWorldPos;
+ p.times(inv);
+ radius = (float)Math.sqrt(p.x * p.x + p.y * p.y);
+ if (radius > this.defaultCameraRadius + 10.0F) {
+ radius = this.defaultCameraRadius + 10.0F;
+ }
+
+ if (this.cameraSpeed == 3) {
+ radius = this.defaultCameraRadius;
+ }
+
+ yaw = (float)(Math.atan2(p.y, p.x) * 180.0 / Math.PI);
+ this.lastInverse.post(world);
+ float yawMove = this.lastInverse.getYaw();
+ if (yawMove > 180.0F) {
+ yawMove -= 360.0F;
+ }
+
+ Point3Temp lip = this.lastInverse.getPosition();
+ if (this.cameraSpeed != 1 || Math.abs(yawMove) < 1.0F && lip.x * lip.x + lip.y * lip.y < 1.0F) {
+ if (++this.framesSinceMoved > 2) {
+ float dyaw = this.defaultCameraYaw - yaw;
+ if (dyaw < -180.0F) {
+ dyaw += 360.0F;
+ } else if (dyaw > 180.0F) {
+ dyaw -= 360.0F;
+ }
+
+ float drad = this.defaultCameraRadius - radius;
+ float dtime = thisDrawTime - this.lastDrawTime;
+ float maxYawCorrection = 0.04F;
+ float maxRadCorrection = 0.03F;
+ if (Math.abs(dyaw) > 1500.0F * maxYawCorrection) {
+ maxYawCorrection *= 1.5F;
+ }
+
+ maxYawCorrection *= dtime;
+ if (dyaw < -maxYawCorrection) {
+ dyaw = -maxYawCorrection;
+ } else if (dyaw > maxYawCorrection) {
+ dyaw = maxYawCorrection;
+ }
+
+ maxRadCorrection *= dtime;
+ if (drad < -maxRadCorrection) {
+ drad = -maxRadCorrection;
+ } else if (drad > maxRadCorrection) {
+ drad = maxRadCorrection;
+ }
+
+ yaw += dyaw;
+ radius += drad;
+ if (this.cameraSpeed == 3) {
+ if (yaw > this.defaultCameraYaw + 40.0F) {
+ yaw = this.defaultCameraYaw + 40.0F;
+ } else if (yaw < this.defaultCameraYaw - 40.0F) {
+ yaw = this.defaultCameraYaw - 40.0F;
+ }
+ }
+ }
+ } else {
+ this.framesSinceMoved = 0;
+ }
+ }
+
+ this.setLastInverse(inv);
+ float hackedZ = this.aimPoint.z;
+ float hackedYaw = yaw;
+ float hackedRadius = radius;
+ if (this.hod != null) {
+ hackedYaw = yaw + this.hod.getCameraPan();
+ hackedRadius = radius + this.hod.getCameraZoom();
+ if (hackedRadius < this.defaultCameraRadius) {
+ hackedZ -= (this.defaultCameraRadius - hackedRadius) * this.smoothDriver.getEyeHeight() / this.defaultCameraRadius;
+ }
+ }
+
+ this.cam.makeIdentity().post(this.defaultTransform);
+ this.cam.moveBy(hackedRadius, 0.0F, 0.0F);
+ this.cam.postspin(0.0F, 0.0F, 1.0F, hackedYaw);
+ this.cam.moveBy(this.aimPoint.x, this.aimPoint.y, hackedZ);
+ this.lastCamRadius = radius;
+ this.lastCamYaw = yaw;
+ double angle = yaw * Math.PI / 180.0;
+ this.lastCamWorldPos.x = (float)(radius * Math.cos(angle));
+ this.lastCamWorldPos.y = (float)(radius * Math.sin(angle));
+ this.lastCamWorldPos.z = 0.0F;
+ this.lastCamWorldPos.times(world);
+ this.lastCamWorldPos.z = 0.0F;
+ this.lastDrawTime = thisDrawTime;
+ this.lastCamRoom = thisCamRoom;
+ world.recycle();
+ }
+ }
+
+ @Override
+ public void setOutsideCameraMode(int camMode, int camSpeed) {
+ this.defaultTransform.makeIdentity();
+ this.aimPoint.x = 0.0F;
+ this.aimPoint.y = 0.0F;
+ this.aimPoint.z = 0.0F;
+ this.setEyeHeight(150.0F);
+ if (this.getInternalDrone() != null && this.getInternalDrone() instanceof PosableDrone) {
+ PosableShape ps = ((PosableDrone)this.getInternalDrone()).getInternalPosableShape();
+ if (ps != null && ps instanceof VehicleShape) {
+ VehicleShape vs = (VehicleShape)ps;
+ if (vs.fixedCamera) {
+ this.defaultTransform
+ .moveTo(vs.camX, vs.camY, vs.camZ)
+ .postspin(1.0F, 0.0F, 0.0F, vs.camRoll)
+ .postspin(0.0F, 1.0F, 0.0F, vs.camYaw)
+ .postspin(0.0F, 0.0F, 1.0F, vs.camPitch);
+ this.aimPoint.x = vs.camAimX;
+ this.aimPoint.y = vs.camAimY;
+ this.aimPoint.z = vs.camAimZ;
+ this.setEyeHeight(vs.eyeHeight);
+ camMode = 99;
+ }
+ }
+ }
+
+ this.cam.setAlwaysClearBackground(false);
+ this.cam.setBumpable(true);
+ switch (camMode) {
+ case 1:
+ case 99:
+ break;
+ case 2:
+ this.setEyeHeight(100.0F);
+ break;
+ case 3:
+ this.defaultTransform.moveTo(0.0F, -120.0F, -60.0F).postspin(1.0F, 0.0F, 0.0F, -10.0F).postspin(0.0F, 0.0F, 1.0F, 30.0F);
+ this.aimPoint.x = 15.0F;
+ this.aimPoint.z = -10.0F;
+ break;
+ case 4:
+ this.defaultTransform.moveTo(0.0F, -140.0F, -40.0F).postspin(1.0F, 0.0F, 0.0F, -10.0F).postspin(0.0F, 0.0F, 1.0F, 15.0F);
+ this.aimPoint.x = 15.0F;
+ this.aimPoint.z = 10.0F;
+ break;
+ case 5:
+ this.defaultTransform.moveTo(0.0F, -140.0F, 0.0F).postspin(1.0F, 0.0F, 0.0F, -10.0F).postspin(0.0F, 0.0F, 1.0F, 15.0F);
+ this.aimPoint.x = 15.0F;
+ this.aimPoint.z = 10.0F;
+ break;
+ case 6:
+ this.defaultTransform.moveTo(0.0F, -100.0F, 0.0F).postspin(1.0F, 0.0F, 0.0F, -30.0F).postspin(0.0F, 0.0F, 1.0F, 30.0F);
+ this.aimPoint.x = 15.0F;
+ this.aimPoint.z = 10.0F;
+ break;
+ case 7:
+ this.defaultTransform.moveTo(0.0F, -140.0F, 0.0F).postspin(1.0F, 0.0F, 0.0F, -10.0F);
+ break;
+ case 8:
+ this.defaultTransform.moveTo(0.0F, -220.0F, -40.0F).postspin(1.0F, 0.0F, 0.0F, -30.0F).postspin(0.0F, 0.0F, 1.0F, 30.0F);
+ this.aimPoint.x = 15.0F;
+ this.aimPoint.z = 10.0F;
+ break;
+ case 9:
+ this.defaultTransform.moveTo(0.0F, -140.0F, 300.0F).postspin(1.0F, 0.0F, 0.0F, -10.0F);
+ this.aimPoint.x = 0.0F;
+ this.aimPoint.z = 300.0F;
+ this.cam.setAlwaysClearBackground(true);
+ this.cam.setBumpable(false);
+ camSpeed = 4;
+ break;
+ default:
+ camMode = 1;
+ camSpeed = 3;
+ this.defaultCameraRadius = 0.0F;
+ this.defaultCameraYaw = 0.0F;
+ }
+
+ if (camMode != 1 && camMode != 2) {
+ float x = this.defaultTransform.getX();
+ float y = this.defaultTransform.getY();
+ this.aimPoint.z = this.aimPoint.z + this.defaultTransform.getZ();
+ this.defaultCameraRadius = (float)Math.sqrt(x * x + y * y);
+ this.defaultCameraYaw = (float)(Math.atan2(y, x) * 180.0 / Math.PI);
+ this.defaultTransform.moveTo(0.0F, 0.0F, 0.0F);
+ this.defaultTransform.postspin(0.0F, 0.0F, 1.0F, -this.defaultCameraYaw);
+ }
+
+ super.setOutsideCameraMode(camMode, camSpeed);
+ }
+
+ @Override
+ public void resetAvatarNow() {
+ URL to = this.getSourceURL();
+ Drone d = this.getInternalDrone();
+ d.setAvatarNow(to);
+ if (!d.shouldBeForcedHuman() || PosableShape.getHuman(to).equals(to)) {
+ this.substWarned = false;
+ } else if (!this.substWarned) {
+ this.substWarned = true;
+ Console.println(Console.message("Sub-human"));
+ }
+ }
+
+ public void setEyeHeight(float h) {
+ float hOld = this.smoothDriver.getEyeHeight();
+ if (h != hOld) {
+ this.smoothDriver.setEyeHeight(h);
+ this.getInternalDrone().moveBy(0.0F, 0.0F, hOld - h);
+ this.setLocalBoundBox(Point3Temp.make(-30.0F, -30.0F, -h), Point3Temp.make(30.0F, 50.0F, 20.0F));
+ }
+ }
+
+ public BoundBoxTemp getLocalBoundBox() {
+ return BoundBoxTemp.make(this.boxLo, this.boxHi);
+ }
+
+ public void setLocalBoundBox(BoundBoxTemp b) {
+ this.boxLo = new Point3(b.lo);
+ this.boxHi = new Point3(b.hi);
+ }
+
+ public void setLocalBoundBox(Point3Temp lo, Point3Temp hi) {
+ this.setLocalBoundBox(BoundBoxTemp.make(lo, hi));
+ }
+
+ @Override
+ public BoundBoxTemp getBoundBox() {
+ Point3Temp lo = Point3Temp.make(this.boxLo);
+ lo.z = lo.z + this.stepHeight;
+ Point3Temp hi = this.boxHi;
+ Transform xfrm = this.getObjectToWorldMatrix();
+ Point3Temp p = Point3Temp.make(lo).times(xfrm);
+ BoundBoxTemp w = BoundBoxTemp.make(p, p);
+ w.encompass(Point3Temp.make(hi).times(xfrm));
+ w.encompass(Point3Temp.make(lo.x, lo.y, hi.z).times(xfrm));
+ w.encompass(Point3Temp.make(lo.x, hi.y, lo.z).times(xfrm));
+ w.encompass(Point3Temp.make(lo.x, hi.y, hi.z).times(xfrm));
+ w.encompass(Point3Temp.make(hi.x, lo.y, lo.z).times(xfrm));
+ w.encompass(Point3Temp.make(hi.x, lo.y, hi.z).times(xfrm));
+ w.encompass(Point3Temp.make(hi.x, hi.y, lo.z).times(xfrm));
+ xfrm.recycle();
+ return w;
+ }
+
+ @Override
+ public float getFootHeight() {
+ if (this.isActive()) {
+ Transform t = this.getObjectToWorldMatrix();
+ float pitch = t.getPitch();
+ t.pitch(-pitch);
+ float ret = Point3Temp.make(this.boxLo).times(t).z;
+ t.recycle();
+ return ret;
+ } else {
+ return 0.0F;
+ }
+ }
+
+ public float getStepHeight() {
+ return this.stepHeight;
+ }
+
+ public void setStepHeight(float h) {
+ this.stepHeight = h;
+ }
+
+ public void releaseCamera() {
+ this.cameraIsFree = true;
+ }
+
+ public void reclaimCamera() {
+ this.cameraIsFree = false;
+ }
+
+ public Camera getCamera() {
+ return this.cam;
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = Point3PropertyEditor.make(new Property(this, index, "Bump Box Start"));
+ } else if (mode == 1) {
+ ret = new Point3(this.boxLo);
+ } else if (mode == 2) {
+ this.boxLo = new Point3((Point3)value);
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = Point3PropertyEditor.make(new Property(this, index, "Bump Box End"));
+ } else if (mode == 1) {
+ ret = new Point3(this.boxHi);
+ } else if (mode == 2) {
+ this.boxHi = new Point3((Point3)value);
+ }
+ break;
+ case 2:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Step Height"));
+ } else if (mode == 1) {
+ ret = new Float(this.getStepHeight());
+ } else if (mode == 2) {
+ this.setStepHeight((Float)value);
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 3, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(0, classCookie);
+ super.saveState(s);
+ s.saveFloat(this.stepHeight);
+ s.save(this.boxLo);
+ s.save(this.boxHi);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ this.stepHeight = r.restoreFloat();
+ this.boxLo = (Point3)r.restore();
+ this.boxHi = (Point3)r.restore();
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/Hologram.java b/NET/worlds/scape/Hologram.java
new file mode 100644
index 0000000..b138ac2
--- /dev/null
+++ b/NET/worlds/scape/Hologram.java
@@ -0,0 +1,568 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.Main;
+import NET.worlds.console.MainCallback;
+import NET.worlds.network.URL;
+import java.io.IOException;
+
+public class Hologram extends Surface implements Prerenderable, BGLoaded, Postrenderable, MainCallback {
+ private int isLoading;
+ ScapePicMovie fromMovie;
+ URL movieName;
+ protected Texture[] images;
+ protected Material[] materials;
+ private static Object classCookie = new Object();
+ private int origTransformID = 0;
+ private HoloCallback callback;
+ private float scaleDist;
+
+ static {
+ nativeInit();
+ }
+
+ public Hologram(float w, float h, Texture[] texs) {
+ super(null);
+ this.scale(w, 1.0F, h);
+ this.images = texs;
+ }
+
+ public Hologram() {
+ super(null);
+ }
+
+ public Hologram(Texture[] texs) {
+ this(texs[0].getW(), texs[0].getH(), texs);
+ }
+
+ public Hologram(ScapePicMovie texs) {
+ this(texs.getW(), texs.getH(), texs.getTextures());
+ this.fromMovie = texs;
+ }
+
+ public Hologram(float w, float h, ScapePicMovie texs) {
+ this(w, h, texs.getTextures());
+ this.fromMovie = texs;
+ }
+
+ public Hologram(URL movieName, HoloCallback cb) {
+ super(null);
+ this.setAutosize(true);
+ this.scale(100.0F, 1.0F, 100.0F);
+ this.load(movieName, cb);
+ }
+
+ public Hologram(URL movieName) {
+ this(movieName, null);
+ }
+
+ public Hologram(float w, float h, URL movieName, HoloCallback cb) {
+ super(null);
+ this.scale(w, 1.0F, h);
+ this.load(movieName, cb);
+ }
+
+ public Hologram(float w, float h, URL movieName) {
+ this(w, h, movieName, null);
+ }
+
+ public static native void nativeInit();
+
+ private void load(URL movieName, HoloCallback cb) {
+ assert this.getMaterial() != null;
+
+ this.callback = cb;
+ this.movieName = movieName;
+ if (this.callback != null || this.hasClump()) {
+ this.forceLoad();
+ }
+ }
+
+ private void lockMaterials(boolean val) {
+ if (this.materials != null) {
+ for (int i = 0; i < this.materials.length; i++) {
+ this.materials[i].setKeepLoaded(val);
+ }
+ }
+ }
+
+ private void releaseMaterials() {
+ this.lockMaterials(false);
+ this.materials = null;
+ }
+
+ private void loadMultipart(URL url, String base, int numParts, String end) {
+ this.images = null;
+ this.releaseMaterials();
+ this.materials = new Material[numParts];
+
+ while (--numParts >= 0) {
+ this.materials[numParts] = new Material(URL.make(url, base + (numParts + 1) + end));
+ }
+
+ this.setMaterial(this.materials[0]);
+ if (this.callback != null) {
+ this.callback.holoCallback(this, true);
+ this.callback = null;
+ }
+ }
+
+ private void forceLoad() {
+ URL url = HoloDrone.permission(this.movieName);
+ String name = (url == null ? this.movieName : url).getBase();
+ int len = name.length();
+ boolean isMov = len > 5 && name.regionMatches(true, len - 5, "*.mov", 0, 5);
+ int h = 1;
+ int v = 1;
+ int s = 1;
+
+ int num;
+ for (int nextStarIndex = len - 5;
+ nextStarIndex > 2 && name.charAt(nextStarIndex) == '*' && (num = name.charAt(nextStarIndex - 2) - '0') > 0 && num <= 9;
+ nextStarIndex -= 3
+ ) {
+ char control = Character.toLowerCase(name.charAt(nextStarIndex - 1));
+ if (control == 'h') {
+ h = num;
+ } else if (control == 'v') {
+ v = num;
+ } else if (control == 's') {
+ if (this.getAutosize()) {
+ this.scale(h * 160.0F / v / this.getScaleX(), 1.0F, 160.0F / this.getScaleZ());
+ }
+
+ if (isMov) {
+ this.loadMultipart(this.movieName, name.substring(0, nextStarIndex - 2), num, "s*" + h + "h*" + v + "v*.mov");
+ } else {
+ this.loadMultipart(this.movieName, name.substring(0, nextStarIndex - 2), num, name.substring(nextStarIndex + 1));
+ }
+
+ return;
+ }
+ }
+
+ this.isLoading++;
+ BackgroundLoader.get(this, this.movieName);
+ }
+
+ @Override
+ public Object asyncBackgroundLoad(String localName, URL remoteName) {
+ if (localName != null) {
+ if (localName.toLowerCase().endsWith(".mov")) {
+ return new ScapePicMovie(localName, remoteName).getTextures();
+ }
+
+ Texture[] texs = new Texture[]{TextureDecoder.decode(remoteName, localName)};
+ if (texs[0] != null && texs[0].textureID != 0) {
+ return texs;
+ }
+ }
+
+ return null;
+ }
+
+ @Override
+ public boolean syncBackgroundLoad(Object obj, URL remoteURL) {
+ this.releaseMaterials();
+ if (obj != null) {
+ this.images = (Texture[])obj;
+ if (this.getAutosize()) {
+ this.scale(this.images[0].getW() / this.getScaleX(), 1.0F, this.images[0].getH() / this.getScaleZ());
+ }
+ } else {
+ if (this.movieName != null) {
+ Console.println(Console.message("No-load-hologram") + this.movieName);
+ }
+
+ this.images = null;
+ this.setMaterial(null);
+ }
+
+ if (this.callback != null) {
+ this.callback.holoCallback(this, this.images != null || this.materials != null);
+ this.callback = null;
+ }
+
+ this.isLoading--;
+ return false;
+ }
+
+ @Override
+ public Room getBackgroundLoadRoom() {
+ return this.getRoom();
+ }
+
+ @Override
+ public BoundBoxTemp getBoundBox() {
+ Point3Temp center = this.getWorldPosition();
+ Point3Temp jog = Point3Temp.make(this.getW() / 2.0F, this.getW() / 2.0F, this.getH() / 2.0F);
+ return BoundBoxTemp.make(Point3Temp.make(center).minus(jog), Point3Temp.make(center).plus(jog));
+ }
+
+ @Override
+ public float getMinXYExtent() {
+ return this.getW();
+ }
+
+ public float getW() {
+ return this.getScaleX();
+ }
+
+ public float getH() {
+ return this.getScaleZ();
+ }
+
+ public int getNumSides() {
+ if (this.images == null) {
+ return this.materials == null ? 1 : this.materials.length;
+ } else {
+ return this.images.length;
+ }
+ }
+
+ void setActiveSide(int side) {
+ if (side >= this.getNumSides()) {
+ System.out.println("Error at NET.worlds.Hologram.setActiveSide side " + side + " of " + this.getNumSides());
+ side = 0;
+ }
+
+ if (this.materials == null) {
+ Texture t = this.images == null ? null : (side < this.images.length ? this.images[side] : null);
+ if (t != null) {
+ t.incRef();
+ }
+
+ this.material.setTexture(t);
+ } else if (this.materials[side] != this.material) {
+ this.setMaterial(this.materials[side]);
+ }
+ }
+
+ public URL getMovieName() {
+ return this.movieName == null && this.fromMovie != null ? this.fromMovie.getURL() : this.movieName;
+ }
+
+ @Override
+ protected void addRwChildren(WObject container) {
+ this.addNewRwChild(container);
+ if (this.images == null && this.materials == null && this.movieName != null && this.isLoading == 0) {
+ this.forceLoad();
+ }
+
+ this.addVertex(0.5F, 0.0F, -0.5F, 0.0F, 1.0F);
+ this.addVertex(-0.5F, 0.0F, -0.5F, 1.0F, 1.0F);
+ this.addVertex(-0.5F, 0.0F, 0.5F, 1.0F, 0.0F);
+ this.addVertex(0.5F, 0.0F, 0.5F, 0.0F, 0.0F);
+ this.doneWithEditing();
+ if (!this.isReclumping()) {
+ this.lockMaterials(true);
+ this.getRoom().addPrerenderHandler(this);
+ this.getRoom().addPostrenderHandler(this);
+ }
+
+ if (this.images == null && this.materials == null && this.isLoading > 0) {
+ this.makeTemporarilyInvisible();
+ }
+ }
+
+ public native void makeTemporarilyInvisible();
+
+ @Override
+ protected void markVoid() {
+ if (!this.isReclumping()) {
+ this.lockMaterials(false);
+ this.getRoom().removePrerenderHandler(this);
+ this.getRoom().removePostrenderHandler(this);
+ }
+
+ if (this.movieName != null && this.fromMovie == null && this.isLoading == 0) {
+ Main.register(this);
+ }
+
+ super.markVoid();
+ }
+
+ @Override
+ public void mainCallback() {
+ if (!this.hasClump()) {
+ if (this.images != null) {
+ int i = this.images.length;
+
+ while (--i >= 0) {
+ if (this.images[i] != null) {
+ this.images[i].decRef();
+ }
+ }
+
+ this.images = null;
+ }
+
+ this.releaseMaterials();
+ }
+
+ Main.unregister(this);
+ }
+
+ @Override
+ public native void prerender(Camera var1);
+
+ @Override
+ public native void postrender(Camera var1);
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(6, classCookie);
+ s.saveFloat(this.scaleDist);
+ Material origMaterial = this.getMaterial();
+ URL name = this.getMovieName();
+ if (name != null) {
+ this.setMaterial(null);
+ }
+
+ super.saveState(s);
+ this.setMaterial(origMaterial);
+ URL.save(s, name);
+ if (name == null) {
+ if (this.fromMovie != null) {
+ s.saveBoolean(true);
+ s.save(this.fromMovie);
+ } else {
+ s.saveBoolean(false);
+ if (this.images != null) {
+ s.saveBoolean(true);
+ s.saveArray(this.images);
+ } else {
+ assert this.materials == null;
+
+ s.saveBoolean(false);
+ }
+ }
+ }
+ }
+
+ private static Texture[] extractTextureArray(Material[] mats) {
+ Texture[] texs = new Texture[mats.length];
+
+ for (int i = 0; i < mats.length; i++) {
+ texs[i] = mats[i].extractTexture(0);
+ }
+
+ return texs;
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ int vers = r.restoreVersion(classCookie);
+ switch (vers) {
+ case 0:
+ super.restoreState(r);
+ float w = r.restoreFloat();
+ if (w == 0.0F) {
+ w = 100.0F;
+ }
+
+ float h = r.restoreFloat();
+ if (h == 0.0F) {
+ h = 100.0F;
+ }
+
+ this.scale(w, 1.0F, h);
+ if (r.restoreBoolean()) {
+ this.fromMovie = (ScapePicMovie)r.restore();
+ this.images = this.fromMovie.getTextures();
+ } else {
+ this.setAutosize(true);
+ }
+ break;
+ case 1:
+ super.restoreState(r);
+ float wx = r.restoreFloat();
+ if (wx == 0.0F) {
+ wx = 100.0F;
+ }
+
+ float hx = r.restoreFloat();
+ if (hx == 0.0F) {
+ hx = 100.0F;
+ }
+
+ this.scale(wx, 1.0F, hx);
+ if ((this.movieName = URL.restore(r)) != null) {
+ this.load(this.movieName, null);
+ } else if (r.restoreBoolean()) {
+ this.fromMovie = (ScapePicMovie)r.restore();
+ this.images = this.fromMovie.getTextures();
+ } else {
+ this.setAutosize(true);
+ }
+ break;
+ case 2:
+ super.restoreState(r);
+ if ((this.movieName = URL.restore(r)) != null) {
+ this.load(this.movieName, null);
+ } else if (r.restoreBoolean()) {
+ this.fromMovie = (ScapePicMovie)r.restore();
+ this.images = this.fromMovie.getTextures();
+ } else {
+ this.setAutosize(true);
+ }
+ break;
+ case 3:
+ super.restoreState(r);
+ if ((this.movieName = URL.restore(r)) != null) {
+ this.load(this.movieName, null);
+ } else if (r.restoreBoolean()) {
+ this.fromMovie = (ScapePicMovie)r.restore();
+ this.images = this.fromMovie.getTextures();
+ } else {
+ this.setAutosize(true);
+ if (r.restoreBoolean()) {
+ this.images = extractTextureArray((Material[])r.restoreArray());
+ }
+ }
+ break;
+ case 5:
+ case 6:
+ this.scaleDist = r.restoreFloat();
+ case 4:
+ super.restoreState(r);
+ if ((this.movieName = URL.restore(r)) != null) {
+ this.load(this.movieName, null);
+ } else if (r.restoreBoolean()) {
+ this.fromMovie = (ScapePicMovie)r.restore();
+ this.images = this.fromMovie.getTextures();
+ } else {
+ if (vers < 6) {
+ this.setAutosize(true);
+ }
+
+ if (r.restoreBoolean()) {
+ this.images = (Texture[])r.restoreArray();
+ }
+ }
+ break;
+ default:
+ throw new TooNewException();
+ }
+ }
+
+ public Hologram setRoughCut(boolean b) {
+ if (b) {
+ this.flags |= 4;
+ } else {
+ this.flags &= -5;
+ }
+
+ return this;
+ }
+
+ public final boolean getRoughCut() {
+ return (this.flags & 4) != 0;
+ }
+
+ public void setAutosize(boolean b) {
+ if (b) {
+ this.flags |= 4194304;
+ } else {
+ this.flags &= -4194305;
+ }
+ }
+
+ public final boolean getAutosize() {
+ return (this.flags & 4194304) != 0;
+ }
+
+ public Hologram setViewplaneAligned(boolean b) {
+ if (b) {
+ this.flags |= 262144;
+ } else {
+ this.flags &= -262145;
+ }
+
+ return this;
+ }
+
+ public final boolean getViewplaneAligned() {
+ return (this.flags & 262144) != 0;
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = URLPropertyEditor.make(new Property(this, index, "File"), TextureDecoder.getAllExts());
+ } else if (mode == 1) {
+ ret = this.getMovieName();
+ } else if (mode == 2) {
+ this.load((URL)value, null);
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Viewplane Aligned"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(this.getViewplaneAligned());
+ } else if (mode == 2) {
+ this.setViewplaneAligned((Boolean)value);
+ }
+ break;
+ case 2:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Rough Cut Alignment"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(this.getRoughCut());
+ } else if (mode == 2) {
+ this.setRoughCut((Boolean)value);
+ }
+ break;
+ case 3:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Scale Distance"));
+ } else if (mode == 1) {
+ ret = new Float(this.getScaleDist());
+ } else if (mode == 2) {
+ this.setScaleDist((Float)value);
+ }
+ break;
+ case 4:
+ if (mode == 0) {
+ ret = Point2PropertyEditor.make(new Property(this, index, "Extent"));
+ } else if (mode == 1) {
+ ret = new Point2(this.getScaleX(), this.getScaleZ());
+ } else if (mode == 2) {
+ this.setAutosize(false);
+ this.scale(((Point2)value).x / this.getScaleX(), 1.0F, ((Point2)value).y / this.getScaleZ());
+ }
+ break;
+ case 5:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Autosize"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(this.getAutosize());
+ } else if (mode == 2) {
+ this.setAutosize((Boolean)value);
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 6, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public String toString() {
+ URL name = this.getMovieName();
+ return super.toString() + "[" + (name != null ? name.toString() : "") + "]";
+ }
+
+ public void setScaleDist(float dist) {
+ this.scaleDist = dist;
+ }
+
+ public final float getScaleDist() {
+ return this.scaleDist;
+ }
+}
diff --git a/NET/worlds/scape/HorizontalRect.java b/NET/worlds/scape/HorizontalRect.java
new file mode 100644
index 0000000..cf12fd9
--- /dev/null
+++ b/NET/worlds/scape/HorizontalRect.java
@@ -0,0 +1,38 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+public class HorizontalRect extends Surface {
+ private static Object classCookie = new Object();
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ assert false;
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ float x = r.restoreFloat();
+ float y = r.restoreFloat();
+ float u = r.restoreFloat();
+ float v = r.restoreFloat();
+ boolean faceUp = r.restoreBoolean();
+ Rect rect = new Rect(1.0F, 1.0F, this.getMaterial());
+ rect.setTransform(this);
+ if (faceUp) {
+ rect.pitch(-90.0F).scale(x, 1.0F, y);
+ } else {
+ rect.yaw(90.0F).pitch(90.0F).scale(y, 1.0F, x);
+ }
+
+ rect.setUV(u, v);
+ r.replace(this, rect);
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/Iconic.java b/NET/worlds/scape/Iconic.java
new file mode 100644
index 0000000..cdee035
--- /dev/null
+++ b/NET/worlds/scape/Iconic.java
@@ -0,0 +1,9 @@
+package NET.worlds.scape;
+
+import NET.worlds.network.URL;
+
+public interface Iconic {
+ URL getIconURL();
+
+ String getIconCaption();
+}
diff --git a/NET/worlds/scape/ImageConverter.java b/NET/worlds/scape/ImageConverter.java
new file mode 100644
index 0000000..091ba1f
--- /dev/null
+++ b/NET/worlds/scape/ImageConverter.java
@@ -0,0 +1,181 @@
+package NET.worlds.scape;
+
+import java.awt.Image;
+import java.awt.Toolkit;
+import java.awt.image.ColorModel;
+import java.awt.image.DirectColorModel;
+import java.awt.image.ImageConsumer;
+import java.awt.image.IndexColorModel;
+import java.util.Hashtable;
+
+public class ImageConverter implements ImageConsumer {
+ private String urlName;
+ private String filename;
+ private int width;
+ private int height;
+ private Image image;
+ private boolean done;
+ private boolean ok;
+ private boolean debug = false;
+ private ColorModel model;
+ private int transparentColor = -1;
+ private int hDIB;
+ private int pixelPtr;
+
+ static {
+ nativeInit();
+ }
+
+ public ImageConverter(String urlName, String filename) {
+ this.urlName = urlName;
+ this.filename = filename;
+ }
+
+ public static native void nativeInit();
+
+ public synchronized int convert() {
+ this.image = Toolkit.getDefaultToolkit().getImage(this.filename);
+ this.image.getSource().startProduction(this);
+
+ while (!this.done) {
+ try {
+ this.wait();
+ } catch (InterruptedException var2) {
+ }
+ }
+
+ int textureID = 0;
+ if (this.ok) {
+ textureID = this.convertDIBToTexture();
+ }
+
+ this.cleanup();
+ return textureID;
+ }
+
+ @Override
+ public void setDimensions(int width, int height) {
+ if (this.debug) {
+ System.out.println("Set dimensions: w " + width + " h " + height);
+ }
+
+ this.width = width;
+ this.height = height;
+ }
+
+ @Override
+ public void setProperties(Hashtable props) {
+ if (this.debug) {
+ System.out.println("Set properties");
+ }
+ }
+
+ @Override
+ public void setColorModel(ColorModel model) {
+ if (this.debug) {
+ System.out.println("Set color model: " + model);
+ }
+
+ this.model = model;
+
+ assert this.width != 0 && this.height != 0;
+
+ int[] palette = (int[])null;
+ int colors = 0;
+ if (model instanceof IndexColorModel) {
+ IndexColorModel im = (IndexColorModel)model;
+ colors = im.getMapSize();
+ this.transparentColor = im.getTransparentPixel();
+ palette = new int[colors * 3];
+
+ for (int i = 0; i < colors; i++) {
+ palette[i] = im.getRGB(i);
+ }
+ } else {
+ DirectColorModel dm = (DirectColorModel)model;
+
+ assert dm.getBlueMask() == 255;
+
+ assert dm.getGreenMask() == 65280;
+
+ assert dm.getRedMask() == 16711680;
+ }
+
+ this.prepareDIB(this.width, this.height, colors, palette);
+ }
+
+ @Override
+ public void setHints(int hintflags) {
+ if (this.debug) {
+ System.out
+ .println(
+ "Set hints: "
+ + ((hintflags & 1) != 0 ? " RANDOM " : "")
+ + ((hintflags & 2) != 0 ? " TOPDOWNLEFTRIGHT " : "")
+ + ((hintflags & 4) != 0 ? " COMPLETESCANS " : "")
+ + ((hintflags & 8) != 0 ? " SINGLEPASS " : "")
+ + ((hintflags & 16) != 0 ? " SINGLEFRAME " : "")
+ );
+ }
+ }
+
+ @Override
+ public void setPixels(int x, int y, int w, int h, ColorModel model, byte[] pixels, int off, int scansize) {
+ if (this.debug) {
+ System.out.println("setPixels(byte): x " + x + " y " + y + " w " + w + " h " + h + " model " + model + " off " + off + " scansize " + scansize);
+ }
+
+ assert model == this.model;
+
+ this.setDIBPixelBytes(x, y, w, h, pixels, off, scansize);
+ }
+
+ @Override
+ public void setPixels(int x, int y, int w, int h, ColorModel model, int[] pixels, int off, int scansize) {
+ if (this.debug) {
+ System.out.println("setPixels(int): x " + x + " y " + y + " w " + w + " h " + h + " model " + model + " off " + off + " scansize " + scansize);
+ }
+
+ assert model == this.model;
+
+ this.setDIBPixelInts(x, y, w, h, pixels, off, scansize);
+ }
+
+ @Override
+ public synchronized void imageComplete(int status) {
+ if (this.debug) {
+ String state = null;
+ switch (status) {
+ case 1:
+ state = "ERROR";
+ break;
+ case 2:
+ state = "SINGLEDONE";
+ break;
+ case 3:
+ state = "STATICDONE";
+ break;
+ case 4:
+ state = "ABORTED";
+ }
+
+ System.out.println("Image complete: " + state);
+ }
+
+ this.image.getSource().removeConsumer(this);
+ this.image.flush();
+ this.ok = status != 1 && status != 4;
+ this.done = true;
+ this.notify();
+ }
+
+ private native void prepareDIB(int var1, int var2, int var3, int[] var4);
+
+ private native void setDIBPixelBytes(int var1, int var2, int var3, int var4, byte[] var5, int var6, int var7);
+
+ private native void setDIBPixelInts(int var1, int var2, int var3, int var4, int[] var5, int var6, int var7);
+
+ private native int convertDIBToTexture();
+
+ private native void cleanup();
+}
diff --git a/NET/worlds/scape/IncrementalRestorer.java b/NET/worlds/scape/IncrementalRestorer.java
new file mode 100644
index 0000000..27b4fb4
--- /dev/null
+++ b/NET/worlds/scape/IncrementalRestorer.java
@@ -0,0 +1,5 @@
+package NET.worlds.scape;
+
+public interface IncrementalRestorer {
+ int incRestore(int var1, Restorer var2, URLSelfLoader var3) throws Exception;
+}
diff --git a/NET/worlds/scape/IndentStream.java b/NET/worlds/scape/IndentStream.java
new file mode 100644
index 0000000..b7bd27d
--- /dev/null
+++ b/NET/worlds/scape/IndentStream.java
@@ -0,0 +1,94 @@
+package NET.worlds.scape;
+
+import java.io.OutputStream;
+import java.io.PrintStream;
+
+public class IndentStream extends PrintStream {
+ private boolean _atstart = true;
+ private int _indent = 0;
+
+ public IndentStream(OutputStream os) {
+ super(os);
+ }
+
+ public IndentStream(OutputStream os, boolean flush) {
+ super(os, flush);
+ }
+
+ public void indent(int step) {
+ this._indent += step;
+ }
+
+ public void indent() {
+ this.indent(2);
+ }
+
+ public void undent(int step) {
+ if (this._indent >= step) {
+ this._indent -= step;
+ } else {
+ this._indent = 0;
+ }
+ }
+
+ public void undent() {
+ this.undent(2);
+ }
+
+ public int curIndent() {
+ return this._indent;
+ }
+
+ private void startLine() {
+ for (int i = 0; i < this._indent; i++) {
+ super.write(32);
+ }
+
+ this._atstart = false;
+ }
+
+ @Override
+ public void write(int b) {
+ if (b == 10) {
+ this._atstart = true;
+ } else if (this._atstart) {
+ this.startLine();
+ }
+
+ super.write(b);
+ }
+
+ @Override
+ public void write(byte[] b, int off, int len) {
+ while (len > 0) {
+ int firstlen = 0;
+
+ while (firstlen < len && b[off + firstlen] != 10) {
+ firstlen++;
+ }
+
+ if (firstlen > 0) {
+ if (this._atstart) {
+ this.startLine();
+ }
+
+ super.write(b, off, firstlen);
+ off += firstlen;
+ len -= firstlen;
+ this._atstart = false;
+ firstlen = 0;
+ }
+
+ while (firstlen < len && b[off + firstlen] == 10) {
+ firstlen++;
+ }
+
+ if (firstlen > 0) {
+ super.write(b, off, firstlen);
+ off += firstlen;
+ len -= firstlen;
+ this._atstart = true;
+ }
+ }
+ }
+}
diff --git a/NET/worlds/scape/IntegerFieldEditorDialog.java b/NET/worlds/scape/IntegerFieldEditorDialog.java
new file mode 100644
index 0000000..07a0369
--- /dev/null
+++ b/NET/worlds/scape/IntegerFieldEditorDialog.java
@@ -0,0 +1,34 @@
+package NET.worlds.scape;
+
+class IntegerFieldEditorDialog extends FieldEditorDialog {
+ Property property;
+ IntegerPropertyEditor limits;
+
+ IntegerFieldEditorDialog(EditTile parent, String title, Property property, IntegerPropertyEditor limits) {
+ super(parent, title);
+ this.property = property;
+ this.limits = limits;
+ this.ready();
+ }
+
+ @Override
+ protected String getValue() {
+ return "" + this.property.get();
+ }
+
+ @Override
+ protected boolean setValue(String text) {
+ if (text.length() != 0) {
+ try {
+ int val = Integer.parseInt(text);
+ if (!this.limits.rangeLimits || val >= this.limits.minVal && val <= this.limits.maxVal) {
+ this.parent.addUndoableSet(this.property, new Integer(val));
+ return true;
+ }
+ } catch (NumberFormatException var3) {
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/NET/worlds/scape/IntegerPropertyEditor.java b/NET/worlds/scape/IntegerPropertyEditor.java
new file mode 100644
index 0000000..dc210ac
--- /dev/null
+++ b/NET/worlds/scape/IntegerPropertyEditor.java
@@ -0,0 +1,35 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.PolledDialog;
+
+public class IntegerPropertyEditor extends PropEditor {
+ boolean rangeLimits = false;
+ int minVal;
+ int maxVal;
+
+ private IntegerPropertyEditor(Property property) {
+ super(property);
+ }
+
+ private IntegerPropertyEditor(Property property, int minVal, int maxVal) {
+ super(property);
+ this.rangeLimits = true;
+ this.minVal = minVal;
+ this.maxVal = maxVal;
+ }
+
+ @Override
+ public PolledDialog edit(EditTile parent, String title) {
+ return new IntegerFieldEditorDialog(parent, title, this.property, this);
+ }
+
+ public static Property make(Property property) {
+ property.setPropertyType(1);
+ return property.setEditor(new IntegerPropertyEditor(property));
+ }
+
+ public static Property make(Property property, int minVal, int maxVal) {
+ property.setPropertyType(1);
+ return property.setEditor(new IntegerPropertyEditor(property, minVal, maxVal));
+ }
+}
diff --git a/NET/worlds/scape/InterpolatedDrone.java b/NET/worlds/scape/InterpolatedDrone.java
new file mode 100644
index 0000000..bf50bb4
--- /dev/null
+++ b/NET/worlds/scape/InterpolatedDrone.java
@@ -0,0 +1,247 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.BBAppearDroneCommand;
+import NET.worlds.console.BBDisappearDroneCommand;
+import NET.worlds.console.BBDroneDeltaPosCommand;
+import NET.worlds.console.BBMoveDroneCommand;
+import NET.worlds.console.BlackBox;
+import NET.worlds.core.Std;
+import NET.worlds.network.ObjID;
+import NET.worlds.network.URL;
+import NET.worlds.network.WorldServer;
+import java.io.IOException;
+
+public class InterpolatedDrone extends Drone implements FrameHandler {
+ private int _last_FrameTime;
+ private int _last_PosTime;
+ private int _vel_x;
+ private int _vel_y;
+ private int _vel_z;
+ private int _vel_yaw;
+ private int _last_x;
+ private int _last_y;
+ private int _last_z;
+ private int _last_yaw;
+ private int _x;
+ private int _y;
+ private int _z;
+ private int _yaw;
+ private boolean inited = false;
+ private static Object classCookie = new Object();
+
+ public InterpolatedDrone(ObjID objID, WorldServer serv) {
+ super(objID, serv);
+ }
+
+ public InterpolatedDrone() {
+ }
+
+ @Override
+ public Point3Temp getVelocity() {
+ return Point3Temp.make(this._vel_x, this._vel_y, this._vel_z);
+ }
+
+ @Override
+ public int getYawRate() {
+ return this._vel_yaw;
+ }
+
+ @Override
+ public boolean handle(FrameEvent fe) {
+ if (this._server == null) {
+ return true;
+ } else {
+ int timeNow = fe.time;
+ this.interpolate(timeNow, this._server.getUpdateTime(), this);
+ return true;
+ }
+ }
+
+ @Override
+ public void interpolate(int timeNow, int updateTime, Transform target) {
+ if (this.inited) {
+ if (timeNow - this._last_PosTime > updateTime) {
+ this._last_PosTime = timeNow;
+ this._vel_x = this._last_x - this._x;
+ this._vel_y = this._last_y - this._y;
+ this._vel_z = this._last_z - this._z;
+ this._vel_yaw = ((this._last_yaw - this._yaw) % 360 + 360) % 360;
+
+ assert this._vel_yaw >= 0;
+
+ if (this._vel_yaw > 180) {
+ this._vel_yaw -= 360;
+ }
+ }
+
+ double timeDiff = (double)(timeNow - this._last_FrameTime) / updateTime;
+ if (timeNow - this._last_FrameTime > updateTime) {
+ timeDiff = 0.0;
+ }
+
+ this._x = this._x + (int)(timeDiff * this._vel_x);
+ this._y = this._y + (int)(timeDiff * this._vel_y);
+ this._z = this._z + (int)(timeDiff * this._vel_z);
+ this._yaw = this._yaw + (int)(timeDiff * this._vel_yaw) % 360;
+ target.makeIdentity().moveBy(this._x, this._y, this._z).yaw(this._yaw);
+ this._last_FrameTime = timeNow;
+ }
+ }
+
+ @Override
+ public void reset(short x, short y, short z, short yaw) {
+ this._x = x;
+ this._y = y;
+ this._z = z;
+ this._yaw = yaw;
+ this._vel_x = this._vel_y = this._vel_z = 0;
+ this._vel_yaw = 0;
+ this._last_x = this._x;
+ this._last_y = this._y;
+ this._last_z = this._z;
+ this._last_yaw = this._yaw;
+ this._last_PosTime = this._last_FrameTime = Std.getRealTime();
+ this.inited = true;
+ }
+
+ @Override
+ public void appear(Room rm, short x, short y, short z, short yaw) {
+ assert rm != null;
+
+ BlackBox.getInstance().submitEvent(new BBAppearDroneCommand(rm.toString(), this.getName(), x, y, z, yaw));
+ if (this.getRoom() != rm) {
+ this.detach();
+ rm.add(this);
+ }
+
+ this.makeIdentity().moveBy(x, y, z).yaw(yaw);
+ this._x = x;
+ this._y = y;
+ this._z = z;
+ this._yaw = yaw;
+ this._vel_x = this._vel_y = this._vel_z = 0;
+ this._vel_yaw = 0;
+ this._last_x = x;
+ this._last_y = y;
+ this._last_z = z;
+ this._last_yaw = yaw;
+ this._last_PosTime = this._last_FrameTime = Std.getRealTime();
+ URL u = this.getCurrentURL();
+ if (u != null) {
+ this.setAvatarNow(u);
+ }
+
+ this.inited = true;
+ }
+
+ @Override
+ public void disappear() {
+ BlackBox.getInstance().submitEvent(new BBDisappearDroneCommand(this.getName()));
+ this.detachFromServer(true);
+ this.detach();
+ }
+
+ @Override
+ public void longLoc(short x, short y, short z, short yaw) {
+ if (!(this.getOwner() instanceof Pilot)) {
+ BlackBox.getInstance().submitEvent(new BBMoveDroneCommand(this.getName(), x, y, z, yaw));
+ }
+
+ this._last_x = x;
+ this._last_y = y;
+ this._last_z = z;
+ this._last_yaw = yaw;
+ this._vel_x = this._last_x - this._x;
+ this._vel_y = this._last_y - this._y;
+ this._vel_z = this._last_z - this._z;
+ this._vel_yaw = ((this._last_yaw - this._yaw) % 360 + 360) % 360;
+
+ assert this._vel_yaw >= 0;
+
+ if (this._vel_yaw > 180) {
+ this._vel_yaw -= 360;
+ }
+
+ this._last_PosTime = Std.getRealTime();
+ this.inited = true;
+ }
+
+ @Override
+ protected void transferFrom(Drone d) {
+ super.transferFrom(d);
+ if (d instanceof InterpolatedDrone) {
+ InterpolatedDrone i = (InterpolatedDrone)d;
+ this._x = i._x;
+ this._y = i._y;
+ this._z = i._z;
+ this._yaw = i._yaw;
+ this._vel_x = i._vel_x;
+ this._vel_y = i._vel_y;
+ this._vel_z = i._vel_z;
+ this._vel_yaw = i._vel_yaw;
+ this._last_x = i._last_x;
+ this._last_y = i._last_y;
+ this._last_z = i._last_z;
+ this._last_yaw = i._last_yaw;
+ this._last_PosTime = i._last_PosTime;
+ this._last_FrameTime = i._last_FrameTime;
+ this.inited = true;
+ }
+ }
+
+ @Override
+ public void roomChange(Room newRoom, short x, short y, short z, short yaw) {
+ this.detach();
+ if (newRoom != null) {
+ this.appear(newRoom, x, y, z, yaw);
+ }
+ }
+
+ @Override
+ public void shortLoc(byte dx, byte dy, byte dyaw) {
+ if (!(this.getOwner() instanceof Pilot)) {
+ BlackBox.getInstance().submitEvent(new BBDroneDeltaPosCommand(this.getName(), dx, dy, dyaw));
+ }
+
+ this._last_x += dx;
+ this._last_y += dy;
+ this._last_yaw += dyaw;
+ this._last_yaw %= 360;
+ this._vel_x = this._last_x - this._x;
+ this._vel_y = this._last_y - this._y;
+ this._vel_z = 0;
+ this._vel_yaw = ((this._last_yaw - this._yaw) % 360 + 360) % 360;
+
+ assert this._vel_yaw >= 0;
+
+ if (this._vel_yaw > 180) {
+ this._vel_yaw -= 360;
+ }
+
+ this._last_PosTime = Std.getRealTime();
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ int var10000 = index - offset;
+ return super.properties(index, offset + 0, mode, value);
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(0, classCookie);
+ super.saveState(s);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/InventoryAction.java b/NET/worlds/scape/InventoryAction.java
new file mode 100644
index 0000000..33d4e65
--- /dev/null
+++ b/NET/worlds/scape/InventoryAction.java
@@ -0,0 +1,28 @@
+package NET.worlds.scape;
+
+public class InventoryAction extends InventoryItem {
+ public InventoryAction(String id, String name) {
+ super(id, name);
+ }
+
+ public InventoryAction(String id, String name, int qty) {
+ super(id, name, qty);
+ }
+
+ public InventoryAction(InventoryAction in) {
+ super(in);
+ }
+
+ @Override
+ public InventoryItem cloneItem() {
+ return new InventoryAction(this);
+ }
+
+ public static InventoryAction createAction(String id, String name, int qty) {
+ return (InventoryAction)(id.equals("H") ? new HighJump(id, name, qty) : new InventoryAction(id, name, qty));
+ }
+
+ public boolean doAction() {
+ return true;
+ }
+}
diff --git a/NET/worlds/scape/InventoryAvatar.java b/NET/worlds/scape/InventoryAvatar.java
new file mode 100644
index 0000000..dfd7b47
--- /dev/null
+++ b/NET/worlds/scape/InventoryAvatar.java
@@ -0,0 +1,20 @@
+package NET.worlds.scape;
+
+public class InventoryAvatar extends InventoryItem {
+ public InventoryAvatar(String id, String name) {
+ super(id, name);
+ }
+
+ public InventoryAvatar(String id, String name, int qty) {
+ super(id, name, qty);
+ }
+
+ public InventoryAvatar(InventoryAvatar in) {
+ super(in);
+ }
+
+ @Override
+ public InventoryItem cloneItem() {
+ return new InventoryAvatar(this);
+ }
+}
diff --git a/NET/worlds/scape/InventoryCallback.java b/NET/worlds/scape/InventoryCallback.java
new file mode 100644
index 0000000..5835472
--- /dev/null
+++ b/NET/worlds/scape/InventoryCallback.java
@@ -0,0 +1,5 @@
+package NET.worlds.scape;
+
+public interface InventoryCallback {
+ void droppedInventoryItem(Object var1);
+}
diff --git a/NET/worlds/scape/InventoryDialog.java b/NET/worlds/scape/InventoryDialog.java
new file mode 100644
index 0000000..d3b1f93
--- /dev/null
+++ b/NET/worlds/scape/InventoryDialog.java
@@ -0,0 +1,310 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.ImageCanvas;
+import NET.worlds.console.PolledDialog;
+import NET.worlds.network.URL;
+import java.awt.Button;
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Frame;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Label;
+import java.util.Vector;
+
+public class InventoryDialog extends PolledDialog {
+ private InventoryList rightWristItems_;
+ private ImageCanvas rightWristIcon_;
+ private InventoryList leftWristItems_;
+ private ImageCanvas leftWristIcon_;
+ private InventoryList headItems_;
+ private ImageCanvas headIcon_;
+ private InventoryList rightAnkleItems_;
+ private ImageCanvas rightAnkleIcon_;
+ private InventoryList leftAnkleItems_;
+ private ImageCanvas leftAnkleIcon_;
+ private Button okButton_;
+ private Button cancelButton_;
+ private Frame parent_;
+ private static final URL defaultImageURL = URL.make("home:..\\default.gif");
+ private static Object lastPosAndSize;
+
+ public InventoryDialog(Frame frame) {
+ super(frame, null, Console.message("Inventory"), true);
+ InventoryManager im = InventoryManager.getInventoryManager();
+ Vector equippableItems = im.getEquippableItems();
+ Vector equippedItems = im.getEquippedItems();
+ this.parent_ = frame;
+ this.rightWristItems_ = new InventoryList();
+ this.leftWristItems_ = new InventoryList();
+ this.headItems_ = new InventoryList();
+ this.rightAnkleItems_ = new InventoryList();
+ this.leftAnkleItems_ = new InventoryList();
+ this.rightWristIcon_ = new ImageCanvas(defaultImageURL);
+ this.leftWristIcon_ = new ImageCanvas(defaultImageURL);
+ this.headIcon_ = new ImageCanvas(defaultImageURL);
+ this.leftAnkleIcon_ = new ImageCanvas(defaultImageURL);
+ this.rightAnkleIcon_ = new ImageCanvas(defaultImageURL);
+ this.okButton_ = new Button("Ok");
+ this.cancelButton_ = new Button("Cancel");
+
+ for (int i = 0; i < equippableItems.size(); i++) {
+ EquippableItem item = (EquippableItem)equippableItems.elementAt(i);
+ switch (item.getBodyLocation()) {
+ case 4:
+ this.headItems_.add(item);
+ break;
+ case 8:
+ this.rightWristItems_.add(item);
+ break;
+ case 13:
+ this.leftWristItems_.add(item);
+ break;
+ case 17:
+ this.rightAnkleItems_.add(item);
+ break;
+ case 21:
+ this.leftAnkleItems_.add(item);
+ }
+ }
+
+ for (int i = 0; i < equippedItems.size(); i++) {
+ EquippableItem item = (EquippableItem)equippedItems.elementAt(i);
+ switch (item.getBodyLocation()) {
+ case 4:
+ this.headItems_.selectItem(item);
+ break;
+ case 8:
+ this.rightWristItems_.selectItem(item);
+ break;
+ case 13:
+ this.leftWristItems_.selectItem(item);
+ break;
+ case 17:
+ this.rightAnkleItems_.selectItem(item);
+ break;
+ case 21:
+ this.leftAnkleItems_.selectItem(item);
+ }
+ }
+
+ this.ready();
+ }
+
+ @Override
+ protected void build() {
+ this.setBackground(Color.cyan);
+ this.setForeground(Color.black);
+ GridBagLayout gbag = new GridBagLayout();
+ this.setLayout(gbag);
+ GridBagConstraints c = new GridBagConstraints();
+ Font f1 = new Font(Console.message("ConsoleFont"), 1, 18);
+ Font f2 = new Font(Console.message("ConsoleFont"), 0, 12);
+ Label invLabel = new Label("Inventory");
+ c.gridx = 2;
+ c.gridy = 0;
+ c.weightx = 3.0;
+ invLabel.setFont(f1);
+ this.add(gbag, invLabel, c);
+ Label rwLabel = new Label("Right Hand");
+ c.gridx = 4;
+ c.gridy = 4;
+ c.weightx = 1.0;
+ rwLabel.setFont(f2);
+ this.add(gbag, rwLabel, c);
+ c.gridy = 5;
+ c.weighty = 1.0;
+ this.rightWristItems_.setFont(f2);
+ this.add(gbag, this.rightWristItems_, c);
+ c.gridx = 3;
+ c.gridy = 5;
+ c.weighty = 1.0;
+ c.weightx = 1.0;
+ this.add(gbag, this.rightWristIcon_, c);
+ Label lwLabel = new Label("Left Hand");
+ c.gridx = 0;
+ c.gridy = 4;
+ c.weighty = 1.0;
+ lwLabel.setFont(f2);
+ this.add(gbag, lwLabel, c);
+ c.gridy = 5;
+ c.weighty = 1.0;
+ this.leftWristItems_.setFont(f2);
+ this.add(gbag, this.leftWristItems_, c);
+ c.gridx = 1;
+ c.gridy = 5;
+ c.weighty = 1.0;
+ c.weightx = 1.0;
+ this.add(gbag, this.leftWristIcon_, c);
+ Label headLabel = new Label("Head");
+ c.gridx = 2;
+ c.gridy = 2;
+ c.weighty = 1.0;
+ headLabel.setFont(f2);
+ this.add(gbag, headLabel, c);
+ c.gridy = 3;
+ c.weighty = 1.0;
+ this.headItems_.setFont(f2);
+ this.add(gbag, this.headItems_, c);
+ c.gridx = 2;
+ c.gridy = 4;
+ c.weighty = 1.0;
+ c.weightx = 1.0;
+ this.add(gbag, this.headIcon_, c);
+ Label raLabel = new Label("Right Foot");
+ c.gridx = 4;
+ c.gridy = 6;
+ c.weightx = 1.0;
+ raLabel.setFont(f2);
+ this.add(gbag, raLabel, c);
+ c.gridy = 7;
+ c.weighty = 0.0;
+ this.rightAnkleItems_.setFont(f2);
+ this.add(gbag, this.rightAnkleItems_, c);
+ c.gridx = 3;
+ c.gridy = 7;
+ c.weighty = 1.0;
+ c.weightx = 1.0;
+ this.add(gbag, this.rightAnkleIcon_, c);
+ Label laLabel = new Label("Left Foot");
+ c.gridx = 0;
+ c.gridy = 6;
+ c.weighty = 1.0;
+ laLabel.setFont(f2);
+ this.add(gbag, laLabel, c);
+ c.gridy = 7;
+ c.weighty = 0.0;
+ this.leftAnkleItems_.setFont(f2);
+ this.add(gbag, this.leftAnkleItems_, c);
+ c.gridx = 1;
+ c.gridy = 7;
+ c.weighty = 1.0;
+ c.weightx = 1.0;
+ this.add(gbag, this.leftAnkleIcon_, c);
+ c.gridx = 0;
+ c.gridy = 10;
+ c.weightx = 2.0;
+ c.weighty = 1.0;
+ this.okButton_.setFont(f2);
+ this.add(gbag, this.okButton_, c);
+ c.gridx = 4;
+ c.gridy = 10;
+ this.cancelButton_.setFont(f2);
+ this.add(gbag, this.cancelButton_, c);
+ this.setSize(360, 300);
+ }
+
+ @Override
+ public synchronized boolean done(boolean confirmed) {
+ Vector equippedItems = new Vector();
+ EquippableItem eItem;
+ if ((eItem = this.rightWristItems_.getSelected()) != null) {
+ equippedItems.add(eItem);
+ }
+
+ if ((eItem = this.leftWristItems_.getSelected()) != null) {
+ equippedItems.add(eItem);
+ }
+
+ if ((eItem = this.headItems_.getSelected()) != null) {
+ equippedItems.add(eItem);
+ }
+
+ if ((eItem = this.leftAnkleItems_.getSelected()) != null) {
+ equippedItems.add(eItem);
+ }
+
+ if ((eItem = this.rightAnkleItems_.getSelected()) != null) {
+ equippedItems.add(eItem);
+ }
+
+ if (confirmed) {
+ InventoryManager im = InventoryManager.getInventoryManager();
+ im.setEquippedItems(equippedItems);
+ }
+
+ return super.done(confirmed);
+ }
+
+ @Override
+ public boolean handleEvent(java.awt.Event event) {
+ return super.handleEvent(event);
+ }
+
+ @Override
+ public boolean action(java.awt.Event event, Object what) {
+ Object target = event.target;
+ URL imageURL = defaultImageURL;
+ if (target == this.leftWristItems_) {
+ InventoryItem item = this.leftWristItems_.getSelected();
+ if (item != null) {
+ imageURL = item.getItemGraphicLocation();
+ }
+
+ this.setIcon(this.leftWristIcon_, imageURL);
+ return true;
+ } else if (target == this.rightWristItems_) {
+ InventoryItem item = this.rightWristItems_.getSelected();
+ if (item != null) {
+ imageURL = item.getItemGraphicLocation();
+ }
+
+ this.setIcon(this.rightWristIcon_, imageURL);
+ return true;
+ } else if (target == this.headItems_) {
+ InventoryItem item = this.headItems_.getSelected();
+ if (item != null) {
+ imageURL = item.getItemGraphicLocation();
+ }
+
+ this.setIcon(this.headIcon_, imageURL);
+ return true;
+ } else if (target == this.leftAnkleItems_) {
+ InventoryItem item = this.leftAnkleItems_.getSelected();
+ if (item != null) {
+ imageURL = item.getItemGraphicLocation();
+ }
+
+ this.setIcon(this.leftAnkleIcon_, imageURL);
+ return true;
+ } else if (target == this.rightAnkleItems_) {
+ InventoryItem item = this.rightAnkleItems_.getSelected();
+ if (item != null) {
+ imageURL = item.getItemGraphicLocation();
+ }
+
+ this.setIcon(this.rightAnkleIcon_, imageURL);
+ return true;
+ } else if (target == this.okButton_) {
+ return this.done(true);
+ } else {
+ return target == this.cancelButton_ ? this.done(false) : false;
+ }
+ }
+
+ private void setIcon(ImageCanvas ic, URL newLoc) {
+ ic.setNewImage(newLoc, this.getGraphics());
+ this.repaint();
+ }
+
+ @Override
+ public void savePosAndSize(Object state) {
+ lastPosAndSize = state;
+ }
+
+ @Override
+ public Object restorePosAndSize() {
+ return lastPosAndSize;
+ }
+
+ @Override
+ public boolean keyDown(java.awt.Event event, int key) {
+ return key == 27 ? this.done(false) : super.keyDown(event, key);
+ }
+
+ @Override
+ protected synchronized void activeCallback() {
+ this.notify();
+ }
+}
diff --git a/NET/worlds/scape/InventoryItem.java b/NET/worlds/scape/InventoryItem.java
new file mode 100644
index 0000000..22fbd30
--- /dev/null
+++ b/NET/worlds/scape/InventoryItem.java
@@ -0,0 +1,65 @@
+package NET.worlds.scape;
+
+import NET.worlds.network.URL;
+
+public class InventoryItem {
+ protected String itemId_;
+ protected String itemName_;
+ protected int itemQuantity_;
+ protected URL itemGraphicLocation_;
+
+ public InventoryItem(String id, String name) {
+ this.itemId_ = id;
+ this.itemName_ = name;
+ this.itemQuantity_ = 1;
+ }
+
+ public InventoryItem(String id, String name, int qty) {
+ this.itemId_ = id;
+ this.itemName_ = name;
+ this.itemQuantity_ = qty;
+ }
+
+ public InventoryItem(InventoryItem in) {
+ this.itemId_ = in.itemId_;
+ this.itemName_ = in.itemName_;
+ this.itemQuantity_ = in.itemQuantity_;
+ this.itemGraphicLocation_ = in.itemGraphicLocation_;
+ }
+
+ public String getItemId() {
+ return this.itemId_;
+ }
+
+ public void setItemId(String id) {
+ this.itemId_ = id;
+ }
+
+ public String getItemName() {
+ return this.itemName_;
+ }
+
+ public void setItemName(String name) {
+ this.itemName_ = name;
+ }
+
+ public int getItemQuantity() {
+ return this.itemQuantity_;
+ }
+
+ public void setQuantity(int qty) {
+ this.itemQuantity_ = qty;
+ }
+
+ public URL getItemGraphicLocation() {
+ return this.itemGraphicLocation_;
+ }
+
+ public void setItemGraphicLocation(URL newLoc) {
+ this.itemGraphicLocation_ = newLoc;
+ }
+
+ public InventoryItem cloneItem() {
+ return new InventoryItem(this);
+ }
+}
diff --git a/NET/worlds/scape/InventoryList.java b/NET/worlds/scape/InventoryList.java
new file mode 100644
index 0000000..250f9df
--- /dev/null
+++ b/NET/worlds/scape/InventoryList.java
@@ -0,0 +1,26 @@
+package NET.worlds.scape;
+
+import java.awt.Choice;
+import java.util.Vector;
+
+class InventoryList extends Choice {
+ private Vector invItems_ = new Vector();
+
+ public InventoryList() {
+ super.add("None");
+ }
+
+ public EquippableItem getSelected() {
+ int selectedIndex = super.getSelectedIndex();
+ return selectedIndex > 0 ? (EquippableItem)this.invItems_.elementAt(selectedIndex - 1) : null;
+ }
+
+ public void add(EquippableItem item) {
+ super.add(item.getItemName());
+ this.invItems_.add(item);
+ }
+
+ public void selectItem(EquippableItem item) {
+ super.select(item.getItemName());
+ }
+}
diff --git a/NET/worlds/scape/InventoryManager.java b/NET/worlds/scape/InventoryManager.java
new file mode 100644
index 0000000..641619a
--- /dev/null
+++ b/NET/worlds/scape/InventoryManager.java
@@ -0,0 +1,315 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.ActionsPart;
+import NET.worlds.console.Console;
+import NET.worlds.console.TradeDialog;
+import NET.worlds.console.WhisperManager;
+import NET.worlds.core.ServerTableManager;
+import NET.worlds.network.URL;
+import java.net.MalformedURLException;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+public class InventoryManager {
+ private static InventoryManager manager_;
+ private Hashtable<String, InventoryItem> masterList_;
+ private Hashtable<String, InventoryItem> inventory_ = new Hashtable<String, InventoryItem>();
+ private boolean initialized_;
+ private Vector<InventoryItem> equipped_;
+
+ public synchronized void setEquippedItems(Vector<InventoryItem> equippedItems) {
+ this.removeEquippedItems();
+ this.equipped_ = equippedItems;
+ this.equipItems();
+ }
+
+ public synchronized Vector<InventoryItem> getEquippedItems() {
+ return this.equipped_;
+ }
+
+ private synchronized void removeEquippedItems() {
+ for (int i = 0; i < this.equipped_.size(); i++) {
+ EquippableItem itemToEquip = (EquippableItem)this.equipped_.elementAt(i);
+ Shape ownedShape = itemToEquip.getOwnedShape();
+ if (ownedShape != null) {
+ ownedShape.detach();
+ }
+
+ itemToEquip.setOwnedShape(null);
+ }
+ }
+
+ private synchronized void equipItems() {
+ System.out.println("Equipped Items Size: " + this.equipped_.size());
+
+ for (int i = 0; i < this.equipped_.size(); i++) {
+ Shape itemShape = new Shape();
+ EquippableItem itemToEquip = (EquippableItem)this.equipped_.elementAt(i);
+ if (itemToEquip != null) {
+ try {
+ itemShape.setURL(new URL(itemToEquip.getModelLocation()));
+ } catch (MalformedURLException var10) {
+ System.out.println("Badly formed URL for " + itemToEquip.getItemName());
+ continue;
+ }
+
+ float s = itemToEquip.getScale();
+ itemShape.scale(s, s, s);
+ itemShape.pitch(itemToEquip.getPitch());
+ itemShape.roll(itemToEquip.getRoll());
+ itemShape.yaw(itemToEquip.getYaw());
+ itemShape.moveBy(itemToEquip.getXPos(), itemToEquip.getYPos(), itemToEquip.getZPos());
+ int properLoc = itemToEquip.getBodyLocation();
+ DeepEnumeration de = new DeepEnumeration();
+ Pilot.getActive().getChildren(de);
+
+ while (de.hasMoreElements()) {
+ Object obj = de.nextElement();
+ if (obj instanceof Shape) {
+ Shape objShape = (Shape)obj;
+ int partType = objShape.getBodPartNum();
+ if (partType == properLoc) {
+ objShape.add(itemShape);
+ itemToEquip.setOwnedShape(itemShape);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public Vector<InventoryItem> getEquippableItems() {
+ Vector<InventoryItem> retVal = new Vector<InventoryItem>();
+ Enumeration<InventoryItem> invEnum = this.inventory_.elements();
+
+ while (invEnum.hasMoreElements()) {
+ InventoryItem obj = invEnum.nextElement();
+ if (obj instanceof EquippableItem) {
+ retVal.addElement(obj);
+ }
+ }
+
+ return retVal;
+ }
+
+ public Vector<InventoryItem> getInventoryAvatars() {
+ Vector<InventoryItem> retVal = new Vector<InventoryItem>();
+ Enumeration<InventoryItem> invEnum = this.inventory_.elements();
+
+ while (invEnum.hasMoreElements()) {
+ InventoryItem obj = invEnum.nextElement();
+ if (obj instanceof InventoryAvatar) {
+ retVal.addElement(obj);
+ }
+ }
+
+ return retVal;
+ }
+
+ public Hashtable<String, InventoryItem> getInventoryItems() {
+ return this.inventory_;
+ }
+
+ public int checkInventoryFor(String nm) {
+ InventoryItem it = this.inventory_.get(nm);
+ return it != null ? it.getItemQuantity() : 0;
+ }
+
+ public Vector<InventoryItem> getInventoryActionList() {
+ Vector<InventoryItem> retVal = new Vector<InventoryItem>();
+ Enumeration<InventoryItem> invEnum = this.inventory_.elements();
+
+ while (invEnum.hasMoreElements()) {
+ InventoryItem obj = invEnum.nextElement();
+ if (obj instanceof InventoryAction) {
+ retVal.addElement(obj);
+ }
+ }
+
+ return retVal;
+ }
+
+ public void doInventoryAction(String act) {
+ Vector<InventoryItem> actVector = this.getInventoryActionList();
+
+ for (int i = 0; i < actVector.size(); i++) {
+ InventoryAction invAct = (InventoryAction)actVector.elementAt(i);
+ if (invAct.getItemName().equalsIgnoreCase(act)) {
+ invAct.doAction();
+ String msg = "&|+deal>trade " + invAct.getItemId() + ",";
+ TradeDialog.sendTradeMessage(msg);
+ }
+ }
+ }
+
+ public void setInventory(String invString) {
+ this.initialized_ = true;
+ Hashtable<String, InventoryItem> newInv = this.parseInventoryString(invString);
+ this.inventory_ = newInv;
+ Enumeration<TradeDialog> e = WhisperManager.whisperManager().tradeDialogs().elements();
+
+ while (e.hasMoreElements()) {
+ TradeDialog wd = e.nextElement();
+ wd.setTrading(true);
+ }
+
+ if (Console.getActive() != null) {
+ Console a = Console.getActive();
+ a.inventoryChanged();
+ if (a.targetValid != a.isValidAv()) {
+ a.resetAvatar();
+ }
+ }
+
+ ActionsPart.updateActionDialog();
+ }
+
+ public Hashtable<String, InventoryItem> parseInventoryString(String invString) {
+ Hashtable<String, InventoryItem> newInventory = new Hashtable<String, InventoryItem>();
+ if (invString == null) {
+ return newInventory;
+ } else {
+ int len = invString.length();
+ int itemStart = 0;
+
+ while (itemStart < len) {
+ char ch = invString.charAt(itemStart);
+ if (ch < 'A' || ch > 'Z') {
+ System.out.println("Bad inventory: " + invString);
+ return newInventory;
+ }
+
+ int descLen;
+ for (descLen = 1; itemStart + descLen < len; descLen++) {
+ ch = invString.charAt(itemStart + descLen);
+ if (ch < 'a' || ch > 'z') {
+ break;
+ }
+ }
+
+ String shortName = invString.substring(itemStart, itemStart + descLen);
+ int countStart = itemStart + descLen;
+ int countLen = 0;
+
+ while (true) {
+ if (countLen + countStart < len) {
+ ch = invString.charAt(countStart + countLen);
+ if (ch >= '0' && ch <= '9') {
+ countLen++;
+ continue;
+ }
+ }
+
+ int count = 1;
+ if (countLen > 0) {
+ count = Integer.parseInt(invString.substring(countStart, countStart + countLen));
+ }
+
+ InventoryItem foundItem = this.masterList_.get(shortName);
+ if (foundItem != null) {
+ InventoryItem newItem = foundItem.cloneItem();
+ newItem.setQuantity(count);
+ newInventory.put(shortName, newItem);
+ }
+
+ itemStart = countStart + countLen;
+ break;
+ }
+ }
+
+ return newInventory;
+ }
+ }
+
+ public String properCase(String s) {
+ return s.equals("") ? s : s.substring(0, 1).toUpperCase() + s.substring(1);
+ }
+
+ public String getSingular(String sn) {
+ InventoryItem item = this.masterList_.get(sn);
+ return item != null ? item.getItemName() : "unknown" + sn;
+ }
+
+ public String getPlural(String sn) {
+ return this.getSingular(sn) + "s";
+ }
+
+ public String itemName(String sn, int num) {
+ return num == 1 ? "a " + this.getSingular(sn) : num + " " + this.getPlural(sn);
+ }
+
+ public String itemName(InventoryItem item) {
+ return this.itemName(item.getItemId(), item.getItemQuantity());
+ }
+
+ private InventoryManager() {
+ this.masterList_ = new Hashtable<String, InventoryItem>();
+ this.initialized_ = false;
+ this.equipped_ = new Vector<InventoryItem>();
+ ServerTableManager stm = ServerTableManager.instance();
+ int invVersion = stm.getFileVersion();
+ String[] invStrings = stm.getTable("invList");
+ String[] graphicStrings = new String[0];
+ if (invVersion > 1) {
+ graphicStrings = stm.getTable("graphicList");
+ }
+
+ URL defaultImageURL = URL.make("home:..\\default.gif");
+ if (invStrings != null) {
+ int numStringsPerItem = 12;
+
+ for (int i = 0; i < invStrings.length; i += numStringsPerItem) {
+ String id = invStrings[i];
+ String name = invStrings[i + 2];
+ String model = invStrings[i + 3];
+ int loc = Double.valueOf(invStrings[i + 4]).intValue();
+ float scale = Double.valueOf(invStrings[i + 5]).floatValue();
+ int pitch = Double.valueOf(invStrings[i + 6]).intValue();
+ int roll = Double.valueOf(invStrings[i + 7]).intValue();
+ int yaw = Double.valueOf(invStrings[i + 8]).intValue();
+ float xPos = Double.valueOf(invStrings[i + 9]).floatValue();
+ float yPos = Double.valueOf(invStrings[i + 10]).floatValue();
+ float zPos = Double.valueOf(invStrings[i + 11]).floatValue();
+ URL graphic = null;
+ if (invVersion > 1 && graphicStrings.length > i / 6 + 1) {
+ String gString = graphicStrings[i / 6 + 1];
+ if (gString != "default") {
+ graphic = URL.make(gString);
+ }
+ }
+
+ if (graphic == null) {
+ graphic = defaultImageURL;
+ }
+
+ InventoryItem newItem;
+ if (id.charAt(0) == 'H') {
+ newItem = InventoryAction.createAction(id, name, 1);
+ } else if (id.charAt(0) == 'W') {
+ newItem = new EquippableItem(id, name, 1, model, scale, loc, xPos, yPos, zPos, pitch, roll, yaw);
+ } else if (id.charAt(0) == 'V') {
+ newItem = new InventoryAvatar(id, name, 1);
+ } else {
+ newItem = new InventoryItem(id, name, 1);
+ }
+
+ newItem.setItemGraphicLocation(graphic);
+ this.masterList_.put(id, newItem);
+ }
+ }
+ }
+
+ public static InventoryManager getInventoryManager() {
+ if (manager_ == null) {
+ manager_ = new InventoryManager();
+ }
+
+ return manager_;
+ }
+
+ public boolean inventoryInitialized() {
+ return this.initialized_;
+ }
+}
diff --git a/NET/worlds/scape/ItemNotAvailableDialog.java b/NET/worlds/scape/ItemNotAvailableDialog.java
new file mode 100644
index 0000000..c70268f
--- /dev/null
+++ b/NET/worlds/scape/ItemNotAvailableDialog.java
@@ -0,0 +1,42 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.DialogReceiver;
+import NET.worlds.console.ImageButtons;
+import NET.worlds.console.ImageButtonsCallback;
+import NET.worlds.console.PolledDialog;
+import java.awt.Component;
+import java.awt.Rectangle;
+import java.awt.Window;
+
+public class ItemNotAvailableDialog extends PolledDialog implements ImageButtonsCallback {
+ private ImageButtons ib;
+
+ public ItemNotAvailableDialog(Window parent, DialogReceiver receiver) {
+ super(parent, receiver, Console.message("Not-Available"), false);
+ this.setAlignment(1);
+ Rectangle[] rects = new Rectangle[]{new Rectangle(101, 22, 48, 19)};
+ this.ib = new ImageButtons(Console.message("notavail.gif"), rects, this);
+ this.ready();
+ }
+
+ @Override
+ protected void build() {
+ this.add("Center", this.ib);
+ }
+
+ @Override
+ public Object imageButtonsCallback(Component who, int which) {
+ this.done(false);
+ return null;
+ }
+
+ @Override
+ public boolean keyDown(java.awt.Event event, int key) {
+ if (key == 27) {
+ return this.done(false);
+ } else {
+ return key == 10 ? this.done(false) : super.keyDown(event, key);
+ }
+ }
+}
diff --git a/NET/worlds/scape/Key.java b/NET/worlds/scape/Key.java
new file mode 100644
index 0000000..95f7cff
--- /dev/null
+++ b/NET/worlds/scape/Key.java
@@ -0,0 +1,53 @@
+package NET.worlds.scape;
+
+public interface Key {
+ char bkspace = '\ue308';
+ char tab = '\ue309';
+ char enter = '\ue30d';
+ char shift = '\ue310';
+ char ctrl = '\ue311';
+ char pause = '\ue313';
+ char capLock = '\ue314';
+ char esc = '\ue31b';
+ char pgup = '\ue321';
+ char pgdn = '\ue322';
+ char end = '\ue323';
+ char home = '\ue324';
+ char left = '\ue325';
+ char up = '\ue326';
+ char right = '\ue327';
+ char down = '\ue328';
+ char insert = '\ue32d';
+ char del = '\ue32e';
+ char starPad = '\ue36a';
+ char plusPad = '\ue36b';
+ char minusPad = '\ue36d';
+ char slashPad = '\ue36f';
+ char f1 = '\ue370';
+ char f2 = '\ue371';
+ char f3 = '\ue372';
+ char f4 = '\ue373';
+ char f5 = '\ue374';
+ char f6 = '\ue375';
+ char f7 = '\ue376';
+ char f8 = '\ue377';
+ char f9 = '\ue378';
+ char f11 = '\ue37a';
+ char f12 = '\ue37b';
+ char numLock = '\ue390';
+ char scrollLock = '\ue391';
+ char semicolon = '\ue3ba';
+ char equals = '\ue3bb';
+ char comma = '\ue3bc';
+ char minusKbd = '\ue3bd';
+ char period = '\ue3be';
+ char slashKbd = '\ue3bf';
+ char backQuote = '\ue3c0';
+ char openBrkt = '\ue3db';
+ char backslash = '\ue3dc';
+ char closeBrkt = '\ue3dd';
+ char quote = '\ue3de';
+ char leftMouse = '\ue301';
+ char rightMouse = '\ue302';
+ char centerMouse = '\ue304';
+}
diff --git a/NET/worlds/scape/KeyCharEvent.java b/NET/worlds/scape/KeyCharEvent.java
new file mode 100644
index 0000000..f02227e
--- /dev/null
+++ b/NET/worlds/scape/KeyCharEvent.java
@@ -0,0 +1,12 @@
+package NET.worlds.scape;
+
+public class KeyCharEvent extends KeyEvent {
+ public KeyCharEvent(int time, WObject target, char key) {
+ super(time, null, target, key);
+ }
+
+ @Override
+ public boolean deliver(Object o) {
+ return o instanceof KeyCharHandler && ((KeyCharHandler)o).handle(this) ? true : super.deliver(o);
+ }
+}
diff --git a/NET/worlds/scape/KeyCharHandler.java b/NET/worlds/scape/KeyCharHandler.java
new file mode 100644
index 0000000..648f7f4
--- /dev/null
+++ b/NET/worlds/scape/KeyCharHandler.java
@@ -0,0 +1,5 @@
+package NET.worlds.scape;
+
+public interface KeyCharHandler {
+ boolean handle(KeyCharEvent var1);
+}
diff --git a/NET/worlds/scape/KeyDownEvent.java b/NET/worlds/scape/KeyDownEvent.java
new file mode 100644
index 0000000..5ba9ffb
--- /dev/null
+++ b/NET/worlds/scape/KeyDownEvent.java
@@ -0,0 +1,12 @@
+package NET.worlds.scape;
+
+public class KeyDownEvent extends KeyEvent {
+ public KeyDownEvent(int time, WObject target, char key) {
+ super(time, null, target, key);
+ }
+
+ @Override
+ public boolean deliver(Object o) {
+ return o instanceof KeyDownHandler && ((KeyDownHandler)o).handle(this) ? true : super.deliver(o);
+ }
+}
diff --git a/NET/worlds/scape/KeyDownHandler.java b/NET/worlds/scape/KeyDownHandler.java
new file mode 100644
index 0000000..c2227f4
--- /dev/null
+++ b/NET/worlds/scape/KeyDownHandler.java
@@ -0,0 +1,5 @@
+package NET.worlds.scape;
+
+public interface KeyDownHandler {
+ boolean handle(KeyDownEvent var1);
+}
diff --git a/NET/worlds/scape/KeyEvent.java b/NET/worlds/scape/KeyEvent.java
new file mode 100644
index 0000000..cff81f8
--- /dev/null
+++ b/NET/worlds/scape/KeyEvent.java
@@ -0,0 +1,19 @@
+package NET.worlds.scape;
+
+public class KeyEvent extends UserEvent {
+ char key;
+
+ public KeyEvent(int time, Object source, WObject target, char key) {
+ super(time, source, target);
+ this.key = key;
+ }
+
+ @Override
+ public boolean deliver(Object o) {
+ return o instanceof KeyHandler && ((KeyHandler)o).handle(this) ? true : super.deliver(o);
+ }
+
+ public char getKey() {
+ return this.key;
+ }
+}
diff --git a/NET/worlds/scape/KeyHandler.java b/NET/worlds/scape/KeyHandler.java
new file mode 100644
index 0000000..eb421e4
--- /dev/null
+++ b/NET/worlds/scape/KeyHandler.java
@@ -0,0 +1,5 @@
+package NET.worlds.scape;
+
+public interface KeyHandler {
+ boolean handle(KeyEvent var1);
+}
diff --git a/NET/worlds/scape/KeyUpEvent.java b/NET/worlds/scape/KeyUpEvent.java
new file mode 100644
index 0000000..0976a60
--- /dev/null
+++ b/NET/worlds/scape/KeyUpEvent.java
@@ -0,0 +1,12 @@
+package NET.worlds.scape;
+
+public class KeyUpEvent extends KeyEvent {
+ public KeyUpEvent(int time, WObject target, char key) {
+ super(time, null, target, key);
+ }
+
+ @Override
+ public boolean deliver(Object o) {
+ return o instanceof KeyUpHandler && ((KeyUpHandler)o).handle(this) ? true : super.deliver(o);
+ }
+}
diff --git a/NET/worlds/scape/KeyUpHandler.java b/NET/worlds/scape/KeyUpHandler.java
new file mode 100644
index 0000000..d2fa2e9
--- /dev/null
+++ b/NET/worlds/scape/KeyUpHandler.java
@@ -0,0 +1,5 @@
+package NET.worlds.scape;
+
+public interface KeyUpHandler {
+ boolean handle(KeyUpEvent var1);
+}
diff --git a/NET/worlds/scape/LibEntContentEditorDialog.java b/NET/worlds/scape/LibEntContentEditorDialog.java
new file mode 100644
index 0000000..2311d8c
--- /dev/null
+++ b/NET/worlds/scape/LibEntContentEditorDialog.java
@@ -0,0 +1,131 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.OkCancelDialog;
+import java.awt.Choice;
+import java.awt.GridBagConstraints;
+import java.awt.List;
+import java.awt.TextField;
+import java.util.Enumeration;
+import java.util.StringTokenizer;
+
+class LibEntContentEditorDialog extends OkCancelDialog {
+ private Property property;
+ private TextField strField = new TextField(40);
+ private List list = new List();
+ private Choice choice = new Choice();
+ private EditTile parent;
+ private static String[] choices = new String[]{"WObject files", "Behavior/Action files", "Texture files"};
+ private static String[] dirs = new String[]{LibrariesTile.getLibSubdir(), LibrariesTile.getLibSubdir(), LibrariesTile.getLibSubdir()};
+ private static String[] exts = new String[]{WObject.getSaveExtension(), "class", TextureDecoder.getAllExts()};
+
+ LibEntContentEditorDialog(EditTile parent, String title, Property property) {
+ super(Console.getFrame(), parent, title);
+ this.property = property;
+ this.parent = parent;
+ this.ready();
+ }
+
+ private void matchExt(String name) {
+ int lastDot = name.lastIndexOf(46);
+ if (lastDot != -1) {
+ String ext = name.substring(lastDot + 1).toLowerCase();
+
+ for (int i = 0; i < exts.length; i++) {
+ StringTokenizer t = new StringTokenizer(exts[i], ";");
+
+ while (t.hasMoreTokens()) {
+ if (ext.equals(t.nextToken())) {
+ this.choice.select(i);
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ protected void build() {
+ for (int i = 0; i < choices.length; i++) {
+ this.choice.addItem(choices[i]);
+ }
+
+ String name = (String)this.property.get();
+ if (name == null) {
+ name = "";
+ }
+
+ this.strField.setText(name);
+ this.matchExt(name);
+ this.setListContents();
+ GridBagConstraints c = new GridBagConstraints();
+ c.fill = 2;
+ c.weightx = 1.0;
+ c.weighty = 1.0;
+ c.gridwidth = 0;
+ this.add(this.gbag, this.strField, c);
+ c.gridheight = 6;
+ this.add(this.gbag, this.list, c);
+ c.gridheight = 1;
+ this.add(this.gbag, this.choice, c);
+ super.build();
+ }
+
+ private void setListContents() {
+ int count = this.list.countItems();
+ if (count != 0) {
+ this.list.delItems(0, count - 1);
+ }
+
+ int chosen = this.choice.getSelectedIndex();
+ Enumeration files = new FileList(dirs[chosen], exts[chosen]).getList().elements();
+
+ while (files.hasMoreElements()) {
+ this.list.addItem((String)files.nextElement());
+ }
+
+ String s = (String)this.property.get();
+ this.strField.setText(s != null ? s : "");
+ }
+
+ @Override
+ public boolean handleEvent(java.awt.Event event) {
+ if (event.id == 701) {
+ this.strField.setText(this.list.getSelectedItem());
+ this.strField.selectAll();
+ }
+
+ return super.handleEvent(event);
+ }
+
+ @Override
+ public boolean action(java.awt.Event event, Object what) {
+ if (event.target == this.list) {
+ event.target = this.okButton;
+ }
+
+ if (event.target == this.choice) {
+ this.setListContents();
+ }
+
+ return super.action(event, what);
+ }
+
+ @Override
+ protected boolean setValue() {
+ String text = this.strField.getText().trim();
+ if (text.length() != 0) {
+ this.parent.addUndoableSet(this.property, text);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public void show() {
+ super.show();
+ this.strField.requestFocus();
+ this.strField.selectAll();
+ }
+}
diff --git a/NET/worlds/scape/LibEntContentPropertyEditor.java b/NET/worlds/scape/LibEntContentPropertyEditor.java
new file mode 100644
index 0000000..b7890fa
--- /dev/null
+++ b/NET/worlds/scape/LibEntContentPropertyEditor.java
@@ -0,0 +1,18 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.PolledDialog;
+
+public class LibEntContentPropertyEditor extends PropEditor {
+ private LibEntContentPropertyEditor(Property property) {
+ super(property);
+ }
+
+ @Override
+ public PolledDialog edit(EditTile parent, String title) {
+ return new LibEntContentEditorDialog(parent, title, this.property);
+ }
+
+ public static Property make(Property property) {
+ return property.setEditor(new LibEntContentPropertyEditor(property));
+ }
+}
diff --git a/NET/worlds/scape/LibEventHandler.java b/NET/worlds/scape/LibEventHandler.java
new file mode 100644
index 0000000..38d3d81
--- /dev/null
+++ b/NET/worlds/scape/LibEventHandler.java
@@ -0,0 +1,5 @@
+package NET.worlds.scape;
+
+public interface LibEventHandler {
+ void libraryChanged(Library var1);
+}
diff --git a/NET/worlds/scape/LibrariesTile.java b/NET/worlds/scape/LibrariesTile.java
new file mode 100644
index 0000000..d0fcd5f
--- /dev/null
+++ b/NET/worlds/scape/LibrariesTile.java
@@ -0,0 +1,374 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.Cursor;
+import NET.worlds.console.Main;
+import NET.worlds.console.MainCallback;
+import NET.worlds.core.IniFile;
+import NET.worlds.network.URL;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Point;
+import java.io.File;
+import java.util.Enumeration;
+import java.util.Vector;
+
+public class LibrariesTile extends TabbedPanel implements LibEventHandler, Properties, MainCallback, LibraryDropTarget {
+ private static final int NOTHING = 0;
+ private static final int ADD_LIBRARY = 1;
+ private static final int ADD_ELEMENT = 2;
+ private static URL libURL = URL.make("home:libraries/");
+ private static String libSubdir;
+ private Vector libraries = new Vector();
+ private int queue = 0;
+ private boolean iconsVisible = false;
+ private Cursor dragCursor;
+ private Cursor cantCursor;
+ private LibraryEntry leftClickedOn;
+
+ static {
+ String s = libURL.unalias();
+ libSubdir = s.substring(0, s.length() - 1);
+ }
+
+ public static String getLibSubdir() {
+ return libSubdir;
+ }
+
+ public LibrariesTile() {
+ this.setBackground(Color.lightGray);
+ Vector libNames = new FileList(libSubdir, "library").getList();
+ Enumeration e = libNames.elements();
+
+ while (e.hasMoreElements()) {
+ Library lib = Library.load(URL.make(libURL, (String)e.nextElement()));
+ if (lib != null) {
+ this.addLibrary(lib);
+ }
+ }
+
+ if (this.libraries.size() != 0) {
+ this.select(0);
+ }
+
+ Main.register(this);
+ }
+
+ public synchronized void addLibrary() {
+ if (this.queue == 0) {
+ this.queue = 1;
+ }
+ }
+
+ public synchronized void addElement() {
+ if (this.queue == 0) {
+ this.queue = 2;
+ }
+ }
+
+ @Override
+ public synchronized void mainCallback() {
+ switch (this.queue) {
+ case 1:
+ this.syncAddLibrary(new Library());
+ break;
+ case 2:
+ this.syncAddElement(new LibraryEntry());
+ }
+
+ this.queue = 0;
+ }
+
+ private boolean isUniqueLibraryURL(URL name) {
+ if (name == null) {
+ return false;
+ } else {
+ Enumeration e = this.libraries.elements();
+
+ while (e.hasMoreElements()) {
+ Library lib = (Library)e.nextElement();
+ if (lib.getSourceURL().equals(name)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ }
+
+ private boolean isUniqueLibraryName(String name) {
+ if (name == null) {
+ return false;
+ } else {
+ Enumeration e = this.libraries.elements();
+
+ while (e.hasMoreElements()) {
+ Library lib = (Library)e.nextElement();
+ if (lib.getName().equals(name)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ }
+
+ private void syncAddLibrary(Library lib) {
+ boolean newEntry = lib.getNameMaybeNull() == null;
+ if (!this.isUniqueLibraryURL(lib.getSourceURL())) {
+ int i = 1;
+
+ URL url;
+ do {
+ url = URL.make(libURL, "lib" + i++ + ".library");
+ } while (!this.isUniqueLibraryURL(url));
+
+ lib.setSourceURL(url);
+ }
+
+ if (this.libraries.size() == 0) {
+ File f = new File(libSubdir);
+ f.mkdir();
+ }
+
+ if (!this.isUniqueLibraryName(lib.getNameMaybeNull())) {
+ int num = 1;
+
+ String libName;
+ do {
+ libName = "Category" + num++;
+ } while (!this.isUniqueLibraryName(libName));
+
+ lib.setName(libName);
+ }
+
+ if (this.saveAllowed()) {
+ lib.save();
+ } else {
+ Console.println(Console.message("AllowChangeLibrary"));
+ }
+
+ this.addLibrary(lib);
+ if (newEntry) {
+ this.select(this.libraries.indexOf(lib));
+ }
+ }
+
+ private void syncDeleteLibrary(Library lib) {
+ if (this.saveAllowed()) {
+ lib.delete();
+ } else {
+ Console.println(Console.message("AllowChangeLibrary"));
+ }
+
+ int index = this.libraries.indexOf(lib);
+ this.libraries.removeElementAt(index);
+ this.removeItem(index);
+ }
+
+ private void syncAddElement(LibraryEntry ent) {
+ if (this.libraries.size() != 0) {
+ int selected = this.selected();
+ Library lib = (Library)this.libraries.elementAt(selected);
+ lib.add(ent);
+ }
+ }
+
+ private void addLibrary(Library lib) {
+ int count = this.libraries.size();
+ String name = lib.getName();
+ int i = 0;
+
+ while (i < count && name.compareTo(((Library)this.libraries.elementAt(i)).getName()) >= 0) {
+ i++;
+ }
+
+ this.libraries.insertElementAt(lib, i);
+ this.insertItem(i, lib.getName(), new ScrollingImagePanel(this, lib.getContents(), this.iconsVisible));
+ lib.setEventHandler(this);
+ lib.setOwningDialog(this);
+ }
+
+ public boolean isIconsVisible() {
+ return this.iconsVisible;
+ }
+
+ public void setIconsVisible(boolean showIcons) {
+ this.iconsVisible = showIcons;
+ int count = this.libraries.size();
+
+ for (int i = 0; i < count; i++) {
+ ScrollingImagePanel c = (ScrollingImagePanel)this.getComponent(i);
+ c.setIconsVisible(showIcons);
+ }
+ }
+
+ @Override
+ public void libraryChanged(Library lib) {
+ Library selected = (Library)this.libraries.elementAt(this.selected());
+ int index = this.libraries.indexOf(lib);
+ this.libraries.removeElementAt(index);
+ this.removeItem(index);
+ this.addLibrary(lib);
+ this.select(this.libraries.indexOf(selected));
+ if (this.saveAllowed()) {
+ lib.save();
+ } else {
+ Console.println(Console.message("AllowChangeLibrary"));
+ }
+ }
+
+ private boolean saveAllowed() {
+ return IniFile.gamma().getIniInt("AllowChangeLibrary", 0) == 1;
+ }
+
+ private Library getLibrary(ScrollingImagePanel panel) {
+ int count = this.libraries.size();
+
+ for (int i = 0; i < count; i++) {
+ if (this.getComponent(i) == panel) {
+ return (Library)this.libraries.elementAt(i);
+ }
+ }
+
+ return null;
+ }
+
+ private LibraryEntry getLibraryEntry(Component comp, Point location) {
+ if (comp instanceof ScrollingImagePanel) {
+ ScrollingImagePanel panel = (ScrollingImagePanel)comp;
+ Library lib = this.getLibrary(panel);
+ if (lib != null) {
+ int item = panel.itemAt(location);
+ if (item >= 0) {
+ return lib.getEntry(item);
+ }
+ }
+ }
+
+ return null;
+ }
+
+ private boolean maybeMoveEntry(LibraryEntry src, Component comp, Point loc) {
+ LibraryEntry dst = this.getLibraryEntry(comp, loc);
+ if (dst != null && dst != src) {
+ Library srcOwner = (Library)src.getOwner();
+ Library dstOwner = (Library)dst.getOwner();
+
+ assert srcOwner == dstOwner;
+
+ srcOwner.move(src, dst);
+ return true;
+ } else {
+ if (comp == this) {
+ Library newLib = (Library)this.libraries.elementAt(this.itemAt(loc));
+ Library oldLib = (Library)src.getOwner();
+ if (newLib != oldLib) {
+ oldLib.delete(src);
+ newLib.add(src);
+ return true;
+ }
+ }
+
+ return false;
+ }
+ }
+
+ @Override
+ public void clickEvent(Component who, Point location, int flags) {
+ if ((flags & 1) != 0) {
+ if ((flags & 4) != 0 && who == this) {
+ Console.getFrame().getEditTile().viewProperties(this.libraries.elementAt(this.itemAt(location)));
+ } else {
+ LibraryEntry ent;
+ if ((ent = this.getLibraryEntry(who, location)) != null) {
+ this.leftClickedOn = null;
+ if (ent != null) {
+ if ((flags & 4) != 0) {
+ Console.getFrame().getEditTile().viewProperties(ent);
+ } else {
+ this.leftClickedOn = ent;
+ Console console = Console.getActive();
+ if (this.dragCursor == null) {
+ this.dragCursor = new Cursor(URL.make("home:drag.cur"));
+ } else {
+ this.dragCursor.detach();
+ console.addCursor(this.dragCursor);
+ this.dragCursor.activate();
+ }
+ }
+ }
+ }
+ }
+ } else if ((flags & 2) != 0) {
+ Cursor active = Cursor.getActive();
+ if (active != null && (active == this.dragCursor || active == this.cantCursor)) {
+ Console.getActive().getCursor().activate();
+ }
+
+ if (this.leftClickedOn != null) {
+ if (!this.maybeMoveEntry(this.leftClickedOn, who, location)) {
+ URL url = this.leftClickedOn.getContentURL();
+ String propName = this.leftClickedOn.getPropertyName(true);
+ if (url != null) {
+ Console.getFrame().getEditTile().libraryDrop(url, propName, who, location);
+ }
+ }
+
+ this.leftClickedOn = null;
+ }
+ } else {
+ Cursor activex = Cursor.getActive();
+ boolean isDropTarget = who instanceof LibraryDropTarget;
+ if (activex == this.dragCursor) {
+ if (!isDropTarget) {
+ Console console = Console.getActive();
+ if (this.cantCursor == null) {
+ this.cantCursor = new Cursor(URL.make("system:CANNOT_CURSOR"));
+ } else {
+ this.cantCursor.detach();
+ console.addCursor(this.cantCursor);
+ this.cantCursor.activate();
+ }
+
+ this.cantCursor.activate();
+ }
+ } else if (activex != null && activex == this.cantCursor && isDropTarget) {
+ this.dragCursor.activate();
+ }
+ }
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = PropAdder.make(new VectorProperty(this, index, "Contents"));
+ } else if (mode == 1) {
+ ret = this.libraries;
+ } else if (mode == 3) {
+ this.syncAddLibrary((Library)value);
+ } else if (mode == 4) {
+ this.syncDeleteLibrary((Library)value);
+ } else if (mode == 5 && value instanceof Library) {
+ ret = value;
+ }
+
+ return ret;
+ default:
+ throw new NoSuchPropertyException();
+ }
+ }
+
+ @Override
+ public Object propertyParent() {
+ return null;
+ }
+
+ @Override
+ public String toString() {
+ return "Libraries";
+ }
+}
diff --git a/NET/worlds/scape/Library.java b/NET/worlds/scape/Library.java
new file mode 100644
index 0000000..a531d71
--- /dev/null
+++ b/NET/worlds/scape/Library.java
@@ -0,0 +1,191 @@
+package NET.worlds.scape;
+
+import NET.worlds.network.URL;
+import java.io.File;
+import java.io.IOException;
+import java.util.Vector;
+
+public class Library extends SuperRoot {
+ private Object owningDialog;
+ private Vector contents = new Vector();
+ private LibEventHandler handler;
+ protected String propertyName;
+ private static Object classCookie = new Object();
+
+ public static Library load(URL url) {
+ return (Library)SuperRoot.readFile(url);
+ }
+
+ public Library(URL url, String name) {
+ this.setSourceURL(url);
+ this.setName(name);
+ }
+
+ public Library() {
+ }
+
+ public void save() {
+ try {
+ this.saveFile(this.getSourceURL());
+ } catch (IOException var2) {
+ }
+ }
+
+ public void delete() {
+ new File(this.getSourceURL().unalias()).delete();
+ }
+
+ public void add(LibraryEntry ent) {
+ assert ent.getOwner() == null;
+
+ this.contents.addElement(ent);
+ super.add(ent);
+ this.changed();
+ }
+
+ public void delete(LibraryEntry ent) {
+ boolean found = this.contents.removeElement(ent);
+
+ assert found;
+
+ assert ent.getOwner() == this;
+
+ ent.detach();
+ this.changed();
+ }
+
+ public void move(LibraryEntry src, LibraryEntry dst) {
+ int oldPos = this.contents.indexOf(src);
+
+ assert oldPos != -1;
+
+ int newPos = this.contents.indexOf(dst);
+
+ assert newPos != -1;
+
+ this.contents.removeElement(src);
+ this.contents.insertElementAt(src, newPos);
+ this.changed();
+ }
+
+ void entryChanged(LibraryEntry which) {
+ this.changed();
+ }
+
+ private void changed() {
+ if (this.handler != null) {
+ this.handler.libraryChanged(this);
+ }
+ }
+
+ public Object getOwningDialog() {
+ return this.owningDialog;
+ }
+
+ public Vector getContents() {
+ return (Vector)this.contents.clone();
+ }
+
+ public String getPropertyName() {
+ return this.propertyName;
+ }
+
+ public LibraryEntry getEntry(int index) {
+ return (LibraryEntry)this.contents.elementAt(index);
+ }
+
+ public void setOwningDialog(Object o) {
+ this.owningDialog = o;
+ }
+
+ @Override
+ public void setName(String s) {
+ super.setName(s);
+ this.changed();
+ }
+
+ public void setPropertyName(String s) {
+ this.propertyName = s;
+ this.changed();
+ }
+
+ public void setEventHandler(LibEventHandler handler) {
+ this.handler = handler;
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = PropAdder.make(new VectorProperty(this, index, "Contents"));
+ } else if (mode == 1) {
+ ret = this.getContents();
+ } else if (mode == 4) {
+ this.delete((LibraryEntry)value);
+ } else if (mode == 3) {
+ this.add((LibraryEntry)value);
+ } else if (mode == 5 && value instanceof LibraryEntry) {
+ ret = value;
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Property Name").allowSetNull());
+ } else if (mode == 1) {
+ ret = this.getPropertyName();
+ } else if (mode == 2) {
+ this.setPropertyName((String)value);
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 2, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public Object propertyParent() {
+ return this.getOwningDialog();
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(2, classCookie);
+ super.saveState(s);
+ s.saveVector(this.contents);
+ s.saveString(this.propertyName);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ Vector newContents = null;
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ this.setName(r.restoreString());
+ r.restoreString();
+ r.restoreString();
+ newContents = r.restoreVector();
+ break;
+ case 1:
+ super.restoreState(r);
+ r.restoreString();
+ r.restoreString();
+ newContents = r.restoreVector();
+ break;
+ case 2:
+ super.restoreState(r);
+ newContents = r.restoreVector();
+ this.propertyName = r.restoreString();
+ break;
+ default:
+ throw new TooNewException();
+ }
+
+ for (int i = 0; i < newContents.size(); i++) {
+ this.add((LibraryEntry)newContents.elementAt(i));
+ }
+ }
+}
diff --git a/NET/worlds/scape/LibraryDrop.java b/NET/worlds/scape/LibraryDrop.java
new file mode 100644
index 0000000..1987859
--- /dev/null
+++ b/NET/worlds/scape/LibraryDrop.java
@@ -0,0 +1,5 @@
+package NET.worlds.scape;
+
+public interface LibraryDrop {
+ boolean libraryDrop(EditTile var1, Object var2, boolean var3, boolean var4);
+}
diff --git a/NET/worlds/scape/LibraryDropTarget.java b/NET/worlds/scape/LibraryDropTarget.java
new file mode 100644
index 0000000..1c26d13
--- /dev/null
+++ b/NET/worlds/scape/LibraryDropTarget.java
@@ -0,0 +1,4 @@
+package NET.worlds.scape;
+
+public interface LibraryDropTarget {
+}
diff --git a/NET/worlds/scape/LibraryEntry.java b/NET/worlds/scape/LibraryEntry.java
new file mode 100644
index 0000000..415c35a
--- /dev/null
+++ b/NET/worlds/scape/LibraryEntry.java
@@ -0,0 +1,141 @@
+package NET.worlds.scape;
+
+import NET.worlds.network.URL;
+import java.io.IOException;
+
+public class LibraryEntry extends SuperRoot implements Iconic {
+ protected URL iconURL;
+ protected URL contentURL;
+ protected String propertyName;
+ private static Object classCookie = new Object();
+
+ public LibraryEntry() {
+ }
+
+ public LibraryEntry(String name, URL iconURL) {
+ this.setName(name);
+ this.iconURL = iconURL;
+ }
+
+ private void changed() {
+ Library owner = (Library)this.getOwner();
+ if (owner != null) {
+ owner.entryChanged(this);
+ }
+ }
+
+ @Override
+ public String getIconCaption() {
+ return this.getName();
+ }
+
+ @Override
+ public URL getIconURL() {
+ return this.iconURL;
+ }
+
+ public URL getContentURL() {
+ return this.contentURL;
+ }
+
+ public String getPropertyName(boolean checkParent) {
+ Library owner;
+ return this.propertyName == null && checkParent && (owner = (Library)this.getOwner()) != null ? owner.getPropertyName() : this.propertyName;
+ }
+
+ @Override
+ public void setName(String s) {
+ super.setName(s);
+ this.changed();
+ }
+
+ public void setIconURL(URL s) {
+ this.iconURL = s;
+ this.changed();
+ }
+
+ public void setContentURL(URL s) {
+ this.contentURL = s;
+ this.changed();
+ }
+
+ public void setPropertyName(String s) {
+ this.propertyName = s;
+ this.changed();
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = URLPropertyEditor.make(new Property(this, index, "Icon").allowSetNull(), TextureDecoder.getJavaExts());
+ } else if (mode == 1) {
+ ret = this.getIconURL();
+ } else if (mode == 2) {
+ this.setIconURL((URL)value);
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = URLPropertyEditor.make(new Property(this, index, "Content URL").allowSetNull(), "*wob");
+ } else if (mode == 1) {
+ ret = this.contentURL;
+ } else if (mode == 2) {
+ this.setContentURL((URL)value);
+ }
+ break;
+ case 2:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Property Name").allowSetNull());
+ } else if (mode == 1) {
+ ret = this.getPropertyName(false);
+ } else if (mode == 2) {
+ this.setPropertyName((String)value);
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 3, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(3, classCookie);
+ super.saveState(s);
+ URL.save(s, this.iconURL);
+ URL.save(s, this.contentURL);
+ s.saveString(this.propertyName);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 1:
+ super.restoreState(r);
+ case 0:
+ this.setName(r.restoreString());
+ this.iconURL = URL.restore(r);
+ this.contentURL = URL.restore(r);
+ r.restoreMaybeNull();
+ break;
+ case 2:
+ super.restoreState(r);
+ this.setName(r.restoreString());
+ this.iconURL = URL.restore(r);
+ this.contentURL = URL.restore(r);
+ break;
+ case 3:
+ super.restoreState(r);
+ this.iconURL = URL.restore(r);
+ this.contentURL = URL.restore(r);
+ this.propertyName = r.restoreString();
+ break;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/Light.java b/NET/worlds/scape/Light.java
new file mode 100644
index 0000000..a1e64f6
--- /dev/null
+++ b/NET/worlds/scape/Light.java
@@ -0,0 +1,58 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+public class Light extends WObject {
+ protected int lightID;
+ private static Object classCookie = new Object();
+
+ @Override
+ protected void addRwChildren(WObject parent) {
+ super.addRwChildren(parent);
+ Point3Temp p = this.getWorldPosition();
+ }
+
+ @Override
+ protected void markVoid() {
+ super.markVoid();
+ if (this.lightID != 0) {
+ destroyLight(this.lightID);
+ }
+ }
+
+ @Override
+ protected void noteTransformChange() {
+ super.noteTransformChange();
+ if (this.lightID != 0) {
+ setLightTransform(this.lightID, this.clumpID);
+ }
+ }
+
+ private static native void setLightTransform(int var0, int var1);
+
+ private static native void destroyLight(int var0);
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ int var10000 = index - offset;
+ return super.properties(index, offset + 0, mode, value);
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(0, classCookie);
+ super.saveState(s);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/ListAdderDialog.java b/NET/worlds/scape/ListAdderDialog.java
new file mode 100644
index 0000000..ae3115c
--- /dev/null
+++ b/NET/worlds/scape/ListAdderDialog.java
@@ -0,0 +1,84 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.OkCancelDialog;
+import java.awt.Choice;
+import java.awt.GridBagConstraints;
+import java.util.Enumeration;
+import java.util.Vector;
+
+public abstract class ListAdderDialog extends OkCancelDialog {
+ private Choice list = new Choice();
+ private boolean doSet = false;
+ private int choice;
+ protected EditTile parent;
+
+ public ListAdderDialog(EditTile parent, String title) {
+ super(Console.getFrame(), parent, title);
+ this.parent = parent;
+ }
+
+ @Override
+ protected void build() {
+ GridBagConstraints c = new GridBagConstraints();
+ c.fill = 1;
+ c.weightx = 1.0;
+ c.weighty = 1.0;
+ c.gridwidth = 0;
+ this.add(this.gbag, this.list, c);
+ super.build();
+ }
+
+ protected void setListContents(String[] options) {
+ this.list.removeAll();
+
+ for (int i = 0; i < options.length; i++) {
+ this.list.addItem(options[i]);
+ }
+ }
+
+ protected void setListContents(Vector options) {
+ this.list.removeAll();
+ Enumeration e = options.elements();
+
+ while (e.hasMoreElements()) {
+ this.list.addItem((String)e.nextElement());
+ }
+ }
+
+ protected abstract void add(int var1);
+
+ @Override
+ protected final synchronized void activeCallback() {
+ if (this.doSet) {
+ this.add(this.choice);
+ this.doSet = false;
+ this.notify();
+ }
+ }
+
+ @Override
+ protected synchronized boolean setValue() {
+ if ((this.choice = this.list.getSelectedIndex()) == -1) {
+ return false;
+ } else {
+ this.doSet = true;
+
+ while (this.doSet) {
+ try {
+ this.wait();
+ } catch (InterruptedException var2) {
+ }
+ }
+
+ return true;
+ }
+ }
+
+ @Override
+ public void show() {
+ super.show();
+ this.list.select(0);
+ this.list.requestFocus();
+ }
+}
diff --git a/NET/worlds/scape/ListChooserDialog.java b/NET/worlds/scape/ListChooserDialog.java
new file mode 100644
index 0000000..8b9f1ff
--- /dev/null
+++ b/NET/worlds/scape/ListChooserDialog.java
@@ -0,0 +1,55 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.OkCancelDialog;
+import java.awt.GridBagConstraints;
+import java.awt.List;
+
+public abstract class ListChooserDialog extends OkCancelDialog {
+ private List _listField = new List(5, false);
+ protected EditTile _parent;
+
+ protected ListChooserDialog(EditTile parent, String title) {
+ super(Console.getFrame(), parent, title);
+ this._parent = parent;
+ }
+
+ @Override
+ protected void build() {
+ GridBagConstraints c = new GridBagConstraints();
+ c.weightx = 1.0;
+ c.weighty = 1.0;
+ c.gridwidth = 0;
+ c.fill = 1;
+ this.add(this.gbag, this._listField, c);
+ super.build();
+ }
+
+ protected abstract String getEntry(int var1);
+
+ protected abstract int getSelected();
+
+ protected abstract boolean setValue(String var1, int var2);
+
+ @Override
+ protected boolean setValue() {
+ return this.setValue(this._listField.getSelectedItem(), this._listField.getSelectedIndex());
+ }
+
+ @Override
+ public void show() {
+ super.show();
+ int index = 0;
+
+ for (String entry = this.getEntry(index); entry != null; entry = this.getEntry(++index)) {
+ this._listField.addItem(entry, index);
+ }
+
+ index = this.getSelected();
+ if (index != -1) {
+ this._listField.select(index);
+ }
+
+ this._listField.requestFocus();
+ }
+}
diff --git a/NET/worlds/scape/ListEditorDialog.java b/NET/worlds/scape/ListEditorDialog.java
new file mode 100644
index 0000000..4bdb939
--- /dev/null
+++ b/NET/worlds/scape/ListEditorDialog.java
@@ -0,0 +1,36 @@
+package NET.worlds.scape;
+
+import java.util.StringTokenizer;
+
+public abstract class ListEditorDialog extends FieldEditorDialog {
+ public ListEditorDialog(EditTile parent, String title) {
+ super(parent, title);
+ }
+
+ protected abstract int getElementCount();
+
+ protected abstract String getElement(int var1);
+
+ protected abstract boolean setElements(StringTokenizer var1);
+
+ @Override
+ protected String getValue() {
+ String text = "";
+ int count = this.getElementCount();
+
+ for (int i = 0; i < count; i++) {
+ if (i != 0) {
+ text = text + ", ";
+ }
+
+ text = text + this.getElement(i);
+ }
+
+ return text;
+ }
+
+ @Override
+ protected boolean setValue(String text) {
+ return this.setElements(new StringTokenizer(text, ", \t", false));
+ }
+}
diff --git a/NET/worlds/scape/LoadedAttribute.java b/NET/worlds/scape/LoadedAttribute.java
new file mode 100644
index 0000000..ee458c3
--- /dev/null
+++ b/NET/worlds/scape/LoadedAttribute.java
@@ -0,0 +1,5 @@
+package NET.worlds.scape;
+
+public interface LoadedAttribute {
+ void loadedAttribute(Attribute var1, String var2);
+}
diff --git a/NET/worlds/scape/LoadedURLSelf.java b/NET/worlds/scape/LoadedURLSelf.java
new file mode 100644
index 0000000..6c4881c
--- /dev/null
+++ b/NET/worlds/scape/LoadedURLSelf.java
@@ -0,0 +1,7 @@
+package NET.worlds.scape;
+
+import NET.worlds.network.URL;
+
+public interface LoadedURLSelf {
+ void loadedURLSelf(URLSelf var1, URL var2, String var3);
+}
diff --git a/NET/worlds/scape/MCISoundCommand.java b/NET/worlds/scape/MCISoundCommand.java
new file mode 100644
index 0000000..00bffcd
--- /dev/null
+++ b/NET/worlds/scape/MCISoundCommand.java
@@ -0,0 +1,14 @@
+package NET.worlds.scape;
+
+abstract class MCISoundCommand {
+ boolean isOnQueue;
+ float left;
+ float right;
+ int frameNum;
+
+ public abstract void run();
+
+ public void onQueue(boolean f) {
+ this.isOnQueue = f;
+ }
+}
diff --git a/NET/worlds/scape/MCISoundPlayer.java b/NET/worlds/scape/MCISoundPlayer.java
new file mode 100644
index 0000000..d87d245
--- /dev/null
+++ b/NET/worlds/scape/MCISoundPlayer.java
@@ -0,0 +1,161 @@
+package NET.worlds.scape;
+
+import NET.worlds.network.URL;
+
+public class MCISoundPlayer extends SoundPlayer {
+ private static MCIThread mciThread = new MCIThread();
+ float ang;
+ float dist;
+ float vol;
+ int leftToRepeat;
+ int running;
+ MCISoundCommand poll = new MCISoundCommand() {
+ @Override
+ public void run() {
+ MCISoundPlayer.this.gotFinished(MCISoundPlayer.this.nativeIsFinished());
+ }
+ };
+ private URL url;
+ private static MCISoundCommand activeStopCmd;
+ MCISoundCommand volumeCmd = new MCISoundCommand() {
+ @Override
+ public void run() {
+ if (!WavSoundPlayer.ignoreVolumeChanges) {
+ MCISoundPlayer.this.nativeVolume(this.left, this.right);
+ }
+ }
+ };
+
+ public MCISoundPlayer(Sound owner) {
+ super(owner);
+ }
+
+ @Override
+ public boolean open(float volume, float stopDist, boolean atten, boolean pan) {
+ return true;
+ }
+
+ @Override
+ public void close() {
+ this.stop();
+ }
+
+ @Override
+ public boolean position(Point3Temp cam, Point3Temp obj, Point3Temp out, Point3Temp up) {
+ Point3Temp toObj = Point3Temp.make(obj).minus(cam);
+ Point3Temp right = Point3Temp.make(out).cross(up);
+ float y = toObj.dot(out);
+ float x = toObj.dot(right);
+ this.ang = (float)(Math.atan2(y, x) / Math.PI);
+ this.dist = toObj.length();
+ return this.setVolume(this.vol);
+ }
+
+ @Override
+ public boolean setVolume(float v) {
+ this.vol = v;
+ float leftFrac = 0.5F;
+ if (this.owner != null && this.owner.getPanning()) {
+ leftFrac = Math.abs(this.ang);
+ if (this.ang < 0.0F) {
+ v = this.vol * (float)(0.5 + Math.abs(0.5 + this.ang));
+ }
+ }
+
+ if (this.owner != null && this.owner.getAttenuate()) {
+ float stopDist = this.owner.getStopDistance();
+ if (this.dist > stopDist) {
+ this.volume(0.0F, 0.0F);
+ return false;
+ }
+
+ v *= (stopDist - this.dist) / stopDist;
+ }
+
+ this.volume(v * leftFrac, v * (1.0F - leftFrac));
+ return true;
+ }
+
+ @Override
+ public int getState() {
+ if (!this.poll.isOnQueue) {
+ mciThread.pushCommand(this.poll);
+ }
+
+ return this.running != 0 ? 0 : 1;
+ }
+
+ @Override
+ public synchronized void start(int repeatCount) {
+ if (repeatCount == 0) {
+ this.running = 0;
+ } else {
+ this.leftToRepeat = repeatCount;
+ if (this.leftToRepeat > 0) {
+ this.leftToRepeat--;
+ }
+
+ this.running = 1;
+ activeStopCmd = null;
+ mciThread.pushCommand(new MCISoundCommand() {
+ @Override
+ public void run() {
+ MCISoundPlayer.this.doStart();
+ }
+ });
+ }
+ }
+
+ public synchronized void start(URL u) {
+ this.url = u;
+ this.start(1);
+ }
+
+ synchronized void doStart() {
+ this.running = 2;
+ if (!this.nativeStart((this.owner == null ? this.url : this.owner.getURL()).unalias())) {
+ this.running = 3;
+ }
+ }
+
+ synchronized void gotFinished(boolean f) {
+ if (f && this.running == 2) {
+ this.start(this.leftToRepeat);
+ }
+ }
+
+ @Override
+ public synchronized void stop() {
+ this.leftToRepeat = 0;
+ activeStopCmd = new MCISoundCommand() {
+ @Override
+ public void run() {
+ if (MCISoundPlayer.activeStopCmd == this) {
+ MCISoundPlayer.activeStopCmd = null;
+ MCISoundPlayer.this.nativeStop();
+ }
+ }
+ };
+ mciThread.pushCommand(activeStopCmd);
+ }
+
+ public void volume(float left, float right) {
+ this.volumeCmd.left = left;
+ this.volumeCmd.right = right;
+ if (!this.volumeCmd.isOnQueue) {
+ mciThread.pushCommand(this.volumeCmd);
+ }
+ }
+
+ private native void nativeVolume(float var1, float var2);
+
+ private native boolean nativeStart(String var1);
+
+ private native boolean nativeIsFinished();
+
+ private native void nativeStop();
+
+ public static native boolean isActive();
+
+ static native void shutdown();
+}
diff --git a/NET/worlds/scape/MCIThread.java b/NET/worlds/scape/MCIThread.java
new file mode 100644
index 0000000..e63518a
--- /dev/null
+++ b/NET/worlds/scape/MCIThread.java
@@ -0,0 +1,44 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Main;
+import NET.worlds.console.MainCallback;
+import NET.worlds.console.MainTerminalCallback;
+import java.util.Vector;
+
+class MCIThread implements MainCallback, MainTerminalCallback {
+ private Vector queue = new Vector();
+ private int frameNum;
+
+ public MCIThread() {
+ Main.register(this);
+ }
+
+ public synchronized void pushCommand(MCISoundCommand c) {
+ this.queue.addElement(c);
+ c.onQueue(true);
+ c.frameNum = this.frameNum + 2;
+ }
+
+ @Override
+ public synchronized void mainCallback() {
+ this.frameNum++;
+
+ while (this.queue.size() > 0) {
+ MCISoundCommand command = (MCISoundCommand)this.queue.elementAt(0);
+ if (command.frameNum > this.frameNum) {
+ return;
+ }
+
+ command.onQueue(false);
+ this.queue.removeElementAt(0);
+ command.run();
+ }
+ }
+
+ @Override
+ public synchronized void terminalCallback() {
+ MCISoundPlayer.shutdown();
+ ASFSoundPlayer.shutdown();
+ Main.unregister(this);
+ }
+}
diff --git a/NET/worlds/scape/Manifest.java b/NET/worlds/scape/Manifest.java
new file mode 100644
index 0000000..dc888a9
--- /dev/null
+++ b/NET/worlds/scape/Manifest.java
@@ -0,0 +1,92 @@
+package NET.worlds.scape;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+public class Manifest {
+ private IndentStream _out;
+ private Hashtable<Object, String> _ht = new Hashtable<Object, String>();
+ private int _lastID = 0;
+
+ public Manifest(IndentStream out) {
+ this._out = out;
+ this._out.println("MANIFEST Worlds, Inc.");
+ this._out.indent();
+ }
+
+ public Manifest(String name) throws IOException {
+ this(new IndentStream(new FileOutputStream(name)));
+ }
+
+ public void done() {
+ this._out.undent();
+ this._out.println("END MANIFEST");
+ this._out.close();
+ this._out = null;
+ this._ht = null;
+ }
+
+ private void printID(String s) {
+ this._out.print(" (#" + s + ")");
+ }
+
+ private void printRef(Object obj) {
+ if (obj instanceof SuperRoot) {
+ this._out.print(((SuperRoot)obj).getName());
+ } else {
+ this._out.print("<anonymous>");
+ }
+
+ if (this._ht.containsKey(obj)) {
+ this.printID(this._ht.get(obj));
+ this._out.println(" --q.v.--");
+ } else {
+ String newID = Integer.toString(this._lastID++);
+ this._ht.put(obj, newID);
+ this.printID(newID);
+ this._out.println(":" + obj.getClass().getName() + " [");
+ this._out.indent();
+ this.saveProps((Properties)obj);
+ this._out.undent();
+ this._out.println("]");
+ }
+ }
+
+ private void saveMaybeProp(Object obj) {
+ if (obj instanceof Properties && !obj.getClass().getName().equals("NET.worlds.scape.Transform")) {
+ this.printRef(obj);
+ } else {
+ this._out.println(obj);
+ }
+ }
+
+ public void saveProps(Properties obj) {
+ Enumeration<Object> pe = new EnumProperties(obj);
+
+ while (pe.hasMoreElements()) {
+ Property prop = (Property)pe.nextElement();
+ this._out.print(prop.getName());
+ this._out.print(" := ");
+ if (prop instanceof VectorProperty) {
+ this._out.println("{");
+ this._out.indent();
+ Vector<Object> v = (Vector<Object>)prop.get();
+ if (v != null) {
+ Enumeration<Object> ve = v.elements();
+
+ while (ve.hasMoreElements()) {
+ this.saveMaybeProp(ve.nextElement());
+ }
+ }
+
+ this._out.undent();
+ this._out.println("}");
+ } else {
+ this.saveMaybeProp(prop.get());
+ }
+ }
+ }
+}
diff --git a/NET/worlds/scape/Material.java b/NET/worlds/scape/Material.java
new file mode 100644
index 0000000..36e4a45
--- /dev/null
+++ b/NET/worlds/scape/Material.java
@@ -0,0 +1,783 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.Main;
+import NET.worlds.console.MainCallback;
+import NET.worlds.core.IniFile;
+import NET.worlds.network.NetUpdate;
+import NET.worlds.network.URL;
+import java.awt.Color;
+import java.io.IOException;
+
+public class Material extends SuperRoot implements BGLoaded, MainCallback {
+ static int serial = 0;
+ public static boolean botMode = false;
+ private boolean keepLoaded = false;
+ private int[] ids;
+ private Texture[] textures;
+ private int vRes = 1;
+ private int hRes = 1;
+ private int sPos = -1;
+ private final boolean loResMode = false;
+ URL textureName;
+ protected URL[] subnames;
+ private boolean doReclump;
+ private static boolean tryBMP = IniFile.gamma().getIniInt("TRYBMP", 0) != 0;
+ private float ambient;
+ private float diffuse;
+ private float specular;
+ private float opacity;
+ private boolean smooth;
+ private boolean filter;
+ private int r;
+ private int g;
+ private int b;
+ private Color color;
+ private static Object classCookie = new Object();
+
+ static {
+ nativeInit();
+ }
+
+ public static native void nativeInit();
+
+ public Material(float ambient, float diffuse, float specular, Color color, Texture texture, float opacity, boolean smooth, boolean filter) {
+ if (botMode) {
+ texture = null;
+ }
+
+ this.ambient = ambient;
+ this.diffuse = diffuse;
+ this.specular = specular;
+ this.setColor(color);
+ if (texture != null) {
+ this.textures = new Texture[1];
+ this.textures[0] = texture;
+ }
+
+ this.opacity = opacity;
+ this.smooth = smooth;
+ this.filter = filter;
+ }
+
+ public Material(Color color) {
+ this(0.75F, 0.0F, 0.0F, color, null, 1.0F, false, false);
+ }
+
+ public Material(Texture texture) {
+ this(0.75F, 0.0F, 0.0F, Color.black, texture, 1.0F, false, false);
+ }
+
+ public Material(Color initialColor, URL textureName) {
+ this(initialColor != null ? initialColor : new Color(128, 128, 128));
+ if (!botMode) {
+ this.loadTexture(textureName);
+ }
+ }
+
+ public Material(URL tileTexture, int x, int y) {
+ this(0.75F, 0.0F, 0.0F, Color.black, null, 1.0F, false, false);
+ this.hRes = x;
+ this.vRes = y;
+ serial++;
+ int numSubs = this.getHRes() * this.getVRes();
+ this.textures = new Texture[numSubs];
+ this.makeMaterials();
+ this.subnames = new URL[numSubs];
+ String lowResBaseName = tileTexture.getBase();
+ int nextSubname = 0;
+
+ for (int v = this.vRes; v > 0; v--) {
+ String vExt = "" + v;
+
+ for (int h = 0; h < this.hRes; nextSubname++) {
+ URL subname = URL.make(tileTexture, lowResBaseName + serial + vExt + (h + 1) + ".cmp");
+ this.subnames[nextSubname] = subname;
+ this.syncBackgroundLoad(tileTexture.unalias(), subname);
+ h++;
+ }
+ }
+ }
+
+ public Material(URL textureName) {
+ this(null, textureName);
+ }
+
+ public Material() {
+ }
+
+ @Override
+ protected void noteAddingTo(SuperRoot owner) {
+ if (((WObject)owner).hasClump()) {
+ this.addRwChildren();
+ }
+ }
+
+ @Override
+ public void detach() {
+ if (this.ids != null) {
+ this.markVoid();
+ }
+
+ super.detach();
+ }
+
+ public Texture[] getTextures() {
+ return this.textures;
+ }
+
+ public void addRwChildren() {
+ if (this.ids == null) {
+ if (this.textures == null && this.textureName != null) {
+ this.loadTextures();
+ } else {
+ this.makeMaterials();
+ if (this.textures != null) {
+ for (int i = 0; i < this.ids.length; i++) {
+ this.nativeSetTexture(i, this.textures[i]);
+ }
+ }
+ }
+ }
+ }
+
+ public void markVoid() {
+ if (!this.keepLoaded) {
+ if (this.textureName != null) {
+ this.removeTextures();
+ }
+
+ this.closeMaterials();
+ }
+ }
+
+ public void setKeepLoaded(boolean f) {
+ boolean klWas = this.keepLoaded;
+ this.keepLoaded = f;
+ if (!f && klWas) {
+ SuperRoot o = this.getOwner();
+ if (o == null || !((WObject)o).hasClump()) {
+ this.markVoid();
+ }
+ }
+ }
+
+ public static Material restore(Restorer r) throws IOException, TooNewException {
+ Material m = (Material)r.restoreMaybeNull();
+ if (m != null && r.version() < 6 && m.getOwner() != null) {
+ m = (Material)m.clone();
+ }
+
+ return m;
+ }
+
+ private native void nativeSetTexture(int var1, Texture var2);
+
+ private synchronized void setTexture(int texNum, Texture texture) {
+ if (this.textures[texNum] != null) {
+ Texture t = this.extractTexture(texNum);
+ if (t != null) {
+ t.decRef();
+ }
+ }
+
+ this.textures[texNum] = texture;
+ this.nativeSetTexture(texNum, texture);
+ if (!this.doReclump) {
+ this.doReclump = true;
+ Main.register(this);
+ }
+ }
+
+ @Override
+ public void mainCallback() {
+ Main.unregister(this);
+ if (this.doReclump) {
+ this.propagateTextureChange();
+ }
+
+ this.doReclump = false;
+ }
+
+ private void propagateTextureChange() {
+ if (this.ids != null) {
+ Object o = this.getOwner();
+ if (o instanceof WObject) {
+ if (o instanceof Surface && ((Surface)o).getMaterial() == this) {
+ ((Surface)o).setMaterial(this, true);
+ } else if (o instanceof Shape && ((Shape)o).getMaterial() == this) {
+ ((Shape)o).setMaterial(this);
+ } else {
+ ((WObject)o).reclump();
+ }
+ }
+ }
+
+ this.doReclump = false;
+ }
+
+ public synchronized void setTexture(Texture texture) {
+ this.textureName = null;
+ if (this.textures != null && this.textures.length != 1) {
+ this.removeTextures();
+ this.textures = new Texture[1];
+ this.setTexture(0, texture);
+ } else {
+ if (this.textures == null) {
+ this.textures = new Texture[1];
+ } else if (texture == this.textures[0]) {
+ return;
+ }
+
+ this.setTexture(0, texture);
+ }
+ }
+
+ synchronized native Texture extractTexture(int var1);
+
+ private void removeTextures() {
+ if (this.textures != null) {
+ for (int i = 0; i < this.textures.length; i++) {
+ Texture t = this.extractTexture(i);
+ if (t != null) {
+ t.decRef();
+ }
+ }
+
+ this.textures = null;
+ }
+
+ this.hRes = this.vRes = 1;
+ this.sPos = -1;
+ this.closeMaterials();
+ }
+
+ @Override
+ protected void finalize() {
+ this.removeTextures();
+ super.finalize();
+ }
+
+ private native void closeMaterial(int var1);
+
+ private void closeMaterials() {
+ if (this.ids != null) {
+ for (int i = 0; i < this.ids.length; i++) {
+ this.closeMaterial(i);
+ }
+
+ this.ids = null;
+ }
+ }
+
+ private int calcRes() {
+ this.hRes = 1;
+ this.vRes = 1;
+ this.sPos = -1;
+ if (this.textureName == null) {
+ return -1;
+ } else {
+ String name = this.textureName.getInternal();
+ int len = name.length();
+ if (len >= 4 && name.regionMatches(true, len - 4, ".mov", 0, 4)) {
+ this.sPos = 0;
+ }
+
+ if (len > 7 && name.regionMatches(true, len - 5, "*.", 0, 2)) {
+ int num;
+ int nextStarIndex;
+ for (nextStarIndex = len - 5;
+ nextStarIndex > 2 && name.charAt(nextStarIndex) == '*' && (num = name.charAt(nextStarIndex - 2) - '0') > 0 && num <= 9;
+ nextStarIndex -= 3
+ ) {
+ char control = Character.toLowerCase(name.charAt(nextStarIndex - 1));
+ if (control == 'h') {
+ this.hRes = num;
+ } else if (control == 'v') {
+ this.vRes = num;
+ } else if (control == 's' && this.sPos >= 0) {
+ this.sPos = num - 1;
+ }
+ }
+
+ return len - (nextStarIndex + 1);
+ } else {
+ return -1;
+ }
+ }
+ }
+
+ private void loadTextures() {
+ int endLen = this.calcRes();
+ if (endLen >= 0) {
+ String lowResBaseName = this.textureName.getBase();
+ int baseEnd = lowResBaseName.length() - endLen;
+ lowResBaseName = lowResBaseName.substring(0, baseEnd);
+ int numSubs = this.getHRes() * this.getVRes();
+ this.textures = new Texture[numSubs];
+ this.makeMaterials();
+ if (this.sPos >= 0) {
+ this.subnames = new URL[1];
+ this.subnames[0] = URL.make(this.textureName, lowResBaseName + ".mov");
+ BackgroundLoader.get(this, this.subnames[0]);
+ } else {
+ this.subnames = new URL[numSubs];
+ int nextSubname = 0;
+
+ for (int v = this.vRes; v > 0; v--) {
+ String vExt = "" + v;
+
+ for (int h = 0; h < this.hRes; nextSubname++) {
+ URL subname = URL.make(this.textureName, lowResBaseName + vExt + (h + 1) + ".cmp");
+ this.subnames[nextSubname] = subname;
+ BackgroundLoader.get(this, subname);
+ h++;
+ }
+ }
+ }
+ } else {
+ this.subnames = null;
+ this.textures = new Texture[1];
+ this.makeMaterials();
+ BackgroundLoader.get(this, this.textureName);
+ }
+ }
+
+ public void loadTexture(URL textureName) {
+ boolean vis = this.ids != null;
+ this.removeTextures();
+ this.textureName = textureName;
+ this.calcRes();
+ if (vis) {
+ this.addRwChildren();
+ }
+
+ Object o = this.getOwner();
+ if (o instanceof WObject) {
+ ((WObject)o).reclump();
+ }
+ }
+
+ private static native int makeMaterial(float var0, float var1, float var2, float var3, int var4, int var5, int var6, boolean var7);
+
+ private void makeMaterials() {
+ int numSubs = this.getHRes() * this.getVRes();
+ this.ids = new int[numSubs];
+
+ for (int i = 0; i < numSubs; i++) {
+ this.ids[i] = makeMaterial(
+ this.ambient, this.diffuse, this.specular, this.opacity, this.color.getRed(), this.color.getGreen(), this.color.getBlue(), this.smooth
+ );
+ }
+ }
+
+ private void loadError(URL name) {
+ SuperRoot owner = this.getOwner();
+ System.out.println("Unable to load texture " + name + (owner == null ? "" : " for " + owner.getName()) + ".");
+ }
+
+ public float getAmbient() {
+ return this.ambient;
+ }
+
+ public float getDiffuse() {
+ return this.diffuse;
+ }
+
+ public float getSpecular() {
+ return this.specular;
+ }
+
+ public float getOpacity() {
+ return this.opacity;
+ }
+
+ public boolean getSmooth() {
+ return this.smooth;
+ }
+
+ public boolean getFilter() {
+ return this.filter;
+ }
+
+ public boolean getHiRes() {
+ return this.vRes > 1 || this.hRes > 1;
+ }
+
+ public int getVRes() {
+ return this.vRes;
+ }
+
+ public int getHRes() {
+ return this.hRes;
+ }
+
+ public int getRed() {
+ return this.r;
+ }
+
+ public int getGreen() {
+ return this.g;
+ }
+
+ public int getBlue() {
+ return this.b;
+ }
+
+ public Color getColor() {
+ return this.color;
+ }
+
+ public native void paramChange();
+
+ public void setAmbient(float ambient) {
+ this.ambient = ambient;
+ this.paramChange();
+ }
+
+ public void setDiffuse(float diffuse) {
+ this.diffuse = diffuse;
+ this.paramChange();
+ }
+
+ public void setSpecular(float specular) {
+ this.specular = specular;
+ this.paramChange();
+ }
+
+ public void setOpacity(float opacity) {
+ this.opacity = opacity;
+ this.paramChange();
+ }
+
+ public void setSmooth(boolean smooth) {
+ this.smooth = smooth;
+ this.paramChange();
+ }
+
+ public void setFilter(boolean filter) {
+ this.filter = filter;
+ this.paramChange();
+ }
+
+ public void setColor(Color color) {
+ this.color = color;
+ this.r = color.getRed();
+ this.g = color.getGreen();
+ this.b = color.getBlue();
+ this.paramChange();
+ }
+
+ @Override
+ public Object asyncBackgroundLoad(String localName, URL remoteURL) {
+ return localName;
+ }
+
+ @Override
+ public boolean syncBackgroundLoad(Object obj, URL remoteURL) {
+ int texNum = 0;
+ if (this.textures == null) {
+ return false;
+ } else {
+ String urlString = remoteURL.getAbsolute();
+ String avatarDir = IniFile.gamma().getIniString("avatarDir", "avatar/");
+ if (!avatarDir.endsWith("/")) {
+ avatarDir = avatarDir + "/";
+ }
+
+ String avStart = URL.make(NetUpdate.getUpgradeServerURL() + avatarDir).getAbsolute();
+ String remoteBase = remoteURL == null ? null : remoteURL.getBase();
+ String textureBase = this.textureName == null ? null : this.textureName.getBase();
+ if (!remoteBase.equals(textureBase)) {
+ if (this.textureName != null && this.textureName.endsWith(".mov")) {
+ String rawBase = this.textureName.getBaseWithoutExt();
+ String rawRemote = remoteURL.getBaseWithoutExt();
+ if (!rawBase.startsWith(rawRemote)) {
+ return false;
+ }
+ } else {
+ if (this.subnames == null) {
+ return false;
+ }
+
+ while (texNum < this.subnames.length) {
+ String subBase = this.subnames[texNum].getBase();
+ if (remoteBase.equals(subBase)) {
+ break;
+ }
+
+ texNum++;
+ }
+
+ if (texNum == this.textures.length) {
+ return false;
+ }
+ }
+ }
+
+ String localName = (String)obj;
+ if (this.ids == null) {
+ return false;
+ } else {
+ if (localName != null) {
+ if (this.sPos < 0) {
+ Texture t = TextureDecoder.decode(remoteURL, localName);
+ if (t != null && t.textureID != 0) {
+ this.setTexture(texNum, t);
+ } else {
+ localName = null;
+ }
+ } else {
+ Texture[] ts = new ScapePicMovie(localName, remoteURL).getTextures();
+ if (ts != null && this.hRes * this.vRes * (this.sPos + 1) <= ts.length) {
+ int i = this.hRes * this.vRes * this.sPos;
+
+ for (int v = (this.vRes - 1) * this.hRes; v >= 0; v -= this.hRes) {
+ for (int h = 0; h < this.hRes; i++) {
+ this.setTexture(v + h, ts[i]);
+ h++;
+ }
+ }
+ } else {
+ localName = null;
+ }
+ }
+ } else {
+ int len = urlString.length();
+ if (tryBMP && this.sPos == -1 && len > 4 && urlString.regionMatches(true, len - 4, ".cmp", 0, 4) && !remoteURL.isRemote()) {
+ String lName = urlString.substring(0, len - 4) + ".bmp";
+ Texture t = TextureDecoder.decode(URL.make(lName), lName);
+ if (t != null && t.textureID != 0) {
+ this.setTexture(texNum, t);
+ localName = lName;
+ }
+ }
+ }
+
+ if (localName == null) {
+ if (urlString.startsWith("avatar:")) {
+ BackgroundLoader.get(this, URL.make(avStart + urlString.substring(7)));
+ return false;
+ }
+
+ this.loadError(remoteURL);
+ }
+
+ return false;
+ }
+ }
+ }
+
+ @Override
+ public Room getBackgroundLoadRoom() {
+ WObject owner = (WObject)this.getOwner();
+ return owner == null ? null : owner.getRoom();
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(4, classCookie);
+ super.saveState(s);
+ s.saveFloat(this.getAmbient());
+ s.saveFloat(this.getDiffuse());
+ s.saveFloat(this.getSpecular());
+ s.saveFloat(this.getOpacity());
+ s.saveBoolean(this.getSmooth());
+ s.saveBoolean(this.getFilter());
+ s.saveInt(this.getRed());
+ s.saveInt(this.getGreen());
+ s.saveInt(this.getBlue());
+ URL.save(s, this.textureName);
+ s.saveBoolean(this.keepLoaded);
+ if (this.textureName == null) {
+ if (this.textures != null && this.textures.length != 1) {
+ s.saveMaybeNull(null);
+ } else {
+ s.saveMaybeNull(this.textures == null ? null : this.textures[0]);
+ }
+ }
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ Texture texture = null;
+ int vers = r.restoreVersion(classCookie);
+ switch (vers) {
+ case 1:
+ super.restoreState(r);
+ case 0: {
+ this.ambient = r.restoreFloat();
+ this.diffuse = r.restoreFloat();
+ this.specular = r.restoreFloat();
+ this.opacity = r.restoreFloat();
+ int red = r.restoreInt();
+ int green = r.restoreInt();
+ int blue = r.restoreInt();
+ this.setColor(new Color(red, green, blue));
+ texture = (Texture)r.restoreMaybeNull();
+ break;
+ }
+ case 2:
+ case 3:
+ case 4: {
+ super.restoreState(r);
+ this.ambient = r.restoreFloat();
+ this.diffuse = r.restoreFloat();
+ this.specular = r.restoreFloat();
+ this.opacity = r.restoreFloat();
+ if (vers > 3) {
+ this.smooth = r.restoreBoolean();
+ this.filter = r.restoreBoolean();
+ }
+
+ int red = r.restoreInt();
+ int green = r.restoreInt();
+ int blue = r.restoreInt();
+ this.setColor(new Color(red, green, blue));
+ URL name = URL.restore(r);
+ if (vers > 2) {
+ this.setKeepLoaded(r.restoreBoolean());
+ }
+
+ if (name == null) {
+ texture = (Texture)r.restoreMaybeNull();
+ } else {
+ this.loadTexture(name);
+ }
+ break;
+ }
+ default:
+ throw new TooNewException();
+ }
+
+ if (texture != null) {
+ this.textures = new Texture[1];
+ this.textures[0] = texture;
+ }
+
+ assert r.version() >= 6 || this.getOwner() == null;
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = new Property(this, index, "Texture").allowSetNull();
+ } else if (mode == 1) {
+ MaterialTexture mt;
+ if (this.textures != null && this.textures[0] instanceof StringTexture) {
+ mt = new MaterialTexture((StringTexture)this.textures[0]);
+ } else {
+ mt = new MaterialTexture(this.textureName);
+ }
+
+ this.add(mt);
+ ret = mt;
+ } else if (mode == 2) {
+ if (value == null) {
+ this.loadTexture(null);
+ } else {
+ Console.println(Console.message("Cant-undo-tex"));
+ }
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = ColorPropertyEditor.make(new Property(this, index, "Color"));
+ } else if (mode == 1) {
+ ret = this.getColor();
+ } else if (mode == 2) {
+ this.setColor((Color)value);
+ }
+ break;
+ case 2:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Ambient Reflection Coefficient"), 0.0F, 1.0F);
+ } else if (mode == 1) {
+ ret = new Float(this.getAmbient());
+ } else if (mode == 2) {
+ this.setAmbient((Float)value);
+ }
+ break;
+ case 3:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Diffuse Reflection Coefficient"), 0.0F, 1.0F);
+ } else if (mode == 1) {
+ ret = new Float(this.getDiffuse());
+ } else if (mode == 2) {
+ this.setDiffuse((Float)value);
+ }
+ break;
+ case 4:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Specular Reflection Coefficient"), 0.0F, 1.0F);
+ } else if (mode == 1) {
+ ret = new Float(this.getSpecular());
+ } else if (mode == 2) {
+ this.setSpecular((Float)value);
+ }
+ break;
+ case 5:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Opacity"), 0.0F, 1.0F);
+ } else if (mode == 1) {
+ ret = new Float(this.getOpacity());
+ } else if (mode == 2) {
+ this.setOpacity((Float)value);
+ }
+ break;
+ case 6:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Smooth"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(this.getSmooth());
+ } else if (mode == 2) {
+ this.setSmooth((Boolean)value);
+ }
+ break;
+ case 7:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Filter"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(this.getFilter());
+ } else if (mode == 2) {
+ this.setFilter((Boolean)value);
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 8, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public String toString() {
+ return this.getName()
+ + "["
+ + (this.textureName != null ? this.textureName.toString() : (this.textures == null ? null : this.textures.toString()))
+ + ", "
+ + this.getColor()
+ + ", Ambient "
+ + this.getAmbient()
+ + ", Diffuse "
+ + this.getDiffuse()
+ + ", Specular "
+ + this.getSpecular()
+ + ", Opacity "
+ + this.getOpacity()
+ + ", Smooth "
+ + this.getSmooth()
+ + ", Filter "
+ + this.getFilter()
+ + ", hRes "
+ + this.hRes
+ + ", vRes "
+ + this.vRes
+ + ", loResMode "
+ + false
+ + "]";
+ }
+}
diff --git a/NET/worlds/scape/MaterialTexture.java b/NET/worlds/scape/MaterialTexture.java
new file mode 100644
index 0000000..4fb5363
--- /dev/null
+++ b/NET/worlds/scape/MaterialTexture.java
@@ -0,0 +1,201 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.network.URL;
+import java.awt.Color;
+
+class MaterialTexture extends SuperRoot implements NonPersister {
+ private URL fileName;
+ private StringTexture stexture;
+ private String text = "";
+ private String font = Console.message("MaterialFont");
+ private int size = 48;
+ private Color foregroundColor = Color.white;
+ private Color backgroundColor = Color.black;
+
+ MaterialTexture(URL textureName) {
+ this.fileName = textureName;
+ }
+
+ MaterialTexture(StringTexture texture) {
+ this.stexture = texture;
+ this.text = this.stexture.getText();
+ this.font = this.stexture.getFont();
+ this.size = this.stexture.getSize();
+ this.foregroundColor = this.stexture.getForegroundColor();
+ this.backgroundColor = this.stexture.getBackgroundColor();
+ }
+
+ private void setFile(URL name, boolean force) {
+ this.fileName = name;
+ if (this.stexture == null || force) {
+ this.stexture = null;
+ ((Material)this.getOwner()).loadTexture(name);
+ }
+ }
+
+ private void makeString() {
+ Material owner = (Material)this.getOwner();
+ this.stexture = new StringTexture(this.text, this.font, this.size, this.foregroundColor, this.backgroundColor);
+ owner.setTexture(this.stexture);
+ }
+
+ private String getText() {
+ return this.text;
+ }
+
+ private void setText(String text) {
+ this.text = text;
+ if (this.stexture != null) {
+ this.makeString();
+ }
+ }
+
+ private void setFont(String font) {
+ this.font = font;
+ if (this.stexture != null) {
+ this.makeString();
+ }
+ }
+
+ private void setSize(int size) {
+ if (size >= 1 && size <= 720) {
+ this.size = size;
+ if (this.stexture != null) {
+ this.makeString();
+ }
+ } else {
+ Console.println(Console.message("Font-sizes"));
+ }
+ }
+
+ private void setForegroundColor(Color color) {
+ this.foregroundColor = color;
+ if (this.stexture != null) {
+ this.makeString();
+ }
+ }
+
+ private void setBackgroundColor(Color color) {
+ this.backgroundColor = color;
+ if (this.stexture != null) {
+ this.makeString();
+ }
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(
+ new Property(this, index, "Texture Type (Text String)"), "Texture loaded from an image file.", "Texture created from a text string."
+ );
+ } else if (mode == 1) {
+ ret = new Boolean(this.stexture != null);
+ } else if (mode == 2) {
+ boolean stringTexture = (Boolean)value;
+ if (stringTexture && this.stexture == null) {
+ this.makeString();
+ } else if (!stringTexture && this.stexture != null) {
+ this.setFile(this.fileName, true);
+ }
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = new Property(this, index, "File");
+ if (this.stexture == null) {
+ ret = URLPropertyEditor.make((Property)ret, TextureDecoder.getAllExts());
+ }
+ } else if (mode == 1) {
+ ret = this.fileName;
+ } else if (mode == 2) {
+ this.setFile((URL)value, false);
+ }
+ break;
+ case 2:
+ if (mode == 0) {
+ ret = new Property(this, index, "Text");
+ if (this.stexture != null) {
+ ret = StringPropertyEditor.make((Property)ret);
+ }
+ } else if (mode == 1) {
+ ret = this.getText();
+ } else if (mode == 2) {
+ this.setText((String)value);
+ }
+ break;
+ case 3:
+ if (mode == 0) {
+ ret = new Property(this, index, "Font");
+ if (this.stexture != null) {
+ ret = StringPropertyEditor.make((Property)ret);
+ }
+ } else if (mode == 1) {
+ ret = this.font;
+ } else if (mode == 2) {
+ this.setFont((String)value);
+ }
+
+ System.out.println("Setting font " + (String)value + " in Material.java");
+ break;
+ case 4:
+ if (mode == 0) {
+ ret = new Property(this, index, "Size");
+ if (this.stexture != null) {
+ ret = IntegerPropertyEditor.make((Property)ret);
+ }
+ } else if (mode == 1) {
+ ret = new Integer(this.size);
+ } else if (mode == 2) {
+ this.setSize((Integer)value);
+ }
+ break;
+ case 5:
+ if (mode == 0) {
+ ret = new Property(this, index, "Foreground Color");
+ if (this.stexture != null) {
+ ret = ColorPropertyEditor.make((Property)ret);
+ }
+ } else if (mode == 1) {
+ ret = this.foregroundColor;
+ } else if (mode == 2) {
+ this.setForegroundColor((Color)value);
+ }
+ break;
+ case 6:
+ if (mode == 0) {
+ ret = new Property(this, index, "Background Color");
+ if (this.stexture != null) {
+ ret = ColorPropertyEditor.make((Property)ret);
+ }
+ } else if (mode == 1) {
+ ret = this.backgroundColor;
+ } else if (mode == 2) {
+ this.setBackgroundColor((Color)value);
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 7, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public String toString() {
+ if (this.stexture != null) {
+ return "" + this.stexture;
+ } else {
+ Material owner = (Material)this.getOwner();
+ URL name = null;
+ if (owner != null) {
+ name = owner.textureName;
+ }
+
+ return name == null ? "File " : "File " + name;
+ }
+ }
+}
diff --git a/NET/worlds/scape/MaybeNullDialog.java b/NET/worlds/scape/MaybeNullDialog.java
new file mode 100644
index 0000000..773bdcd
--- /dev/null
+++ b/NET/worlds/scape/MaybeNullDialog.java
@@ -0,0 +1,24 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.ConfirmDialog;
+import NET.worlds.console.Console;
+
+class MaybeNullDialog extends ConfirmDialog {
+ private Property property;
+ private Object newOne;
+ private EditTile parent;
+
+ MaybeNullDialog(EditTile parent, String title, String prompt, Property property, Object newOne) {
+ super(Console.getFrame(), parent, title, prompt);
+ this.property = property;
+ this.newOne = newOne;
+ this.parent = parent;
+ this.ready();
+ }
+
+ @Override
+ protected boolean setValue() {
+ this.parent.addUndoableSet(this.property, this.newOne);
+ return true;
+ }
+}
diff --git a/NET/worlds/scape/MaybeNullPropertyEditor.java b/NET/worlds/scape/MaybeNullPropertyEditor.java
new file mode 100644
index 0000000..1753cb7
--- /dev/null
+++ b/NET/worlds/scape/MaybeNullPropertyEditor.java
@@ -0,0 +1,21 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.PolledDialog;
+
+public class MaybeNullPropertyEditor extends PropEditor {
+ private Object newOne;
+
+ private MaybeNullPropertyEditor(Property property, Object newOne) {
+ super(property);
+ this.newOne = newOne;
+ }
+
+ @Override
+ public PolledDialog edit(EditTile parent, String title) {
+ return new MaybeNullDialog(parent, title, "Create a new instance?", this.property, this.newOne);
+ }
+
+ public static Property make(Property property, Object newOne) {
+ return property.setEditor(new MaybeNullPropertyEditor(property, newOne));
+ }
+}
diff --git a/NET/worlds/scape/MetaEnumeration.java b/NET/worlds/scape/MetaEnumeration.java
new file mode 100644
index 0000000..1eafe57
--- /dev/null
+++ b/NET/worlds/scape/MetaEnumeration.java
@@ -0,0 +1,38 @@
+package NET.worlds.scape;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+public class MetaEnumeration implements Enumeration {
+ private Vector v;
+ private int index;
+
+ MetaEnumeration(Vector v) {
+ assert v.size() > 0;
+
+ this.v = v;
+ this.index = 0;
+ this.advanceToNext();
+ }
+
+ @Override
+ public boolean hasMoreElements() {
+ return ((Enumeration)this.v.elementAt(this.index)).hasMoreElements();
+ }
+
+ @Override
+ public Object nextElement() {
+ Object e = ((Enumeration)this.v.elementAt(this.index)).nextElement();
+ this.advanceToNext();
+ return e;
+ }
+
+ private void advanceToNext() {
+ while (!((Enumeration)this.v.elementAt(this.index)).hasMoreElements()) {
+ if (++this.index == this.v.size()) {
+ this.index--;
+ break;
+ }
+ }
+ }
+}
diff --git a/NET/worlds/scape/Mirror.java b/NET/worlds/scape/Mirror.java
new file mode 100644
index 0000000..a410a18
--- /dev/null
+++ b/NET/worlds/scape/Mirror.java
@@ -0,0 +1,34 @@
+package NET.worlds.scape;
+
+public class Mirror extends Portal {
+ public Mirror(float w, float h) {
+ super(w, h);
+ this.connectTo(this);
+ this.flags |= 4;
+ }
+
+ public Mirror(float llx, float lly, float llz, float urx, float ury, float urz) {
+ super(llx, lly, llz, urx, ury, urz);
+ this.connectTo(this);
+ this.flags |= 4;
+ }
+
+ public Mirror(Point3Temp llc, Point3Temp urc) {
+ super(llc, urc);
+ this.connectTo(this);
+ this.flags |= 4;
+ }
+
+ @Override
+ public BumpCalc getBumpCalc(BumpEventTemp b) {
+ return this.bumpCalc == null ? Rect.standardPlaneBumpCalc : this.bumpCalc;
+ }
+
+ public Mirror() {
+ }
+
+ @Override
+ public boolean handle(BumpEventTemp b) {
+ return true;
+ }
+}
diff --git a/NET/worlds/scape/MomentumBehavior.java b/NET/worlds/scape/MomentumBehavior.java
new file mode 100644
index 0000000..f3c2304
--- /dev/null
+++ b/NET/worlds/scape/MomentumBehavior.java
@@ -0,0 +1,7 @@
+package NET.worlds.scape;
+
+import java.util.Enumeration;
+
+public interface MomentumBehavior {
+ void transferFrom(Enumeration var1);
+}
diff --git a/NET/worlds/scape/MontyDoor.java b/NET/worlds/scape/MontyDoor.java
new file mode 100644
index 0000000..0c128ad
--- /dev/null
+++ b/NET/worlds/scape/MontyDoor.java
@@ -0,0 +1,185 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.Main;
+import NET.worlds.console.MainCallback;
+import NET.worlds.network.URL;
+import java.io.IOException;
+import java.text.MessageFormat;
+import java.util.Enumeration;
+
+public class MontyDoor extends Portal implements MouseDownHandler, MainCallback {
+ boolean setsAvatar = false;
+ URL url;
+ String description = "";
+ DialogAction action;
+ String viewName;
+ URL viewURL;
+ Persister lastTrigger;
+ private static Object classCookie = new Object();
+
+ public MontyDoor() {
+ this.flags |= 262144;
+ }
+
+ @Override
+ public boolean handle(MouseDownEvent e) {
+ if ((e.key & 1) == 0) {
+ return false;
+ } else if (this.action == null && this.url != null) {
+ if (this.setsAvatar) {
+ SelectAvatarAction a = new SelectAvatarAction();
+ a.url = this.viewURL;
+ a.description = this.description;
+ this.action = a;
+ } else {
+ SendURLAction a = new SendURLAction();
+ a.destination = this.url;
+ a.description = this.description;
+ this.action = a;
+ }
+
+ this.action.cancelOnly = true;
+ Main.register(this);
+ return true;
+ } else {
+ return true;
+ }
+ }
+
+ @Override
+ public void mainCallback() {
+ if (this.action.cancelOnly) {
+ this.lastTrigger = this.action.trigger(null, this.lastTrigger);
+ if (this.lastTrigger != null) {
+ return;
+ }
+
+ if (this.viewURL != null && this.viewName != null && this._farSideRoomName != null) {
+ Room r = this.getRoom();
+ World w;
+ if (r != null && (w = r.getWorld()) != null) {
+ r = w.getRoom(this._farSideRoomName);
+ if (r == null) {
+ Main.unregister(this);
+ this.action = null;
+ Object[] arguments = new Object[]{new String(this.getName()), new String(this._farSideRoomName)};
+ Console.println(MessageFormat.format(Console.message("MontyDoor"), arguments));
+ return;
+ }
+
+ Enumeration list = r.getDeepOwned();
+ SetPropertyAction.propHelper(2, this.viewURL, "File", SuperRoot.nameSearch(list, this.viewName));
+ }
+ }
+
+ this.action.cancelOnly = false;
+ this.flags &= -262145;
+ this.reset();
+ }
+
+ this.lastTrigger = this.action.trigger(null, this.lastTrigger);
+ if (this.lastTrigger == null) {
+ Main.unregister(this);
+ this.action = null;
+ this.flags |= 262144;
+ this.reset();
+ }
+ }
+
+ @Override
+ public BumpCalc getBumpCalc(BumpEventTemp b) {
+ return standardPlaneBumpCalc;
+ }
+
+ @Override
+ public boolean handle(BumpEventTemp b) {
+ return true;
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Avatar type"), "SendURL", "SelectAvatar");
+ } else if (mode == 1) {
+ ret = new Boolean(this.setsAvatar);
+ } else if (mode == 2) {
+ this.setsAvatar = (Boolean)value;
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = URLPropertyEditor.make(new Property(this, index, "URL (used only for non-avatar)").allowSetNull(), null);
+ } else if (mode == 1) {
+ ret = this.url;
+ } else if (mode == 2) {
+ this.url = (URL)value;
+ }
+ break;
+ case 2:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Description"));
+ } else if (mode == 1) {
+ ret = this.description;
+ } else if (mode == 2) {
+ this.description = ((String)value).toString().trim();
+ }
+ break;
+ case 3:
+ if (mode == 0) {
+ ret = URLPropertyEditor.make(new Property(this, index, "Display URL").allowSetNull(), null);
+ } else if (mode == 1) {
+ ret = this.viewURL;
+ } else if (mode == 2) {
+ this.viewURL = (URL)value;
+ }
+ break;
+ case 4:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Display Name"));
+ } else if (mode == 1) {
+ ret = this.viewName;
+ } else if (mode == 2) {
+ this.viewName = ((String)value).toString().trim();
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 5, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(0, classCookie);
+ int f = this.flags;
+ this.flags |= 262144;
+ super.saveState(s);
+ this.flags = f;
+ s.saveBoolean(this.setsAvatar);
+ URL.save(s, this.url);
+ s.saveString(this.description);
+ URL.save(s, this.viewURL);
+ s.saveString(this.viewName);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ this.setsAvatar = r.restoreBoolean();
+ this.url = URL.restore(r);
+ this.description = r.restoreString();
+ this.viewURL = URL.restore(r);
+ this.viewName = r.restoreString();
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/MoreInfoDialog.java b/NET/worlds/scape/MoreInfoDialog.java
new file mode 100644
index 0000000..877faf6
--- /dev/null
+++ b/NET/worlds/scape/MoreInfoDialog.java
@@ -0,0 +1,54 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.DialogReceiver;
+import NET.worlds.console.ImageButtons;
+import NET.worlds.console.ImageButtonsCallback;
+import NET.worlds.console.PolledDialog;
+import NET.worlds.core.IniFile;
+import java.awt.Component;
+import java.awt.Rectangle;
+import java.awt.Window;
+
+public class MoreInfoDialog extends PolledDialog implements ImageButtonsCallback {
+ private ImageButtons ib;
+
+ public MoreInfoDialog(Window parent, DialogReceiver receiver) {
+ super(parent, receiver, Console.message("BrowseQ"), false);
+ this.setAlignment(1);
+ Rectangle[] rects = new Rectangle[2];
+ int yesX = IniFile.override().getIniInt("moreinfoYesX", 48);
+ int yesY = IniFile.override().getIniInt("moreinfoYesY", 22);
+ int yesW = IniFile.override().getIniInt("moreinfoYesW", 60);
+ int yesH = IniFile.override().getIniInt("moreinfoYesH", 19);
+ rects[0] = new Rectangle(yesX, yesY, yesW, yesH);
+ int noX = IniFile.override().getIniInt("moreinfoNoX", 139);
+ int noY = IniFile.override().getIniInt("moreinfoNoY", 22);
+ int noW = IniFile.override().getIniInt("moreinfoNoW", 54);
+ int noH = IniFile.override().getIniInt("moreinfoNoH", 19);
+ rects[1] = new Rectangle(noX, noY, noW, noH);
+ String migif = IniFile.override().getIniString("moreInfoDlg", Console.message("moreinfo.gif"));
+ this.ib = new ImageButtons(migif, rects, this);
+ this.ready();
+ }
+
+ @Override
+ protected void build() {
+ this.add("Center", this.ib);
+ }
+
+ @Override
+ public Object imageButtonsCallback(Component who, int which) {
+ this.done(which == 0);
+ return null;
+ }
+
+ @Override
+ public boolean keyDown(java.awt.Event event, int key) {
+ if (key == 27) {
+ return this.done(false);
+ } else {
+ return key == 10 ? this.done(true) : super.keyDown(event, key);
+ }
+ }
+}
diff --git a/NET/worlds/scape/Motion.java b/NET/worlds/scape/Motion.java
new file mode 100644
index 0000000..9283376
--- /dev/null
+++ b/NET/worlds/scape/Motion.java
@@ -0,0 +1,398 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import java.io.IOException;
+import java.text.MessageFormat;
+import java.util.Date;
+
+class Motion extends TriggeredSwitchableBehavior implements FrameHandler, Persister, MouseDownHandler, BumpHandler {
+ long startMotionTime;
+ protected float cycleTime;
+ protected String frameList;
+ protected int cycles;
+ protected Transform motionTransform;
+ protected Point3 startPoint;
+ protected Point3 endPoint;
+ protected Point3 deltaPoint;
+ protected Point3 startScale;
+ protected Point3 endScale;
+ protected Point3 deltaScale;
+ protected Point3 startSpin;
+ protected Point3 endSpin;
+ protected Point3 currentSpin;
+ protected float startRotation;
+ protected float endRotation;
+ protected float currentRotation;
+ protected boolean motionTransformInitialized;
+ protected boolean variableInitialized;
+ protected boolean motionEnd = true;
+
+ public Motion() {
+ this.cycleTime = 1000.0F;
+ this.trigger = new String("none");
+ this.externalTriggerTag = new String("");
+ this.cycles = 0;
+ this.motionTransformInitialized = false;
+ this.variableInitialized = false;
+ this.startPoint = new Point3();
+ this.endPoint = new Point3();
+ this.deltaPoint = new Point3();
+ this.startScale = new Point3();
+ this.endScale = new Point3();
+ this.deltaScale = new Point3();
+ this.startSpin = new Point3();
+ this.endSpin = new Point3();
+ this.currentSpin = new Point3();
+ this.startMotion();
+ }
+
+ @Override
+ public void ExternalTrigger(Trigger trigger_source, int sequence_no, int event_no) {
+ this.trigger_source = trigger_source;
+ this.sequence_no = sequence_no;
+ this.event_no = event_no;
+ this.startMotion();
+ }
+
+ public boolean equivalent(Point3Temp a, Point3Temp b) {
+ return Math.round(a.x) == Math.round(b.x) && Math.round(a.y) == Math.round(b.y) && Math.round(a.z) == Math.round(b.z);
+ }
+
+ public void startMotion() {
+ if (this.motionTransform != null
+ && this.equivalent(this.startPoint, this.motionTransform.getPosition())
+ && Math.round(this.startScale.x) == Math.round(this.motionTransform.getTotalScale())) {
+ this.currentRotation = Math.round(this.motionTransform.getSpin(this.currentSpin));
+ this.startRotation = Math.round(this.startRotation);
+ if ((this.startRotation == this.currentRotation || this.startRotation - 360.0F == this.currentRotation)
+ && this.equivalent(this.startSpin, this.currentSpin)
+ || (-this.startRotation == this.currentRotation || 360.0F - this.startRotation == this.currentRotation)
+ && this.equivalent(this.startSpin, this.currentSpin.negate())) {
+ Date timer = new Date();
+ this.startMotionTime = timer.getTime();
+ this.motionEnd = true;
+ }
+ }
+ }
+
+ @Override
+ public boolean handle(FrameEvent e) {
+ if (!this.motionTransformInitialized) {
+ this.motionTransform = e.target;
+ this.motionTransformInitialized = true;
+ }
+
+ if (!this.variableInitialized) {
+ this.startPoint.copy(this.motionTransform.getPosition());
+ this.endPoint.copy(this.startPoint);
+ this.startScale.x = this.motionTransform.getTotalScale();
+ this.startScale.y = this.motionTransform.getTotalScale();
+ this.startScale.z = this.motionTransform.getTotalScale();
+ this.endScale.copy(this.startScale);
+ this.startRotation = this.motionTransform.getSpin(this.startSpin);
+ this.endRotation = 0.0F;
+ this.variableInitialized = true;
+ }
+
+ if (this.enabled) {
+ Date timer = new Date();
+ long currentTime = timer.getTime();
+ float frameLoc = (float)(-this.startMotionTime + currentTime) % this.cycleTime / this.cycleTime;
+ int cycleNo = (int)((float)(-this.startMotionTime + currentTime) / this.cycleTime);
+ if (cycleNo < this.cycles || this.cycles == 0 || !this.motionEnd) {
+ this.motionEnd = false;
+ if (cycleNo >= this.cycles && this.cycles != 0) {
+ this.motionEnd = true;
+ frameLoc = 1.0F;
+ if (this.trigger_source != null) {
+ this.trigger_source.registerFinishedTriggerTag(this.sequence_no, this.event_no);
+ }
+ }
+
+ e.receiver.makeIdentity();
+ e.receiver
+ .scale(
+ this.startScale.x + (this.endScale.x - this.startScale.x) * frameLoc,
+ this.startScale.x + (this.endScale.x - this.startScale.x) * frameLoc,
+ this.startScale.x + (this.endScale.x - this.startScale.x) * frameLoc
+ );
+ e.receiver
+ .moveTo(
+ this.startPoint.x + (this.endPoint.x - this.startPoint.x) * frameLoc,
+ this.startPoint.y + (this.endPoint.y - this.startPoint.y) * frameLoc,
+ this.startPoint.z + (this.endPoint.z - this.startPoint.z) * frameLoc
+ );
+ e.receiver.spin(this.startSpin, this.startRotation);
+ e.receiver.spin(this.endSpin, this.endRotation * frameLoc);
+ }
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean handle(MouseDownEvent e) {
+ if (this.enabled && this.trigger.equals("click")) {
+ this.startMotion();
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean handle(BumpEventTemp e) {
+ if (this.enabled && this.trigger.equals("bump")) {
+ this.startMotion();
+ }
+
+ return true;
+ }
+
+ public void startTransform() {
+ if (this.motionTransform != null) {
+ this.motionTransform.makeIdentity();
+ this.motionTransform.scale(this.startScale.x, this.startScale.x, this.startScale.x);
+ this.motionTransform.moveTo(this.startPoint.x, this.startPoint.y, this.startPoint.z);
+ this.motionTransform.spin(this.startSpin, this.startRotation);
+ } else {
+ System.out.println("motionTransform is null!!!!");
+ }
+ }
+
+ public void endTransform() {
+ if (this.motionTransform != null) {
+ this.motionTransform.makeIdentity();
+ this.motionTransform.scale(this.endScale.x, this.endScale.x, this.endScale.x);
+ this.motionTransform.moveTo(this.endPoint.x, this.endPoint.y, this.endPoint.z);
+ this.motionTransform.spin(this.startSpin, this.startRotation);
+ this.motionTransform.spin(this.endSpin, this.endRotation);
+ } else {
+ System.out.println("motionTransform is null!!!!");
+ }
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = new ClassProperty(this, index, "Motion");
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Cycle Time"));
+ } else if (mode == 1) {
+ ret = new Float(this.cycleTime);
+ } else if (mode == 2) {
+ this.cycleTime = (Float)value;
+ }
+ break;
+ case 2:
+ if (mode == 0) {
+ ret = IntegerPropertyEditor.make(new Property(this, index, "Cycles"));
+ } else if (mode == 1) {
+ ret = new Integer(this.cycles);
+ } else if (mode == 2) {
+ this.cycles = (Integer)value;
+ }
+ break;
+ case 3:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Trigger"));
+ } else if (mode == 1) {
+ ret = new String(this.trigger);
+ } else if (mode == 2) {
+ this.trigger = ((String)value).toString().trim();
+ if (this.trigger.equals("external")) {
+ Trigger.TriggeredSwitchableBehaviorList[Trigger.TriggeredSwitchableBehaviorListCount] = this;
+ Trigger.TriggeredSwitchableBehaviorListCount++;
+ }
+ }
+ break;
+ case 4:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "External Trigger Tag"));
+ } else if (mode == 1) {
+ ret = new String(this.externalTriggerTag);
+ } else if (mode == 2) {
+ this.externalTriggerTag = ((String)value).toString().trim();
+ }
+ break;
+ case 5:
+ if (mode == 0) {
+ ret = Point3PropertyEditor.make(new Property(this, index, "End Point"));
+ } else if (mode == 1) {
+ ret = new Point3(this.endPoint);
+ this.endTransform();
+ } else if (mode == 2) {
+ this.endPoint.copy((Point3)value);
+ this.endTransform();
+ }
+ break;
+ case 6:
+ if (mode == 0) {
+ ret = Point3PropertyEditor.make(new Property(this, index, "Start Point"));
+ } else if (mode == 1) {
+ ret = new Point3(this.startPoint);
+ this.startTransform();
+ } else if (mode == 2) {
+ this.startPoint.copy((Point3)value);
+ this.startTransform();
+ }
+ break;
+ case 7:
+ if (mode == 0) {
+ ret = Point3PropertyEditor.make(new Property(this, index, "End Scale"));
+ } else if (mode == 1) {
+ ret = new Point3(this.endScale);
+ this.endTransform();
+ } else if (mode == 2) {
+ this.endScale.copy((Point3)value);
+ this.endTransform();
+ }
+ break;
+ case 8:
+ if (mode == 0) {
+ ret = Point3PropertyEditor.make(new Property(this, index, "Start Scale"));
+ } else if (mode == 1) {
+ ret = new Point3(this.startScale);
+ this.startTransform();
+ } else if (mode == 2) {
+ this.startScale.copy((Point3)value);
+ this.startTransform();
+ }
+ break;
+ case 9:
+ if (mode == 0) {
+ ret = Point3PropertyEditor.make(new Property(this, index, "End Spin (Relative)"));
+ } else if (mode == 1) {
+ ret = new Point3(this.endSpin);
+ this.endTransform();
+ } else if (mode == 2) {
+ this.endSpin.copy((Point3)value);
+ this.endTransform();
+ }
+ break;
+ case 10:
+ if (mode == 0) {
+ ret = Point3PropertyEditor.make(new Property(this, index, "Start Spin"));
+ } else if (mode == 1) {
+ ret = new Point3(this.startSpin);
+ this.startTransform();
+ } else if (mode == 2) {
+ this.startSpin.copy((Point3)value);
+ this.startTransform();
+ }
+ break;
+ case 11:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "End Rotation (Relative)"));
+ } else if (mode == 1) {
+ ret = new Float(this.endRotation);
+ this.endTransform();
+ } else if (mode == 2) {
+ this.endRotation = (Float)value;
+ this.endTransform();
+ }
+ break;
+ case 12:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Start Rotation"));
+ } else if (mode == 1) {
+ ret = new Float(this.startRotation);
+ this.startTransform();
+ } else if (mode == 2) {
+ this.startRotation = (Float)value;
+ this.startTransform();
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 13, mode, value);
+ }
+
+ if (mode == 2 && this.trigger.equals("none")) {
+ this.startMotion();
+ }
+
+ return ret;
+ }
+
+ @Override
+ public String toString() {
+ return "Motion: cycleTime "
+ + this.cycleTime
+ + ", cycles "
+ + this.cycles
+ + ", enabled "
+ + this.enabled
+ + ", trigger "
+ + this.trigger
+ + ", externalTriggerTag "
+ + this.externalTriggerTag;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveFloat(this.cycleTime);
+ s.saveInt(this.cycles);
+ s.saveString(this.trigger);
+ s.saveString(this.externalTriggerTag);
+ this.endPoint.saveState(s);
+ this.startPoint.saveState(s);
+ this.endScale.saveState(s);
+ this.startScale.saveState(s);
+ this.endSpin.saveState(s);
+ this.startSpin.saveState(s);
+ s.saveFloat(this.endRotation);
+ s.saveFloat(this.startRotation);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException {
+ this.cycleTime = r.restoreFloat();
+ this.cycles = r.restoreInt();
+ this.trigger = r.restoreString();
+ if (this.trigger.equals("external")) {
+ Trigger.TriggeredSwitchableBehaviorList[Trigger.TriggeredSwitchableBehaviorListCount] = this;
+ Trigger.TriggeredSwitchableBehaviorListCount++;
+ }
+
+ this.externalTriggerTag = r.restoreString();
+
+ try {
+ this.endPoint.restoreState(r);
+ this.startPoint.restoreState(r);
+ this.endScale.restoreState(r);
+ this.startScale.restoreState(r);
+ this.endSpin.restoreState(r);
+ this.startSpin.restoreState(r);
+ } catch (Exception var3) {
+ }
+
+ this.endRotation = r.restoreFloat();
+ this.startRotation = r.restoreFloat();
+ this.variableInitialized = true;
+ if (!this.trigger.equals("none")) {
+ this.startMotionTime = (int)(-(this.cycles * this.cycleTime));
+ } else {
+ this.startMotion();
+ }
+ }
+
+ @Override
+ public void postRestore(int version) {
+ String name = this.getName();
+ String arg1 = name == null ? "<null>" : name;
+ SuperRoot owner = this.getOwner();
+ String oname = "";
+ if (owner != null) {
+ oname = owner.getName();
+ }
+
+ String arg2 = oname == null ? "<null>" : oname;
+ Object[] arguments = new Object[]{new String(arg1), new String(arg2)};
+ Console.println(MessageFormat.format(Console.message("Motion-obs"), arguments));
+ }
+}
diff --git a/NET/worlds/scape/MouseButtonEvent.java b/NET/worlds/scape/MouseButtonEvent.java
new file mode 100644
index 0000000..2f62ad4
--- /dev/null
+++ b/NET/worlds/scape/MouseButtonEvent.java
@@ -0,0 +1,15 @@
+package NET.worlds.scape;
+
+public class MouseButtonEvent extends MouseEvent {
+ public char key;
+
+ public MouseButtonEvent(int time, WObject target, char key, int x, int y) {
+ super(time, target, x, y);
+ this.key = key;
+ }
+
+ @Override
+ public boolean deliver(Object o) {
+ return o instanceof MouseButtonHandler && ((MouseButtonHandler)o).handle(this) ? true : super.deliver(o);
+ }
+}
diff --git a/NET/worlds/scape/MouseButtonHandler.java b/NET/worlds/scape/MouseButtonHandler.java
new file mode 100644
index 0000000..7f2a8b0
--- /dev/null
+++ b/NET/worlds/scape/MouseButtonHandler.java
@@ -0,0 +1,5 @@
+package NET.worlds.scape;
+
+public interface MouseButtonHandler {
+ boolean handle(MouseButtonEvent var1);
+}
diff --git a/NET/worlds/scape/MouseDeltaEvent.java b/NET/worlds/scape/MouseDeltaEvent.java
new file mode 100644
index 0000000..b530b3c
--- /dev/null
+++ b/NET/worlds/scape/MouseDeltaEvent.java
@@ -0,0 +1,17 @@
+package NET.worlds.scape;
+
+public class MouseDeltaEvent extends MouseEvent {
+ public int dx;
+ public int dy;
+
+ public MouseDeltaEvent(int time, WObject target, int dx, int dy) {
+ super(time, target, 0, 0);
+ this.dx = dx;
+ this.dy = dy;
+ }
+
+ @Override
+ public boolean deliver(Object o) {
+ return o instanceof MouseDeltaHandler && ((MouseDeltaHandler)o).handle(this) ? true : super.deliver(o);
+ }
+}
diff --git a/NET/worlds/scape/MouseDeltaHandler.java b/NET/worlds/scape/MouseDeltaHandler.java
new file mode 100644
index 0000000..0da21bf
--- /dev/null
+++ b/NET/worlds/scape/MouseDeltaHandler.java
@@ -0,0 +1,5 @@
+package NET.worlds.scape;
+
+public interface MouseDeltaHandler {
+ boolean handle(MouseDeltaEvent var1);
+}
diff --git a/NET/worlds/scape/MouseDownEvent.java b/NET/worlds/scape/MouseDownEvent.java
new file mode 100644
index 0000000..71ea54f
--- /dev/null
+++ b/NET/worlds/scape/MouseDownEvent.java
@@ -0,0 +1,27 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.BBWObjClickedCommand;
+import NET.worlds.console.BlackBox;
+
+public class MouseDownEvent extends MouseButtonEvent {
+ public MouseDownEvent(int time, WObject target, char key, int x, int y) {
+ super(time, target, key, x, y);
+ }
+
+ @Override
+ public boolean deliver(Object o) {
+ if (o instanceof MouseDownHandler) {
+ BlackBox.getInstance().submitEvent(new BBWObjClickedCommand(((SuperRoot)o).getName(), this.key, this.x, this.y));
+ if (((MouseDownHandler)o).handle(this)) {
+ return true;
+ }
+ }
+
+ return super.deliver(o);
+ }
+
+ @Override
+ public String toString() {
+ return "MouseDown" + super.toString();
+ }
+}
diff --git a/NET/worlds/scape/MouseDownHandler.java b/NET/worlds/scape/MouseDownHandler.java
new file mode 100644
index 0000000..aa1141e
--- /dev/null
+++ b/NET/worlds/scape/MouseDownHandler.java
@@ -0,0 +1,5 @@
+package NET.worlds.scape;
+
+public interface MouseDownHandler {
+ boolean handle(MouseDownEvent var1);
+}
diff --git a/NET/worlds/scape/MouseDragEvent.java b/NET/worlds/scape/MouseDragEvent.java
new file mode 100644
index 0000000..2294bc7
--- /dev/null
+++ b/NET/worlds/scape/MouseDragEvent.java
@@ -0,0 +1,12 @@
+package NET.worlds.scape;
+
+public class MouseDragEvent extends MousePositionEvent {
+ public MouseDragEvent(int time, WObject target, int x, int y) {
+ super(time, target, x, y);
+ }
+
+ @Override
+ public boolean deliver(Object o) {
+ return o instanceof MouseDragHandler && ((MouseDragHandler)o).handle(this) ? true : super.deliver(o);
+ }
+}
diff --git a/NET/worlds/scape/MouseDragHandler.java b/NET/worlds/scape/MouseDragHandler.java
new file mode 100644
index 0000000..28b7105
--- /dev/null
+++ b/NET/worlds/scape/MouseDragHandler.java
@@ -0,0 +1,5 @@
+package NET.worlds.scape;
+
+public interface MouseDragHandler {
+ boolean handle(MouseDragEvent var1);
+}
diff --git a/NET/worlds/scape/MouseEnterEvent.java b/NET/worlds/scape/MouseEnterEvent.java
new file mode 100644
index 0000000..4fdf3d6
--- /dev/null
+++ b/NET/worlds/scape/MouseEnterEvent.java
@@ -0,0 +1,12 @@
+package NET.worlds.scape;
+
+public class MouseEnterEvent extends MousePositionEvent {
+ public MouseEnterEvent(int time, WObject target, int x, int y) {
+ super(time, target, x, y);
+ }
+
+ @Override
+ public boolean deliver(Object o) {
+ return o instanceof MouseEnterHandler && ((MouseEnterHandler)o).handle(this) ? true : super.deliver(o);
+ }
+}
diff --git a/NET/worlds/scape/MouseEnterHandler.java b/NET/worlds/scape/MouseEnterHandler.java
new file mode 100644
index 0000000..fa83b3a
--- /dev/null
+++ b/NET/worlds/scape/MouseEnterHandler.java
@@ -0,0 +1,5 @@
+package NET.worlds.scape;
+
+public interface MouseEnterHandler {
+ boolean handle(MouseEnterEvent var1);
+}
diff --git a/NET/worlds/scape/MouseEvent.java b/NET/worlds/scape/MouseEvent.java
new file mode 100644
index 0000000..1e73583
--- /dev/null
+++ b/NET/worlds/scape/MouseEvent.java
@@ -0,0 +1,17 @@
+package NET.worlds.scape;
+
+public class MouseEvent extends UserEvent {
+ public int x;
+ public int y;
+
+ public MouseEvent(int time, WObject target, int x, int y) {
+ super(time, null, target);
+ this.x = x;
+ this.y = y;
+ }
+
+ @Override
+ public boolean deliver(Object o) {
+ return o instanceof MouseHandler && ((MouseHandler)o).handle(this) ? true : super.deliver(o);
+ }
+}
diff --git a/NET/worlds/scape/MouseExitEvent.java b/NET/worlds/scape/MouseExitEvent.java
new file mode 100644
index 0000000..7a19347
--- /dev/null
+++ b/NET/worlds/scape/MouseExitEvent.java
@@ -0,0 +1,12 @@
+package NET.worlds.scape;
+
+public class MouseExitEvent extends MousePositionEvent {
+ public MouseExitEvent(int time, WObject target, int x, int y) {
+ super(time, target, x, y);
+ }
+
+ @Override
+ public boolean deliver(Object o) {
+ return o instanceof MouseExitHandler && ((MouseExitHandler)o).handle(this) ? true : super.deliver(o);
+ }
+}
diff --git a/NET/worlds/scape/MouseExitHandler.java b/NET/worlds/scape/MouseExitHandler.java
new file mode 100644
index 0000000..d6c3462
--- /dev/null
+++ b/NET/worlds/scape/MouseExitHandler.java
@@ -0,0 +1,5 @@
+package NET.worlds.scape;
+
+public interface MouseExitHandler {
+ boolean handle(MouseExitEvent var1);
+}
diff --git a/NET/worlds/scape/MouseHandler.java b/NET/worlds/scape/MouseHandler.java
new file mode 100644
index 0000000..dbbdc5b
--- /dev/null
+++ b/NET/worlds/scape/MouseHandler.java
@@ -0,0 +1,5 @@
+package NET.worlds.scape;
+
+public interface MouseHandler {
+ boolean handle(MouseEvent var1);
+}
diff --git a/NET/worlds/scape/MouseMoveEvent.java b/NET/worlds/scape/MouseMoveEvent.java
new file mode 100644
index 0000000..3a9a11b
--- /dev/null
+++ b/NET/worlds/scape/MouseMoveEvent.java
@@ -0,0 +1,12 @@
+package NET.worlds.scape;
+
+public class MouseMoveEvent extends MousePositionEvent {
+ public MouseMoveEvent(int time, WObject target, int x, int y) {
+ super(time, target, x, y);
+ }
+
+ @Override
+ public boolean deliver(Object o) {
+ return o instanceof MouseMoveHandler && ((MouseMoveHandler)o).handle(this) ? true : super.deliver(o);
+ }
+}
diff --git a/NET/worlds/scape/MouseMoveHandler.java b/NET/worlds/scape/MouseMoveHandler.java
new file mode 100644
index 0000000..e421ae9
--- /dev/null
+++ b/NET/worlds/scape/MouseMoveHandler.java
@@ -0,0 +1,5 @@
+package NET.worlds.scape;
+
+public interface MouseMoveHandler {
+ boolean handle(MouseMoveEvent var1);
+}
diff --git a/NET/worlds/scape/MousePositionEvent.java b/NET/worlds/scape/MousePositionEvent.java
new file mode 100644
index 0000000..5223ec1
--- /dev/null
+++ b/NET/worlds/scape/MousePositionEvent.java
@@ -0,0 +1,12 @@
+package NET.worlds.scape;
+
+public class MousePositionEvent extends MouseEvent {
+ public MousePositionEvent(int time, WObject target, int x, int y) {
+ super(time, target, x, y);
+ }
+
+ @Override
+ public boolean deliver(Object o) {
+ return o instanceof MousePositionHandler && ((MousePositionHandler)o).handle(this) ? true : super.deliver(o);
+ }
+}
diff --git a/NET/worlds/scape/MousePositionHandler.java b/NET/worlds/scape/MousePositionHandler.java
new file mode 100644
index 0000000..9a6d6ec
--- /dev/null
+++ b/NET/worlds/scape/MousePositionHandler.java
@@ -0,0 +1,5 @@
+package NET.worlds.scape;
+
+public interface MousePositionHandler {
+ boolean handle(MousePositionEvent var1);
+}
diff --git a/NET/worlds/scape/MouseUpEvent.java b/NET/worlds/scape/MouseUpEvent.java
new file mode 100644
index 0000000..5c70713
--- /dev/null
+++ b/NET/worlds/scape/MouseUpEvent.java
@@ -0,0 +1,17 @@
+package NET.worlds.scape;
+
+public class MouseUpEvent extends MouseButtonEvent {
+ public MouseUpEvent(int time, WObject target, char key, int x, int y) {
+ super(time, target, key, x, y);
+ }
+
+ @Override
+ public boolean deliver(Object o) {
+ return o instanceof MouseUpHandler && ((MouseUpHandler)o).handle(this) ? true : super.deliver(o);
+ }
+
+ @Override
+ public String toString() {
+ return "MouseUp" + super.toString();
+ }
+}
diff --git a/NET/worlds/scape/MouseUpHandler.java b/NET/worlds/scape/MouseUpHandler.java
new file mode 100644
index 0000000..00457ae
--- /dev/null
+++ b/NET/worlds/scape/MouseUpHandler.java
@@ -0,0 +1,5 @@
+package NET.worlds.scape;
+
+public interface MouseUpHandler {
+ boolean handle(MouseUpEvent var1);
+}
diff --git a/NET/worlds/scape/MoveAction.java b/NET/worlds/scape/MoveAction.java
new file mode 100644
index 0000000..3ba4be7
--- /dev/null
+++ b/NET/worlds/scape/MoveAction.java
@@ -0,0 +1,444 @@
+package NET.worlds.scape;
+
+import NET.worlds.core.Std;
+import java.io.IOException;
+import java.util.Enumeration;
+
+public class MoveAction extends Action {
+ int startTime;
+ boolean killOthers = true;
+ boolean killed = false;
+ public int cycleTime = 1000;
+ public int cycles = 1;
+ public boolean loopInfinite = false;
+ public Point3 startPoint = new Point3();
+ public Point3 startScale = new Point3(1.0F, 1.0F, 1.0F);
+ public Point3 startSpin = new Point3(0.0F, 0.0F, -1.0F);
+ public float startRotation;
+ public Point3 extentPoint = new Point3();
+ public Point3 extentScale = new Point3(1.0F, 1.0F, 1.0F);
+ public Point3 extentSpin = new Point3(0.0F, 0.0F, -1.0F);
+ public float extentRotation;
+ protected Persister activeID;
+ private static Object classCookie = new Object();
+
+ @Override
+ public void noteAddingTo(SuperRoot owner) {
+ if (this.startPoint.x == 0.0F
+ && this.startPoint.y == 0.0F
+ && this.startPoint.z == 0.0F
+ && this.startScale.x == 1.0F
+ && this.startScale.y == 1.0F
+ && this.startScale.z == 1.0F
+ && this.startSpin.x == 0.0F
+ && this.startSpin.y == 0.0F
+ && this.startSpin.z == -1.0F
+ && this.startRotation == 0.0F) {
+ this.updateStored(true);
+ }
+ }
+
+ public void updateStored(boolean start) {
+ Object owner = this.getOwner();
+ if (owner != null && owner instanceof WObject) {
+ WObject o = (WObject)owner;
+ if (!start) {
+ this.extentPoint.copy(o.getPosition());
+ this.extentScale.copy(o.getScale());
+ Point3Temp newSpin = Point3Temp.make();
+ this.endToExtent(o.getSpin(newSpin), newSpin);
+ } else {
+ this.startPoint.copy(o.getPosition());
+ this.startScale.copy(o.getScale());
+ this.startRotation = o.getSpin(this.startSpin);
+ }
+ }
+ }
+
+ public void endToExtent(float rot, Point3Temp spinAxis) {
+ this.extentPoint.minus(this.startPoint);
+ this.extentScale.dividedBy(this.startScale);
+ Transform t = Transform.make();
+ t.spin(spinAxis, rot);
+ t.spin(this.startSpin, -this.startRotation);
+ rot = t.getSpin(spinAxis);
+ t.recycle();
+ if (this.equivalentSpinAxises(spinAxis, this.extentSpin)) {
+ int wholeTurns = Math.round((this.extentRotation - rot) / 360.0F);
+ this.extentRotation = rot + wholeTurns * 360;
+ } else if (this.equivalentSpinAxises(spinAxis, this.extentSpin.negate())) {
+ this.extentSpin.negate();
+ rot = -rot;
+ int wholeTurns = Math.round((this.extentRotation - rot) / 360.0F);
+ this.extentRotation = rot + wholeTurns * 360;
+ } else {
+ this.extentSpin.copy(spinAxis);
+ this.extentRotation = rot;
+ }
+ }
+
+ private boolean equivalentSpinAxises(Point3Temp a, Point3Temp b) {
+ return Math.abs(a.x - b.x) + Math.abs(a.y - b.y) + Math.abs(a.z - b.z) < 0.001F;
+ }
+
+ public void updateOwner(boolean start) {
+ Object owner = this.getOwner();
+ if (owner != null && owner instanceof WObject) {
+ WObject o = (WObject)owner;
+ o.makeIdentity();
+ if (!start) {
+ o.spin(this.extentSpin, this.extentRotation);
+ o.moveBy(this.extentPoint);
+ o.scale(this.extentScale);
+ }
+
+ o.scale(this.startScale);
+ o.spin(this.startSpin, this.startRotation);
+ o.moveBy(this.startPoint);
+ }
+ }
+
+ public void kill() {
+ this.killed = true;
+ }
+
+ public boolean isRunning() {
+ return this.activeID != null;
+ }
+
+ @Override
+ public Persister trigger(Event e, Persister seqID) {
+ Object owner = this.getOwner();
+ if (owner != null && owner instanceof WObject) {
+ WObject o = (WObject)owner;
+ if (this.killed) {
+ this.killed = false;
+ this.activeID = null;
+ return null;
+ } else {
+ if (seqID == null) {
+ if (this.activeID != null) {
+ return this.activeID;
+ }
+
+ if (this.killOthers) {
+ Enumeration acts = o.getActions();
+
+ while (acts.hasMoreElements()) {
+ Action a = (Action)acts.nextElement();
+ if (a != this && a instanceof MoveAction) {
+ MoveAction ma = (MoveAction)a;
+ if (ma.isRunning()) {
+ ma.kill();
+ }
+ }
+ }
+ }
+
+ this.startTime = Std.getRealTime();
+ this.activeID = new SuperRoot();
+ seqID = this.activeID;
+ }
+
+ if (seqID != this.activeID) {
+ return null;
+ } else {
+ int currentTime = Std.getRealTime();
+ int cycleNo = (currentTime - this.startTime) / this.cycleTime;
+ float frameLoc = 1.0F;
+ if (cycleNo >= this.cycles && !this.loopInfinite) {
+ this.activeID = null;
+ } else {
+ frameLoc = (float)((currentTime - this.startTime) % this.cycleTime) / this.cycleTime;
+ }
+
+ boolean var10000 = o instanceof Camera;
+ if (o instanceof PosableDrone) {
+ float yaw = -(this.startRotation + this.extentRotation * frameLoc);
+ Point3Temp dest = Point3Temp.make(this.extentPoint).times(frameLoc).plus(this.startPoint);
+ o.makeIdentity().moveTo(dest).yaw(yaw);
+ } else {
+ o.makeIdentity();
+ o.spin(this.extentSpin, this.extentRotation * frameLoc);
+ o.spin(this.startSpin, this.startRotation);
+ Point3Temp p = Point3Temp.make(
+ (float)Math.pow(this.extentScale.x, frameLoc),
+ (float)Math.pow(this.extentScale.y, frameLoc),
+ (float)Math.pow(this.extentScale.z, frameLoc)
+ );
+ o.scale(p.times(this.startScale));
+ o.moveTo(Point3Temp.make(this.extentPoint).times(frameLoc).plus(this.startPoint));
+ }
+
+ return this.activeID;
+ }
+ }
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Cycle Time (in seconds)"));
+ } else if (mode == 1) {
+ ret = new Float(this.cycleTime / 1000.0F);
+ } else if (mode == 2) {
+ this.cycleTime = (int)(1000.0F * (Float)value);
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = IntegerPropertyEditor.make(new Property(this, index, "Cycles"));
+ } else if (mode == 1) {
+ ret = new Integer(this.cycles);
+ } else if (mode == 2) {
+ this.cycles = (Integer)value;
+ }
+ break;
+ case 2:
+ if (mode == 0) {
+ ret = IntegerPropertyEditor.make(new Property(this, index, "Copy Start/End 1/2:Action->Owner 3/4:Owner->Action"));
+ } else if (mode == 1) {
+ ret = new Integer(0);
+ } else if (mode == 2) {
+ switch ((Integer)value) {
+ case 1:
+ this.updateOwner(true);
+ return ret;
+ case 2:
+ this.updateOwner(false);
+ return ret;
+ case 3:
+ this.updateStored(true);
+ return ret;
+ case 4:
+ this.updateStored(false);
+ }
+ }
+ break;
+ case 3:
+ if (mode == 0) {
+ ret = Point3PropertyEditor.make(new Property(this, index, "Translation Extent"));
+ } else if (mode == 1) {
+ ret = new Point3(this.extentPoint);
+ } else if (mode == 2) {
+ this.extentPoint.copy((Point3)value);
+ }
+ break;
+ case 4:
+ if (mode == 0) {
+ ret = Point3PropertyEditor.make(new Property(this, index, "Scale Extent"));
+ } else if (mode == 1) {
+ ret = new Point3(this.extentScale);
+ } else if (mode == 2) {
+ this.extentScale.copy((Point3)value);
+ }
+ break;
+ case 5:
+ if (mode == 0) {
+ ret = Point3PropertyEditor.make(new Property(this, index, "Spin Axis For Extent"));
+ } else if (mode == 1) {
+ Point3 p = new Point3(this.extentSpin);
+ p.x = Math.round(p.x * 10000.0F) / 10000.0F;
+ p.y = Math.round(p.y * 10000.0F) / 10000.0F;
+ p.z = Math.round(p.z * 10000.0F) / 10000.0F;
+ ret = p;
+ } else if (mode == 2) {
+ this.extentSpin.copy((Point3)value);
+ }
+ break;
+ case 6:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Extent Rotation Amount"));
+ } else if (mode == 1) {
+ ret = new Float(this.extentRotation);
+ } else if (mode == 2) {
+ this.extentRotation = (Float)value;
+ }
+ break;
+ case 7:
+ if (mode == 0) {
+ ret = Point3PropertyEditor.make(new Property(this, index, "Start Point"));
+ } else if (mode == 1) {
+ ret = new Point3(this.startPoint);
+ } else if (mode == 2) {
+ this.startPoint.copy((Point3)value);
+ }
+ break;
+ case 8:
+ if (mode == 0) {
+ ret = Point3PropertyEditor.make(new Property(this, index, "Start Scale"));
+ } else if (mode == 1) {
+ ret = new Point3(this.startScale);
+ } else if (mode == 2) {
+ this.startScale.copy((Point3)value);
+ }
+ break;
+ case 9:
+ if (mode == 0) {
+ ret = Point3PropertyEditor.make(new Property(this, index, "Start Spin"));
+ } else if (mode == 1) {
+ ret = new Point3(this.startSpin);
+ } else if (mode == 2) {
+ this.startSpin.copy((Point3)value);
+ }
+ break;
+ case 10:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Start Rotation"));
+ } else if (mode == 1) {
+ ret = new Float(this.startRotation);
+ } else if (mode == 2) {
+ this.startRotation = (Float)value;
+ }
+ break;
+ case 11:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Kill Other Move Actions"), "Let other moves finish", "Kill other move actions");
+ } else if (mode == 1) {
+ ret = new Boolean(this.killOthers);
+ } else if (mode == 2) {
+ this.killOthers = (Boolean)value;
+ }
+ break;
+ case 12:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Loop Infinite"), "False", "True");
+ } else if (mode == 1) {
+ ret = new Boolean(this.loopInfinite);
+ } else if (mode == 2) {
+ this.loopInfinite = (Boolean)value;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 13, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public String toString() {
+ String retVal = super.toString() + "[cycleTime " + this.cycleTime / 1000.0F + ", cycles " + this.cycles + ",";
+ if (!this.loopInfinite) {
+ retVal = retVal + " not ";
+ }
+
+ return retVal + " Infinite ]";
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(6, classCookie);
+ super.saveState(s);
+ s.saveBoolean(this.loopInfinite);
+ s.saveInt(this.cycleTime);
+ s.saveInt(this.cycles);
+ s.save(this.extentPoint);
+ s.save(this.startPoint);
+ s.save(this.extentScale);
+ s.save(this.startScale);
+ s.save(this.extentSpin);
+ s.save(this.startSpin);
+ s.saveFloat(this.extentRotation);
+ s.saveFloat(this.startRotation);
+ s.saveBoolean(this.killOthers);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ this.restoreStateMoveActionHelper(r, classCookie);
+ }
+
+ public void restoreStateMoveActionHelper(Restorer r, Object cookie) throws IOException, TooNewException {
+ switch (r.restoreVersion(cookie)) {
+ case 1:
+ super.restoreState(r);
+ case 0:
+ r.setOldFlag();
+ this.cycleTime = (int)r.restoreFloat();
+ this.cycles = r.restoreInt();
+ this.loopInfinite = this.cycles == 0;
+ this.extentPoint = (Point3)r.restore();
+ this.startPoint = (Point3)r.restore();
+ this.extentScale = (Point3)r.restore();
+ this.startScale = (Point3)r.restore();
+ this.extentSpin = (Point3)r.restore();
+ this.startSpin = (Point3)r.restore();
+ this.extentRotation = r.restoreFloat();
+ this.startRotation = r.restoreFloat();
+ this.extentPoint.minus(this.startPoint);
+ this.extentScale.dividedBy(this.startScale);
+ break;
+ case 2:
+ r.setOldFlag();
+ super.restoreState(r);
+ this.cycleTime = r.restoreInt();
+ this.cycles = r.restoreInt();
+ this.loopInfinite = this.cycles == 0;
+ this.extentPoint = (Point3)r.restore();
+ this.startPoint = (Point3)r.restore();
+ this.extentScale = (Point3)r.restore();
+ this.startScale = (Point3)r.restore();
+ this.extentSpin = (Point3)r.restore();
+ this.startSpin = (Point3)r.restore();
+ this.extentRotation = r.restoreFloat();
+ this.startRotation = r.restoreFloat();
+ r.restoreBoolean();
+ break;
+ case 3:
+ case 4:
+ r.setOldFlag();
+ super.restoreState(r);
+ this.cycleTime = r.restoreInt();
+ this.cycles = r.restoreInt();
+ this.loopInfinite = this.cycles == 0;
+ this.extentPoint = (Point3)r.restore();
+ this.startPoint = (Point3)r.restore();
+ this.extentScale = (Point3)r.restore();
+ this.startScale = (Point3)r.restore();
+ this.extentSpin = (Point3)r.restore();
+ this.startSpin = (Point3)r.restore();
+ this.extentRotation = r.restoreFloat();
+ this.startRotation = r.restoreFloat();
+ break;
+ case 5:
+ super.restoreState(r);
+ this.cycleTime = r.restoreInt();
+ this.cycles = r.restoreInt();
+ this.loopInfinite = this.cycles == 0;
+ this.extentPoint = (Point3)r.restore();
+ this.startPoint = (Point3)r.restore();
+ this.extentScale = (Point3)r.restore();
+ this.startScale = (Point3)r.restore();
+ this.extentSpin = (Point3)r.restore();
+ this.startSpin = (Point3)r.restore();
+ this.extentRotation = r.restoreFloat();
+ this.startRotation = r.restoreFloat();
+ this.killOthers = r.restoreBoolean();
+ break;
+ case 6:
+ super.restoreState(r);
+ this.loopInfinite = r.restoreBoolean();
+ this.cycleTime = r.restoreInt();
+ this.cycles = r.restoreInt();
+ this.extentPoint = (Point3)r.restore();
+ this.startPoint = (Point3)r.restore();
+ this.extentScale = (Point3)r.restore();
+ this.startScale = (Point3)r.restore();
+ this.extentSpin = (Point3)r.restore();
+ this.startSpin = (Point3)r.restore();
+ this.extentRotation = r.restoreFloat();
+ this.startRotation = r.restoreFloat();
+ this.killOthers = r.restoreBoolean();
+ break;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/MoveCameraAction.java b/NET/worlds/scape/MoveCameraAction.java
new file mode 100644
index 0000000..d772588
--- /dev/null
+++ b/NET/worlds/scape/MoveCameraAction.java
@@ -0,0 +1,85 @@
+package NET.worlds.scape;
+
+import NET.worlds.core.Std;
+import java.util.Enumeration;
+
+public class MoveCameraAction extends MoveAction {
+ private static Object classCookie = new Object();
+
+ @Override
+ public Persister trigger(Event e, Persister seqID) {
+ Pilot pl = Pilot.getActive();
+ if (!(pl instanceof HoloPilot)) {
+ return null;
+ } else {
+ HoloPilot holo = (HoloPilot)pl;
+ holo.releaseCamera();
+ Object owner = holo.getCamera();
+ if (owner != null && owner instanceof WObject) {
+ WObject o = (WObject)owner;
+ if (this.killed) {
+ this.killed = false;
+ this.activeID = null;
+ holo.reclaimCamera();
+ return null;
+ } else {
+ if (seqID == null) {
+ if (this.activeID != null) {
+ return this.activeID;
+ }
+
+ if (this.killOthers) {
+ Enumeration acts = o.getActions();
+
+ while (acts.hasMoreElements()) {
+ Action a = (Action)acts.nextElement();
+ if (a != this && a instanceof MoveAction) {
+ MoveAction ma = (MoveAction)a;
+ if (ma.isRunning()) {
+ ma.kill();
+ }
+ }
+ }
+ }
+
+ this.startTime = Std.getRealTime();
+ this.activeID = new SuperRoot();
+ seqID = this.activeID;
+ }
+
+ if (seqID != this.activeID) {
+ return null;
+ } else {
+ int currentTime = Std.getRealTime();
+ int cycleNo = (currentTime - this.startTime) / this.cycleTime;
+ float frameLoc = 1.0F;
+ if (cycleNo >= this.cycles && !this.loopInfinite) {
+ System.out.println("Killing MoveCameraAction. loopInfinite = " + this.loopInfinite);
+ this.activeID = null;
+ } else {
+ frameLoc = (float)((currentTime - this.startTime) % this.cycleTime) / this.cycleTime;
+ }
+
+ o.makeIdentity();
+ o.spin(this.extentSpin, this.extentRotation * frameLoc);
+ o.spin(this.startSpin, this.startRotation);
+ Point3Temp p = Point3Temp.make(
+ (float)Math.pow(this.extentScale.x, frameLoc),
+ (float)Math.pow(this.extentScale.y, frameLoc),
+ (float)Math.pow(this.extentScale.z, frameLoc)
+ );
+ o.scale(p.times(this.startScale));
+ o.moveTo(Point3Temp.make(this.extentPoint).times(frameLoc).plus(this.startPoint));
+ if (this.activeID == null) {
+ holo.reclaimCamera();
+ }
+
+ return this.activeID;
+ }
+ }
+ } else {
+ return null;
+ }
+ }
+ }
+}
diff --git a/NET/worlds/scape/MultiManifestAction.java b/NET/worlds/scape/MultiManifestAction.java
new file mode 100644
index 0000000..4852d36
--- /dev/null
+++ b/NET/worlds/scape/MultiManifestAction.java
@@ -0,0 +1,112 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.network.URL;
+import java.io.File;
+import java.io.IOException;
+
+public class MultiManifestAction extends Action implements LoadedURLSelf {
+ private String _directory;
+ private static Object classCookie = new Object();
+ private String[] _files;
+ private File _dir;
+ private int _curFile;
+ private String _file;
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Directory"));
+ } else if (mode == 1) {
+ if (this._directory == null) {
+ this._directory = new String();
+ }
+
+ ret = new String(this._directory);
+ } else if (mode == 2) {
+ this._directory = ((String)value).trim();
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 1, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(0, classCookie);
+ super.saveState(s);
+ s.saveString(this._directory);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ this._directory = r.restoreString();
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+
+ @Override
+ public Persister trigger(Event e, Persister seqId) {
+ if (seqId == null) {
+ System.out.println("MMAState:starting");
+ this._dir = new File(this._directory);
+ this._files = this._dir.list(new ExtensionFilter(".world"));
+ this._curFile = 0;
+ this.startFile();
+ }
+
+ return this._curFile >= this._files.length ? null : this;
+ }
+
+ public void startFile() {
+ if (this._curFile >= this._files.length) {
+ System.out.println("MMAState:Done");
+ } else {
+ this._file = new File(this._dir, this._files[this._curFile]).getAbsolutePath();
+ System.out.println("MMAState:Loading: " + this._file);
+ World.load(URL.make(this._file), this);
+ }
+ }
+
+ @Override
+ public void loadedURLSelf(URLSelf o, URL url, String err) {
+ if (err == null && o instanceof World) {
+ World w = (World)o;
+ String mftname = this._file.substring(0, this._file.lastIndexOf(".world")) + ".mft";
+ System.out.println("MMAState:Manifesting: " + mftname);
+
+ try {
+ Manifest mft = new Manifest(mftname);
+ mft.saveProps(w);
+ mft.done();
+ } catch (Exception var7) {
+ var7.printStackTrace(System.out);
+ }
+
+ if (w != Pilot.getActive().getWorld()) {
+ w.discard();
+ }
+ } else {
+ if (err == null) {
+ err = Console.message("No-contain-world");
+ o.decRef();
+ }
+
+ Console.println(Console.message("Cant-load-remote") + url + "' ");
+ }
+
+ this._curFile++;
+ this.startFile();
+ }
+}
diff --git a/NET/worlds/scape/MultiMotion.java b/NET/worlds/scape/MultiMotion.java
new file mode 100644
index 0000000..7bede30
--- /dev/null
+++ b/NET/worlds/scape/MultiMotion.java
@@ -0,0 +1,531 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import java.io.IOException;
+import java.text.MessageFormat;
+import java.util.Date;
+
+class MultiMotion extends TriggeredSwitchableBehavior implements FrameHandler, Persister, MouseDownHandler, BumpHandler {
+ protected int motionNumber = 0;
+ protected int motionNumberCount = 0;
+ protected int motionNumberMax = 100;
+ long startMultiMotionTime;
+ long totalMultiMotionTime = 0L;
+ protected String cycleTime;
+ protected float[] cycleTimeArray;
+ protected int cycles;
+ protected Transform MultiMotionTransform;
+ protected String startPoint;
+ protected String endPoint;
+ protected String deltaPoint;
+ protected String startScale;
+ protected String endScale;
+ protected String deltaScale;
+ protected String startSpin;
+ protected String endSpin;
+ protected Point3[] startPointArray;
+ protected Point3[] endPointArray;
+ protected Point3[] deltaPointArray;
+ protected Point3[] startScaleArray;
+ protected Point3[] endScaleArray;
+ protected Point3[] deltaScaleArray;
+ protected Point3[] startSpinArray;
+ protected Point3[] endSpinArray;
+ protected String startRotation;
+ protected String endRotation;
+ protected float[] startRotationArray;
+ protected float[] endRotationArray;
+ protected boolean MultiMotionTransformInitialized;
+ protected boolean variableInitialized;
+ protected boolean multiMotionEnd = true;
+
+ public MultiMotion() {
+ this.cycleTime = new String("1000");
+ this.cycleTimeArray = new float[this.motionNumberMax];
+ this.cycleTimeArray[0] = 1000.0F;
+ this.trigger = new String("none");
+ this.externalTriggerTag = new String("");
+ this.cycles = 0;
+ this.MultiMotionTransformInitialized = false;
+ this.variableInitialized = false;
+ this.startPointArray = new Point3[this.motionNumberMax];
+ this.endPointArray = new Point3[this.motionNumberMax];
+ this.deltaPointArray = new Point3[this.motionNumberMax];
+ this.startScaleArray = new Point3[this.motionNumberMax];
+ this.endScaleArray = new Point3[this.motionNumberMax];
+ this.deltaScaleArray = new Point3[this.motionNumberMax];
+ this.startSpinArray = new Point3[this.motionNumberMax];
+ this.endSpinArray = new Point3[this.motionNumberMax];
+
+ for (int i = 0; i < this.motionNumberMax; i++) {
+ this.startPointArray[i] = new Point3();
+ this.endPointArray[i] = new Point3();
+ this.deltaPointArray[i] = new Point3();
+ this.startScaleArray[i] = new Point3();
+ this.endScaleArray[i] = new Point3();
+ this.deltaScaleArray[i] = new Point3();
+ this.startSpinArray[i] = new Point3();
+ this.endSpinArray[i] = new Point3();
+ }
+
+ this.startRotationArray = new float[this.motionNumberMax];
+ this.endRotationArray = new float[this.motionNumberMax];
+ this.startMultiMotion();
+ }
+
+ @Override
+ public void ExternalTrigger(Trigger trigger_source, int sequence_no, int event_no) {
+ this.trigger_source = trigger_source;
+ this.sequence_no = sequence_no;
+ this.event_no = event_no;
+ this.startMultiMotion();
+ }
+
+ public void startMultiMotion() {
+ Date timer = new Date();
+ this.startMultiMotionTime = timer.getTime();
+ this.motionNumber = 0;
+ this.multiMotionEnd = false;
+ }
+
+ public void setTotalMultiMotionTime() {
+ this.totalMultiMotionTime = 0L;
+
+ for (int i = 0; i < this.motionNumberCount; i++) {
+ this.totalMultiMotionTime = this.totalMultiMotionTime + (int)this.cycleTimeArray[i];
+ }
+ }
+
+ public void parseFloatString(String floatList, float[] floatArray) {
+ int currentIndex = 0;
+ int currentSeparator = 0;
+ int nextSeparator = 0;
+ int lastSeparator = floatList.lastIndexOf(" ");
+ if (lastSeparator != -1 || floatList.length() != 0) {
+ if (lastSeparator == -1) {
+ floatArray[currentIndex] = Float.valueOf(floatList);
+ } else {
+ nextSeparator = floatList.indexOf(" ");
+ floatArray[currentIndex] = Float.valueOf(floatList.substring(0, nextSeparator));
+ currentIndex++;
+
+ while (nextSeparator != lastSeparator) {
+ currentSeparator = nextSeparator;
+ nextSeparator = floatList.indexOf(" ", nextSeparator + 1);
+ floatArray[currentIndex] = Float.valueOf(floatList.substring(currentSeparator + 1, nextSeparator));
+ currentIndex++;
+ }
+
+ floatArray[currentIndex] = Float.valueOf(floatList.substring(nextSeparator + 1));
+ }
+ }
+ }
+
+ public Point3 StringToPoint3(String Point3String) {
+ Point3 newPoint3 = new Point3();
+ int currentIndex = 0;
+ newPoint3.x = Float.valueOf(Point3String.substring(currentIndex, Point3String.indexOf(",", currentIndex)));
+ currentIndex = Point3String.indexOf(",", currentIndex) + 1;
+ newPoint3.y = Float.valueOf(Point3String.substring(currentIndex, Point3String.indexOf(",", currentIndex)));
+ currentIndex = Point3String.indexOf(",", currentIndex) + 1;
+ newPoint3.z = Float.valueOf(Point3String.substring(currentIndex, Point3String.length()));
+ return newPoint3;
+ }
+
+ public void parsePoint3String(String Point3List, Point3[] Point3Array) {
+ int currentIndex = 0;
+ int currentSeparator = 0;
+ int nextSeparator = 0;
+ int lastSeparator = Point3List.lastIndexOf(" ");
+ if (lastSeparator != -1 || Point3List.length() != 0) {
+ if (lastSeparator == -1) {
+ Point3Array[currentIndex] = this.StringToPoint3(Point3List);
+ } else {
+ nextSeparator = Point3List.indexOf(" ");
+ Point3Array[currentIndex] = this.StringToPoint3(Point3List.substring(0, nextSeparator));
+ currentIndex++;
+
+ while (nextSeparator != lastSeparator) {
+ currentSeparator = nextSeparator;
+ nextSeparator = Point3List.indexOf(" ", nextSeparator + 1);
+ Point3Array[currentIndex] = this.StringToPoint3(Point3List.substring(currentSeparator + 1, nextSeparator));
+ currentIndex++;
+ }
+
+ Point3Array[currentIndex] = this.StringToPoint3(Point3List.substring(nextSeparator + 1));
+ }
+ }
+ }
+
+ @Override
+ public boolean handle(FrameEvent e) {
+ if (!this.MultiMotionTransformInitialized) {
+ this.MultiMotionTransform = e.target;
+ this.MultiMotionTransformInitialized = true;
+ }
+
+ if (!this.variableInitialized) {
+ this.startPoint = this.MultiMotionTransform.getPosition().toString();
+ this.startPointArray[0].copy(this.MultiMotionTransform.getPosition());
+ this.endPoint = new String(this.startPoint);
+ this.endPointArray[0].copy(this.startPointArray[0]);
+ this.startScaleArray[0].x = this.MultiMotionTransform.getTotalScale();
+ this.startScaleArray[0].y = this.MultiMotionTransform.getTotalScale();
+ this.startScaleArray[0].z = this.MultiMotionTransform.getTotalScale();
+ this.startScale = this.startScaleArray[0].toString();
+ this.endScaleArray[0].copy(this.startScaleArray[0]);
+ this.endScale = this.endScaleArray[0].toString();
+ this.startRotation = new Float(this.MultiMotionTransform.getSpin(this.startSpinArray[0])).toString();
+ this.startRotationArray[0] = Float.valueOf(this.startRotation);
+ this.startSpin = this.startSpinArray[0].toString();
+ this.endRotation = new String("0.0");
+ this.endRotationArray[0] = Float.valueOf(this.endRotation);
+ this.endSpinArray[0] = new Point3();
+ this.endSpin = this.endSpinArray[0].toString();
+ this.variableInitialized = true;
+ }
+
+ if (this.enabled) {
+ Date timer = new Date();
+ long currentTime = timer.getTime();
+ int cycleNo = 0;
+ if (this.totalMultiMotionTime > 0L) {
+ cycleNo = (int)((-this.startMultiMotionTime + currentTime) / this.totalMultiMotionTime);
+ }
+
+ if (this.totalMultiMotionTime > 0L && (cycleNo < this.cycles || this.cycles == 0)) {
+ long totalTime = 0L;
+ int currentCycleTime = (int)((currentTime - this.startMultiMotionTime) % this.totalMultiMotionTime);
+ int currentMotionTime = 0;
+
+ for (this.motionNumber = 0; this.motionNumber < this.motionNumberCount && totalTime <= currentCycleTime; this.motionNumber++) {
+ currentMotionTime = (int)this.cycleTimeArray[this.motionNumber];
+ totalTime += currentMotionTime;
+ }
+
+ this.motionNumber--;
+ if (totalTime < currentCycleTime) {
+ System.out.print("Error in totalMultiMotionTime computation.\n");
+ }
+
+ currentMotionTime = (int)(currentMotionTime - (totalTime - currentCycleTime));
+ float frameLoc = currentMotionTime % this.cycleTimeArray[this.motionNumber] / this.cycleTimeArray[this.motionNumber];
+ e.receiver.makeIdentity();
+ e.receiver
+ .scale(
+ this.startScaleArray[this.motionNumber].x + (this.endScaleArray[this.motionNumber].x - this.startScaleArray[this.motionNumber].x) * frameLoc,
+ this.startScaleArray[this.motionNumber].x + (this.endScaleArray[this.motionNumber].x - this.startScaleArray[this.motionNumber].x) * frameLoc,
+ this.startScaleArray[this.motionNumber].x + (this.endScaleArray[this.motionNumber].x - this.startScaleArray[this.motionNumber].x) * frameLoc
+ );
+ e.receiver
+ .moveTo(
+ this.startPointArray[this.motionNumber].x + (this.endPointArray[this.motionNumber].x - this.startPointArray[this.motionNumber].x) * frameLoc,
+ this.startPointArray[this.motionNumber].y + (this.endPointArray[this.motionNumber].y - this.startPointArray[this.motionNumber].y) * frameLoc,
+ this.startPointArray[this.motionNumber].z + (this.endPointArray[this.motionNumber].z - this.startPointArray[this.motionNumber].z) * frameLoc
+ );
+ e.receiver.spin(this.startSpinArray[this.motionNumber], this.startRotationArray[this.motionNumber]);
+ e.receiver.spin(this.endSpinArray[this.motionNumber], this.endRotationArray[this.motionNumber] * frameLoc);
+ } else if (cycleNo >= this.cycles && this.cycles != 0 && !this.multiMotionEnd) {
+ this.multiMotionEnd = true;
+ if (this.trigger_source != null) {
+ this.trigger_source.registerFinishedTriggerTag(this.sequence_no, this.event_no);
+ }
+ }
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean handle(MouseDownEvent e) {
+ if (this.enabled && this.trigger.equals("click")) {
+ this.startMultiMotion();
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean handle(BumpEventTemp e) {
+ if (this.enabled && this.trigger.equals("bump")) {
+ this.startMultiMotion();
+ }
+
+ return true;
+ }
+
+ public void startTransform() {
+ if (this.MultiMotionTransform != null) {
+ this.MultiMotionTransform.makeIdentity();
+ this.MultiMotionTransform
+ .scale(this.startScaleArray[this.motionNumber].x, this.startScaleArray[this.motionNumber].x, this.startScaleArray[this.motionNumber].x);
+ this.MultiMotionTransform
+ .moveTo(this.startPointArray[this.motionNumber].x, this.startPointArray[this.motionNumber].y, this.startPointArray[this.motionNumber].z);
+ this.MultiMotionTransform.spin(this.startSpinArray[this.motionNumber], this.startRotationArray[this.motionNumber]);
+ }
+ }
+
+ public void endTransform() {
+ if (this.MultiMotionTransform != null) {
+ this.MultiMotionTransform.makeIdentity();
+ this.MultiMotionTransform
+ .scale(this.endScaleArray[this.motionNumber].x, this.endScaleArray[this.motionNumber].x, this.endScaleArray[this.motionNumber].x);
+ this.MultiMotionTransform
+ .moveTo(this.endPointArray[this.motionNumber].x, this.endPointArray[this.motionNumber].y, this.endPointArray[this.motionNumber].z);
+ this.MultiMotionTransform.spin(this.startSpinArray[this.motionNumber], this.startRotationArray[this.motionNumber]);
+ this.MultiMotionTransform.spin(this.endSpinArray[this.motionNumber], this.endRotationArray[this.motionNumber]);
+ }
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = new ClassProperty(this, index, "MultiMotion");
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = IntegerPropertyEditor.make(new Property(this, index, "Number of Motions"));
+ } else if (mode == 1) {
+ ret = new Integer(this.motionNumberCount);
+ } else if (mode == 2) {
+ this.motionNumberCount = (Integer)value;
+ this.setTotalMultiMotionTime();
+ }
+ break;
+ case 2:
+ if (mode == 0) {
+ ret = IntegerPropertyEditor.make(new Property(this, index, "Cycles"));
+ } else if (mode == 1) {
+ ret = new Integer(this.cycles);
+ } else if (mode == 2) {
+ this.cycles = (Integer)value;
+ }
+ break;
+ case 3:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Trigger"));
+ } else if (mode == 1) {
+ ret = new String(this.trigger);
+ } else if (mode == 2) {
+ this.trigger = ((String)value).toString().trim();
+ if (this.trigger.equals("external")) {
+ Trigger.TriggeredSwitchableBehaviorList[Trigger.TriggeredSwitchableBehaviorListCount] = this;
+ Trigger.TriggeredSwitchableBehaviorListCount++;
+ }
+ }
+ break;
+ case 4:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "External Trigger Tag"));
+ } else if (mode == 1) {
+ ret = new String(this.externalTriggerTag);
+ } else if (mode == 2) {
+ this.externalTriggerTag = ((String)value).toString().trim();
+ }
+ break;
+ case 5:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Cycle Time"));
+ } else if (mode == 1) {
+ ret = new String(this.cycleTime);
+ } else if (mode == 2) {
+ this.cycleTime = (String)value;
+ this.parseFloatString(this.cycleTime, this.cycleTimeArray);
+ this.setTotalMultiMotionTime();
+ }
+ break;
+ case 6:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "End Point"));
+ } else if (mode == 1) {
+ ret = new String(this.endPoint);
+ this.endTransform();
+ } else if (mode == 2) {
+ this.endPoint = (String)value;
+ this.parsePoint3String(this.endPoint, this.endPointArray);
+ this.endTransform();
+ }
+ break;
+ case 7:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Start Point"));
+ } else if (mode == 1) {
+ ret = new String(this.startPoint);
+ this.startTransform();
+ } else if (mode == 2) {
+ this.startPoint = (String)value;
+ this.parsePoint3String(this.startPoint, this.startPointArray);
+ this.startTransform();
+ }
+ break;
+ case 8:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "End Scale"));
+ } else if (mode == 1) {
+ ret = new String(this.endScale);
+ this.endTransform();
+ } else if (mode == 2) {
+ this.endScale = (String)value;
+ this.parsePoint3String(this.endScale, this.endScaleArray);
+ this.endTransform();
+ }
+ break;
+ case 9:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Start Scale"));
+ } else if (mode == 1) {
+ ret = new String(this.startScale);
+ this.startTransform();
+ } else if (mode == 2) {
+ this.startScale = (String)value;
+ this.parsePoint3String(this.startScale, this.startScaleArray);
+ this.startTransform();
+ }
+ break;
+ case 10:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "End Spin (Relative)"));
+ } else if (mode == 1) {
+ ret = new String(this.endSpin);
+ this.endTransform();
+ } else if (mode == 2) {
+ this.endSpin = (String)value;
+ this.parsePoint3String(this.endSpin, this.endSpinArray);
+ this.endTransform();
+ }
+ break;
+ case 11:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Start Spin"));
+ } else if (mode == 1) {
+ ret = new String(this.startSpin);
+ this.startTransform();
+ } else if (mode == 2) {
+ this.startSpin = (String)value;
+ this.parsePoint3String(this.startSpin, this.startSpinArray);
+ this.startTransform();
+ }
+ break;
+ case 12:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "End Rotation (Relative)"));
+ } else if (mode == 1) {
+ ret = new String(this.endRotation);
+ this.endTransform();
+ } else if (mode == 2) {
+ this.endRotation = (String)value;
+ this.parseFloatString(this.endRotation, this.endRotationArray);
+ this.endTransform();
+ }
+ break;
+ case 13:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Start Rotation"));
+ } else if (mode == 1) {
+ ret = new String(this.startRotation);
+ this.startTransform();
+ } else if (mode == 2) {
+ this.startRotation = (String)value;
+ this.parseFloatString(this.startRotation, this.startRotationArray);
+ this.startTransform();
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 14, mode, value);
+ }
+
+ if (mode == 2 && this.trigger.equals("none")) {
+ this.startMultiMotion();
+ }
+
+ return ret;
+ }
+
+ @Override
+ public String toString() {
+ return "Multimotion: cycleTime "
+ + this.cycleTime
+ + ", cycles "
+ + this.cycles
+ + ", enabled "
+ + this.enabled
+ + ", trigger "
+ + this.trigger
+ + ", externalTriggerTag "
+ + this.externalTriggerTag;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveInt(this.motionNumberCount);
+ s.saveInt(this.cycles);
+ s.saveString(this.trigger);
+ s.saveString(this.externalTriggerTag);
+ s.saveString(this.cycleTime);
+ s.saveString(this.endPoint);
+ s.saveString(this.startPoint);
+ s.saveString(this.endScale);
+ s.saveString(this.startScale);
+ s.saveString(this.endSpin);
+ s.saveString(this.startSpin);
+ s.saveString(this.endRotation);
+ s.saveString(this.startRotation);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException {
+ this.motionNumberCount = r.restoreInt();
+ this.cycles = r.restoreInt();
+ this.trigger = r.restoreString();
+ if (this.trigger.equals("external")) {
+ Trigger.TriggeredSwitchableBehaviorList[Trigger.TriggeredSwitchableBehaviorListCount] = this;
+ Trigger.TriggeredSwitchableBehaviorListCount++;
+ }
+
+ this.externalTriggerTag = r.restoreString();
+ this.cycleTime = r.restoreString();
+ this.parseFloatString(this.cycleTime, this.cycleTimeArray);
+ this.endPoint = r.restoreString();
+ this.parsePoint3String(this.endPoint, this.endPointArray);
+ this.setTotalMultiMotionTime();
+ this.startPoint = r.restoreString();
+ this.parsePoint3String(this.startPoint, this.startPointArray);
+ this.endScale = r.restoreString();
+ this.parsePoint3String(this.endScale, this.endScaleArray);
+ this.startScale = r.restoreString();
+ this.parsePoint3String(this.startScale, this.startScaleArray);
+ this.endSpin = r.restoreString();
+ this.parsePoint3String(this.endSpin, this.endSpinArray);
+ this.startSpin = r.restoreString();
+ this.parsePoint3String(this.startSpin, this.startSpinArray);
+ this.endRotation = r.restoreString();
+ this.parseFloatString(this.endRotation, this.endRotationArray);
+ this.startRotation = r.restoreString();
+ this.parseFloatString(this.startRotation, this.startRotationArray);
+ this.variableInitialized = true;
+ if (!this.trigger.equals("none")) {
+ this.startMultiMotionTime = (int)(-(this.cycles * this.cycleTimeArray[this.motionNumber]));
+ } else {
+ this.startMultiMotion();
+ }
+ }
+
+ @Override
+ public void postRestore(int version) {
+ String name = this.getName();
+ String arg1 = name == null ? "<null>" : name;
+ SuperRoot owner = this.getOwner();
+ String oname = "";
+ if (owner != null) {
+ oname = owner.getName();
+ }
+
+ String arg2 = oname == null ? "<null>" : oname;
+ Object[] arguments = new Object[]{new String(arg1), new String(arg2)};
+ Console.println(MessageFormat.format(Console.message("MultiMotion-obs"), arguments));
+ }
+}
diff --git a/NET/worlds/scape/MusicManager.java b/NET/worlds/scape/MusicManager.java
new file mode 100644
index 0000000..9ef0cac
--- /dev/null
+++ b/NET/worlds/scape/MusicManager.java
@@ -0,0 +1,258 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.DialogReceiver;
+import NET.worlds.console.Main;
+import NET.worlds.console.MainCallback;
+import NET.worlds.core.Sort;
+import NET.worlds.network.URL;
+import java.io.DataInputStream;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.StringTokenizer;
+
+public class MusicManager implements MainCallback, DialogReceiver {
+ private static Hashtable managers = new Hashtable();
+ private static MusicManagerDialog dialog;
+ private static boolean registered;
+ private static URL lastWorldURL;
+ private static boolean showDialog;
+ private static MusicManager curManager;
+ private static String lastRoomName = "";
+ private static int lastCDTrack;
+ private static URL lastMIDIFile;
+ private String name;
+ private Hashtable tracks = new Hashtable();
+ private Hashtable rooms = new Hashtable();
+ private World world;
+ private String fileName;
+ private boolean maybeMusicChange;
+
+ public static void showDialog() {
+ if (dialog == null) {
+ showDialog = true;
+ }
+ }
+
+ public MusicManager() {
+ if (!registered) {
+ Main.register(this);
+ registered = true;
+ curManager = this;
+ }
+ }
+
+ private MusicManager(World world, URL url) {
+ this.world = world;
+ this.name = world.getName();
+ String file = url.unalias().toLowerCase();
+ int index = file.lastIndexOf(".world");
+ if (index != -1) {
+ this.fileName = url.unalias().substring(0, index) + ".music";
+ this.load();
+ }
+ }
+
+ public World getWorld() {
+ return this.world;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public String getFileName() {
+ return this.fileName;
+ }
+
+ public Hashtable getMusic() {
+ return this.tracks;
+ }
+
+ public MusicTrack getMusic(String name) {
+ return (MusicTrack)this.tracks.get(name);
+ }
+
+ public Hashtable getRooms() {
+ return this.rooms;
+ }
+
+ public MusicRoom getRoom(String name) {
+ return (MusicRoom)this.rooms.get(name);
+ }
+
+ public synchronized void maybeChangedMusic() {
+ this.maybeMusicChange = true;
+ }
+
+ public void save() {
+ PrintStream out = null;
+
+ try {
+ out = new PrintStream(new FileOutputStream(this.fileName));
+ Enumeration e = this.tracks.elements();
+ String[] keys = Sort.sortKeys(this.tracks);
+
+ for (int i = 0; i < keys.length; i++) {
+ MusicTrack m = (MusicTrack)this.tracks.get(keys[i]);
+ String midiName = m.getMIDIFileName();
+ if (midiName.length() == 0) {
+ midiName = "-";
+ }
+
+ out.println("MUSIC|" + m.getName() + "|" + m.getVirtTrackNumber() + "|" + midiName + "|" + m.getLooping());
+ }
+
+ keys = Sort.sortKeys(this.rooms);
+
+ for (int i = 0; i < keys.length; i++) {
+ MusicRoom r = (MusicRoom)this.rooms.get(keys[i]);
+ out.println("ROOM|" + r.getRoomName() + "|" + r.getMusicName());
+ }
+ } catch (Exception var10) {
+ } finally {
+ if (out != null) {
+ out.close();
+ }
+ }
+ }
+
+ private void load() {
+ this.tracks.clear();
+ this.rooms.clear();
+ DataInputStream in = null;
+ String line = null;
+
+ try {
+ in = new DataInputStream(new FileInputStream(this.fileName));
+
+ while ((line = in.readLine()) != null) {
+ StringTokenizer tok = new StringTokenizer(line, "|");
+ String type = tok.nextToken();
+ if (type.equals("MUSIC")) {
+ MusicTrack track = new MusicTrack(tok.nextToken(), Integer.parseInt(tok.nextToken()), tok.nextToken(), Boolean.valueOf(tok.nextToken()));
+ this.tracks.put(track.getName(), track);
+ } else if (type.equals("ROOM")) {
+ MusicRoom room = new MusicRoom(tok.nextToken(), tok.nextToken());
+ this.rooms.put(room.getRoomName(), room);
+ }
+ }
+ } catch (Exception var14) {
+ } finally {
+ try {
+ if (in != null) {
+ in.close();
+ }
+ } catch (IOException var13) {
+ }
+ }
+ }
+
+ @Override
+ public void mainCallback() {
+ Pilot pilot = Pilot.getActive();
+ if (pilot != null) {
+ World world = pilot.getWorld();
+ boolean worldChange = false;
+ String newRoomName = "";
+ if (world != null) {
+ URL url = world.getSourceURL();
+ if (!url.equals(lastWorldURL)) {
+ MusicManager manager = (MusicManager)managers.get(url);
+ if (manager == null) {
+ manager = new MusicManager(world, url);
+ managers.put(url, manager);
+ }
+
+ lastWorldURL = url;
+ curManager = manager;
+ worldChange = true;
+ }
+
+ Room room = pilot.getRoom();
+ if (room != null) {
+ String roomName = room.getName();
+ if (roomName != null) {
+ newRoomName = roomName;
+ }
+ }
+ } else {
+ lastWorldURL = null;
+ }
+
+ synchronized (this) {
+ if (worldChange || !newRoomName.equals(lastRoomName) || curManager.maybeMusicChange) {
+ curManager.maybeMusicChange = false;
+ lastRoomName = newRoomName;
+ MusicRoom mr = curManager.getRoom(lastRoomName);
+ CDAudio cd = CDAudio.get();
+ boolean found = false;
+ if (mr != null) {
+ MusicTrack mt = curManager.getMusic(mr.getMusicName());
+ if (mt != null) {
+ found = true;
+ int track = mt.getVirtTrackNumber();
+ boolean changed = false;
+ if (track != cd.getCDTrack()) {
+ lastCDTrack = track;
+ cd.setCDTrack(track);
+ changed = true;
+ }
+
+ String name = mt.getMIDIFileName();
+ URL midiPath;
+ if (name.length() != 0) {
+ midiPath = URL.make(world.getSourceURL(), mt.getMIDIFileName());
+ } else {
+ midiPath = cd.getDefaultMIDIFile();
+ }
+
+ if (!midiPath.equals(cd.getMIDIFile())) {
+ lastMIDIFile = midiPath;
+ cd.setMIDIFile(midiPath);
+ changed = true;
+ }
+
+ if (changed) {
+ cd.change(mt.getLooping());
+ }
+ }
+ }
+
+ if (!found) {
+ if (lastCDTrack != 0 && cd.getCDTrack() == lastCDTrack || lastMIDIFile != null && lastMIDIFile.equals(cd.getMIDIFile())) {
+ cd.setCDTrack(0);
+ cd.setMIDIFile(cd.getDefaultMIDIFile());
+ cd.stop();
+ }
+
+ lastCDTrack = 0;
+ lastMIDIFile = null;
+ }
+ }
+ }
+ } else {
+ lastWorldURL = null;
+ }
+
+ if (lastWorldURL != null && dialog == null && showDialog) {
+ showDialog = false;
+ dialog = new MusicManagerDialog((MusicManager)managers.get(lastWorldURL));
+ }
+ }
+
+ @Override
+ public void dialogDone(Object who, boolean confirmed) {
+ if (confirmed) {
+ this.save();
+ } else {
+ this.load();
+ this.maybeChangedMusic();
+ }
+
+ dialog = null;
+ }
+}
diff --git a/NET/worlds/scape/MusicManagerDialog.java b/NET/worlds/scape/MusicManagerDialog.java
new file mode 100644
index 0000000..50e643d
--- /dev/null
+++ b/NET/worlds/scape/MusicManagerDialog.java
@@ -0,0 +1,397 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.ConfirmDialog;
+import NET.worlds.console.Console;
+import NET.worlds.console.DialogReceiver;
+import NET.worlds.console.OkCancelDialog;
+import NET.worlds.console.PolledDialog;
+import NET.worlds.core.Sort;
+import java.awt.BorderLayout;
+import java.awt.Button;
+import java.awt.Checkbox;
+import java.awt.CheckboxGroup;
+import java.awt.Font;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Label;
+import java.awt.List;
+import java.awt.Panel;
+import java.awt.Point;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+class MusicManagerDialog extends PolledDialog implements DialogReceiver {
+ private MusicManager manager;
+ private String lastRoom = "";
+ private Label curRoom = new Label();
+ private Label curMusic = new Label();
+ private Button assignCurButton = new Button(Console.message("Assign-Current"));
+ private Checkbox autoAssign = new Checkbox(Console.message("Auto-assign"));
+ private CheckboxGroup group = new CheckboxGroup();
+ private Checkbox musicBox = new Checkbox(Console.message("Music"), this.group, true);
+ private Checkbox aRoomsBox = new Checkbox(Console.message("Assigned-rooms"), this.group, false);
+ private Checkbox uRoomsBox = new Checkbox(Console.message("Unassigned-rooms"), this.group, false);
+ private List list = new List(10);
+ private Button editButton = new Button(Console.message("Edit"));
+ private Button addButton = new Button(Console.message("Add"));
+ private Button delButton = new Button(Console.message("Delete"));
+ private Button assignButton = new Button(Console.message("Assign"));
+ private Button saveButton = new Button(Console.message("Save-Changes"));
+ private Button okButton = new Button(Console.message("OK"));
+ private Button cancelButton = new Button(Console.message("Cancel"));
+ private PolledDialog subDialog;
+ private Vector allRooms;
+ private boolean madeChanges;
+ private boolean confirmingState;
+ static Point lastWindowLocation = null;
+ private static Font font = new Font(Console.message("MenuFont"), 0, 12);
+ private static Font bfont = new Font(Console.message("ButtonFont"), 0, 12);
+ private static final String title = Console.message("Music-Manager");
+
+ public MusicManagerDialog(MusicManager manager) {
+ super(Console.getFrame(), manager, title + manager.getName(), false);
+ this.setAlignment(2);
+ this.manager = manager;
+ this.ready();
+ }
+
+ public MusicManager getManager() {
+ return this.manager;
+ }
+
+ public String getCurRoom() {
+ return this.curRoom.getText();
+ }
+
+ public Vector getAllRooms() {
+ return this.allRooms;
+ }
+
+ @Override
+ protected void build() {
+ GridBagLayout gbag = new GridBagLayout();
+ this.setLayout(gbag);
+ GridBagConstraints c = new GridBagConstraints();
+ Panel p = new Panel(new BorderLayout());
+ this.musicBox.setFont(font);
+ this.aRoomsBox.setFont(font);
+ this.uRoomsBox.setFont(font);
+ p.add("West", this.musicBox);
+ p.add("Center", this.aRoomsBox);
+ p.add("East", this.uRoomsBox);
+ c.weightx = 0.0;
+ c.gridwidth = 0;
+ this.add(gbag, p, c);
+ c.fill = 1;
+ c.weightx = 1.0;
+ c.weighty = 1.0;
+ c.gridwidth = 2;
+ c.gridheight = 6;
+ this.list.setFont(font);
+ this.add(gbag, this.list, c);
+ c.fill = 2;
+ c.weightx = 0.0;
+ c.weighty = 0.0;
+ c.gridwidth = 0;
+ c.gridheight = 1;
+ this.assignButton.setFont(bfont);
+ this.editButton.setFont(bfont);
+ this.addButton.setFont(bfont);
+ this.delButton.setFont(bfont);
+ this.add(gbag, this.assignButton, c);
+ this.add(gbag, this.editButton, c);
+ this.add(gbag, this.addButton, c);
+ this.add(gbag, this.delButton, c);
+
+ for (int i = 0; i < 2; i++) {
+ this.add(gbag, new Label(""), c);
+ }
+
+ c.gridwidth = 1;
+ c.fill = 0;
+ Label cRoom = new Label(Console.message("Current-room"));
+ cRoom.setFont(font);
+ this.add(gbag, cRoom, c);
+ c.gridwidth = 0;
+ c.weightx = 1.0;
+ c.fill = 2;
+ this.curRoom.setFont(font);
+ this.add(gbag, this.curRoom, c);
+ c.gridwidth = 1;
+ c.weightx = 0.0;
+ Label aMusic = new Label(Console.message("Assigned-music"));
+ aMusic.setFont(font);
+ this.add(gbag, aMusic, c);
+ c.fill = 0;
+ c.gridwidth = 0;
+ c.fill = 2;
+ c.weightx = 1.0;
+ this.curMusic.setFont(font);
+ this.add(gbag, this.curMusic, c);
+ c.weightx = 0.0;
+ c.weighty = 0.0;
+ c.gridwidth = 1;
+ c.fill = 0;
+ this.assignCurButton.setFont(bfont);
+ this.autoAssign.setFont(bfont);
+ this.add(gbag, this.assignCurButton, c);
+ c.gridwidth = 0;
+ this.add(gbag, this.autoAssign, c);
+ p = new Panel();
+ p.setFont(bfont);
+ p.add(this.saveButton);
+ p.add(this.okButton);
+ p.add(this.cancelButton);
+ c.fill = 2;
+ this.add(gbag, p, c);
+ this.rebuildList(false);
+ this.buildAllRoomsList();
+ }
+
+ @Override
+ protected boolean done(boolean confirmed) {
+ lastWindowLocation = this.getLocation();
+ return super.done(confirmed);
+ }
+
+ @Override
+ protected void initialSize(int width, int height) {
+ if (lastWindowLocation == null) {
+ super.initialSize(width, height);
+ } else {
+ this.setLocation(lastWindowLocation);
+ this.setSize(width, height);
+ }
+ }
+
+ private void buildAllRoomsList() {
+ this.allRooms = new Vector();
+ Pilot pilot = Pilot.getActive();
+ if (pilot != null) {
+ World world = pilot.getWorld();
+ if (world != null) {
+ Enumeration rooms = world.getRooms();
+
+ while (rooms.hasMoreElements()) {
+ this.allRooms.addElement(((Room)rooms.nextElement()).getName());
+ }
+ }
+ }
+ }
+
+ private void rebuildList(boolean changed) {
+ boolean enable = !this.uRoomsBox.getState();
+ this.assignButton.setEnabled(!this.musicBox.getState());
+ this.editButton.setEnabled(enable);
+ this.addButton.setEnabled(enable);
+ this.delButton.setEnabled(enable);
+ this.list.removeAll();
+ if (this.musicBox.getState()) {
+ Sort.sortInto(this.list, this.manager.getMusic());
+ } else if (this.aRoomsBox.getState()) {
+ String[] content = Sort.sortKeys(this.manager.getRooms());
+
+ for (int i = 0; i < content.length; i++) {
+ String name = content[i];
+ this.list.add(name + " (" + this.manager.getRoom(name).getMusicName() + ")");
+ }
+ } else {
+ Enumeration e = this.allRooms.elements();
+ Hashtable aRooms = this.manager.getRooms();
+ Vector v = new Vector();
+
+ while (e.hasMoreElements()) {
+ String name = (String)e.nextElement();
+ if (!aRooms.containsKey(name)) {
+ v.addElement(name);
+ }
+ }
+
+ Sort.sortInto(this.list, v);
+ }
+
+ if (changed) {
+ this.madeChanges = true;
+ this.manager.maybeChangedMusic();
+ }
+ }
+
+ @Override
+ protected synchronized void activeCallback() {
+ Pilot pilot = Pilot.getActive();
+ if (pilot != null) {
+ World world = pilot.getWorld();
+ if (world != null && world.getSourceURL().equals(this.manager.getWorld().getSourceURL())) {
+ Room room = pilot.getRoom();
+ if (room != null) {
+ String name = room.getName();
+ if (!name.equals(this.lastRoom)) {
+ this.lastRoom = name;
+ this.curRoom.setText(name);
+ MusicRoom mr = this.manager.getRoom(name);
+ if (mr != null) {
+ this.curMusic.setText(mr.getMusicName());
+ } else {
+ this.curMusic.setText("");
+ if (this.autoAssign.getState() && this.subDialog == null) {
+ this.subDialog = new EditRoomDialog(this, null, name);
+ }
+ }
+ }
+
+ return;
+ }
+ }
+ }
+
+ this.curRoom.setText("");
+ this.curMusic.setText("");
+ }
+
+ @Override
+ public synchronized boolean action(java.awt.Event event, Object what) {
+ Object target = event.target;
+ String selected = this.list.getSelectedItem();
+ boolean isMusic = this.musicBox.getState();
+ boolean haveMusic = this.manager.getMusic().size() != 0;
+ if (isMusic && target == this.editButton && selected != null) {
+ this.subDialog = new EditMusicDialog(this, this.manager.getMusic(selected));
+ } else if (isMusic && target == this.addButton) {
+ this.subDialog = new EditMusicDialog(this, null);
+ } else if (isMusic && target == this.delButton && selected != null) {
+ if (!this.isMusicInUse(selected)) {
+ this.manager.getMusic().remove(selected);
+ if (this.manager.getMusic().size() == 0) {
+ this.autoAssign.setState(false);
+ }
+
+ this.rebuildList(true);
+ } else {
+ this.cantChangeMusic();
+ }
+ } else if (!isMusic && target == this.editButton && selected != null && haveMusic) {
+ selected = selected.substring(0, selected.lastIndexOf(40) - 1);
+ this.subDialog = new EditRoomDialog(this, this.manager.getRoom(selected), selected);
+ } else if (!isMusic && target == this.addButton) {
+ if (haveMusic) {
+ this.subDialog = new EditRoomDialog(this, null, this.getCurRoom());
+ } else {
+ this.needMusic();
+ }
+ } else if (!isMusic && target == this.delButton && selected != null) {
+ selected = selected.substring(0, selected.lastIndexOf(40) - 1);
+ this.manager.getRooms().remove(selected);
+ this.rebuildList(true);
+ } else if (target == this.saveButton) {
+ this.manager.save();
+ this.madeChanges = false;
+ } else if (target == this.okButton) {
+ if (this.madeChanges) {
+ this.confirmingState = true;
+ new ConfirmDialog(this, this, Console.message("Save-Changes2"), Console.message("sure-save"));
+ } else {
+ this.done(false);
+ }
+ } else if (target == this.cancelButton) {
+ if (this.madeChanges) {
+ this.confirmingState = false;
+ new ConfirmDialog(this, this, Console.message("Abandon-Changes"), Console.message("sure-cancel"));
+ } else {
+ this.done(false);
+ }
+ } else if (target != this.musicBox && target != this.aRoomsBox && target != this.uRoomsBox) {
+ if ((target != this.assignButton || selected == null) && target != this.assignCurButton) {
+ if (target != this.autoAssign || !this.autoAssign.getState()) {
+ return false;
+ }
+
+ if (haveMusic) {
+ if (this.manager.getRoom(this.lastRoom) == null) {
+ this.subDialog = new EditRoomDialog(this, null, this.lastRoom);
+ }
+ } else {
+ this.autoAssign.setState(false);
+ this.needMusic();
+ }
+ } else if (haveMusic) {
+ String selection = target == this.assignButton ? selected : this.lastRoom;
+ this.subDialog = new EditRoomDialog(this, this.manager.getRoom(selection), selection);
+ } else {
+ this.needMusic();
+ }
+ } else {
+ this.rebuildList(false);
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean handleEvent(java.awt.Event event) {
+ if (event.key != 1004 && event.key != 1005 && event.key != 1006 && event.key != 1007) {
+ return super.handleEvent(event);
+ } else {
+ Console.getFrame().requestFocus();
+ return true;
+ }
+ }
+
+ private void needMusic() {
+ this.subDialog = new OkCancelDialog(this, this, Console.message("Need-Music"), null, Console.message("OK"), Console.message("at-least-one"), true);
+ }
+
+ private boolean isMusicInUse(String name) {
+ Enumeration e = this.manager.getRooms().elements();
+
+ while (e.hasMoreElements()) {
+ if (name.equals(((MusicRoom)e.nextElement()).getMusicName())) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private void cantChangeMusic() {
+ this.subDialog = new OkCancelDialog(this, this, Console.message("Cant-Change"), null, Console.message("OK"), Console.message("may-not-delete"), true);
+ }
+
+ @Override
+ public synchronized void dialogDone(Object who, boolean confirmed) {
+ boolean showCantChange = false;
+ if (confirmed) {
+ if (who instanceof EditMusicDialog) {
+ EditMusicDialog em = (EditMusicDialog)who;
+ MusicTrack music = em.getMusicTrack();
+ String oldName = em.getOldName();
+ if (oldName != null && !oldName.equals(music.getName()) && this.isMusicInUse(oldName)) {
+ music.setName(oldName);
+ showCantChange = true;
+ }
+
+ this.manager.getMusic().put(music.getName(), music);
+ this.rebuildList(true);
+ } else if (who instanceof EditRoomDialog) {
+ EditRoomDialog er = (EditRoomDialog)who;
+ MusicRoom room = er.getMusicRoom();
+ this.manager.getRooms().put(room.getRoomName(), room);
+ this.rebuildList(true);
+ } else if (who instanceof ConfirmDialog) {
+ this.done(this.confirmingState);
+ }
+
+ if (this.lastRoom != null) {
+ MusicRoom mr = this.manager.getRoom(this.lastRoom);
+ if (mr != null) {
+ this.curMusic.setText(mr.getMusicName());
+ }
+ }
+ }
+
+ this.subDialog = null;
+ if (showCantChange) {
+ this.cantChangeMusic();
+ }
+ }
+}
diff --git a/NET/worlds/scape/MusicRoom.java b/NET/worlds/scape/MusicRoom.java
new file mode 100644
index 0000000..1ce3299
--- /dev/null
+++ b/NET/worlds/scape/MusicRoom.java
@@ -0,0 +1,32 @@
+package NET.worlds.scape;
+
+class MusicRoom {
+ private String roomName;
+ private String musicName;
+
+ public MusicRoom(String roomName, String musicName) {
+ this.roomName = roomName;
+ this.musicName = musicName;
+ }
+
+ public String getRoomName() {
+ return this.roomName;
+ }
+
+ public void setRoomName(String roomName) {
+ this.roomName = roomName;
+ }
+
+ public String getMusicName() {
+ return this.musicName;
+ }
+
+ public void setMusicName(String musicName) {
+ this.musicName = musicName;
+ }
+
+ @Override
+ public String toString() {
+ return this.roomName;
+ }
+}
diff --git a/NET/worlds/scape/MusicTrack.java b/NET/worlds/scape/MusicTrack.java
new file mode 100644
index 0000000..9872a20
--- /dev/null
+++ b/NET/worlds/scape/MusicTrack.java
@@ -0,0 +1,52 @@
+package NET.worlds.scape;
+
+class MusicTrack {
+ private String name;
+ private int vTrack;
+ private String midi;
+ private boolean loop;
+
+ public MusicTrack(String name, int vTrack, String midi, boolean loop) {
+ this.name = name;
+ this.vTrack = vTrack;
+ this.midi = midi.equals("-") ? "" : midi;
+ this.loop = loop;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public int getVirtTrackNumber() {
+ return this.vTrack;
+ }
+
+ public void setVirtTrackNumber(int vTrack) {
+ this.vTrack = vTrack;
+ }
+
+ public String getMIDIFileName() {
+ return this.midi;
+ }
+
+ public void setMIDIFileName(String midi) {
+ this.midi = midi;
+ }
+
+ public boolean getLooping() {
+ return this.loop;
+ }
+
+ public void setLooping(boolean loop) {
+ this.loop = loop;
+ }
+
+ @Override
+ public String toString() {
+ return this.name;
+ }
+}
diff --git a/NET/worlds/scape/MutedDrone.java b/NET/worlds/scape/MutedDrone.java
new file mode 100644
index 0000000..cccc363
--- /dev/null
+++ b/NET/worlds/scape/MutedDrone.java
@@ -0,0 +1,46 @@
+package NET.worlds.scape;
+
+import NET.worlds.network.ObjID;
+import NET.worlds.network.URL;
+import NET.worlds.network.WorldServer;
+import java.io.IOException;
+
+public class MutedDrone extends Drone {
+ private static Object classCookie = new Object();
+
+ public MutedDrone(ObjID objID, WorldServer serv, URL url) {
+ super(objID, serv);
+ this.setSourceURL(url);
+ }
+
+ public MutedDrone() {
+ }
+
+ @Override
+ public Drone setAvatarNow(URL url) {
+ if (this.shouldBeMuted()) {
+ this.setSourceURL(url);
+ return this;
+ } else {
+ return super.setAvatarNow(url);
+ }
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(1, classCookie);
+ super.saveState(s);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ int vers = r.restoreVersion(classCookie);
+ switch (vers) {
+ case 1:
+ super.restoreState(r);
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/MyButton.java b/NET/worlds/scape/MyButton.java
new file mode 100644
index 0000000..8c5a077
--- /dev/null
+++ b/NET/worlds/scape/MyButton.java
@@ -0,0 +1,14 @@
+package NET.worlds.scape;
+
+import java.awt.Button;
+
+class MyButton extends Button {
+ int numParamsXYZ;
+ int numParamsN;
+
+ MyButton(String text, int numParamsXYZ, int numParamsN) {
+ super(text);
+ this.numParamsXYZ = numParamsXYZ;
+ this.numParamsN = numParamsN;
+ }
+}
diff --git a/NET/worlds/scape/NamedPortal.java b/NET/worlds/scape/NamedPortal.java
new file mode 100644
index 0000000..a90fbd4
--- /dev/null
+++ b/NET/worlds/scape/NamedPortal.java
@@ -0,0 +1,33 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+public class NamedPortal implements Persister {
+ private static Object classCookie = new Object();
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ assert false;
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ r.setOldFlag();
+ Portal p = new Portal();
+ r.replace(this, p);
+ p.restoreState(r);
+ String name = r.restoreString();
+ p.setName(name);
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+
+ @Override
+ public void postRestore(int version) {
+ assert false;
+ }
+}
diff --git a/NET/worlds/scape/NametagDrone.java b/NET/worlds/scape/NametagDrone.java
new file mode 100644
index 0000000..61bf382
--- /dev/null
+++ b/NET/worlds/scape/NametagDrone.java
@@ -0,0 +1,50 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import java.awt.Color;
+import java.io.IOException;
+
+public class NametagDrone extends Drone {
+ private static Object classCookie = new Object();
+
+ @Override
+ public void loadInit() {
+ }
+
+ @Override
+ public void setName(String v) {
+ super.setName(v);
+ SuperRoot nametag = SuperRoot.nameSearch(this.getContents(), "nametag");
+ if (nametag != null && nametag instanceof Hologram) {
+ Hologram oldtag = (Hologram)nametag;
+ String name = this.getLongID();
+ Texture[] tagText = new Texture[]{new StringTexture(name, Console.message("TextureFont"), 48, Color.black, Color.white)};
+ oldtag.detach();
+ Hologram newtag = new Hologram(tagText);
+ newtag.post(oldtag);
+ newtag.setScale(name.length() * 10, 1.0F, 10.0F);
+ newtag.setVisible(true);
+ newtag.setBumpable(false);
+ newtag.setLocalShadowed(false);
+ newtag.setShadowedLocally(true);
+ this.add(newtag);
+ }
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(0, classCookie);
+ super.saveState(s);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/NoSuchPropertyException.java b/NET/worlds/scape/NoSuchPropertyException.java
new file mode 100644
index 0000000..d25078d
--- /dev/null
+++ b/NET/worlds/scape/NoSuchPropertyException.java
@@ -0,0 +1,4 @@
+package NET.worlds.scape;
+
+public class NoSuchPropertyException extends Exception {
+}
diff --git a/NET/worlds/scape/NonPersister.java b/NET/worlds/scape/NonPersister.java
new file mode 100644
index 0000000..a21e402
--- /dev/null
+++ b/NET/worlds/scape/NonPersister.java
@@ -0,0 +1,4 @@
+package NET.worlds.scape;
+
+public interface NonPersister {
+}
diff --git a/NET/worlds/scape/NotifyScriptAction.java b/NET/worlds/scape/NotifyScriptAction.java
new file mode 100644
index 0000000..31f61e1
--- /dev/null
+++ b/NET/worlds/scape/NotifyScriptAction.java
@@ -0,0 +1,57 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+public class NotifyScriptAction extends Action {
+ private String message = "NotifyScriptAction";
+ private static Object classCookie = new Object();
+
+ public void setMessage(String m) {
+ this.message = m;
+ }
+
+ @Override
+ public Persister trigger(Event e, Persister seqId) {
+ WorldScriptManager.getInstance().action(this.message);
+ return null;
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Message"));
+ } else if (mode == 1) {
+ ret = new String(this.message);
+ } else if (mode == 2) {
+ this.message = (String)value;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 1, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(1, classCookie);
+ super.saveState(s);
+ s.saveString(this.message);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 1:
+ super.restoreState(r);
+ this.message = r.restoreString();
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/NumberAttribute.java b/NET/worlds/scape/NumberAttribute.java
new file mode 100644
index 0000000..b37cf6b
--- /dev/null
+++ b/NET/worlds/scape/NumberAttribute.java
@@ -0,0 +1,81 @@
+package NET.worlds.scape;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class NumberAttribute extends Attribute {
+ float value = 0.0F;
+ private static Object classCookie = new Object();
+
+ public NumberAttribute(int attrID) {
+ super(attrID);
+ }
+
+ public NumberAttribute() {
+ }
+
+ public void set(float x) {
+ this.value = x;
+ this.noteChange();
+ }
+
+ public float get() {
+ return this.value;
+ }
+
+ @Override
+ public void generateNetData(DataOutputStream s) throws IOException {
+ s.writeFloat(this.value);
+ }
+
+ @Override
+ public void setFromNetData(DataInputStream ds, int len) throws IOException {
+ this.value = ds.readFloat();
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "value"));
+ } else if (mode == 1) {
+ ret = new Float(this.get());
+ } else if (mode == 2) {
+ this.set((Float)value);
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 1, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(0, classCookie);
+ super.saveState(s);
+ s.saveFloat(this.value);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ this.value = r.restoreFloat();
+ this.set(this.value);
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + "[" + this.get() + "]";
+ }
+}
diff --git a/NET/worlds/scape/ObjEditorDialog.java b/NET/worlds/scape/ObjEditorDialog.java
new file mode 100644
index 0000000..a304dba
--- /dev/null
+++ b/NET/worlds/scape/ObjEditorDialog.java
@@ -0,0 +1,12 @@
+package NET.worlds.scape;
+
+class ObjEditorDialog extends ObjectSelectorDialog {
+ ObjEditorDialog(EditTile parent, String title, Property property, SuperRoot r, Class clas) {
+ super(parent, title, property, r, clas);
+ }
+
+ @Override
+ protected void addIt(Property p, Object obj) {
+ this.parent.addUndoableSet(p, obj);
+ }
+}
diff --git a/NET/worlds/scape/ObjPropertyEditor.java b/NET/worlds/scape/ObjPropertyEditor.java
new file mode 100644
index 0000000..73f0eb4
--- /dev/null
+++ b/NET/worlds/scape/ObjPropertyEditor.java
@@ -0,0 +1,37 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.PolledDialog;
+
+public class ObjPropertyEditor extends PropEditor {
+ SuperRoot root;
+ Class clas;
+
+ private ObjPropertyEditor(Property property, SuperRoot r, Class clas) {
+ super(property);
+ this.root = r;
+ this.clas = clas;
+ }
+
+ @Override
+ public PolledDialog edit(EditTile parent, String title) {
+ return new ObjEditorDialog(parent, title, this.property, this.root, this.clas);
+ }
+
+ public static Property make(Property property, SuperRoot r, Class clas) {
+ return property.setEditor(new ObjPropertyEditor(property, r, clas));
+ }
+
+ public static Property make(Property property, SuperRoot r, String clas) {
+ Class c = null;
+
+ try {
+ c = Class.forName(clas);
+ } catch (ClassNotFoundException var5) {
+ System.out.println("Couldn't find " + clas);
+
+ assert false;
+ }
+
+ return property.setEditor(new ObjPropertyEditor(property, r, c));
+ }
+}
diff --git a/NET/worlds/scape/ObjectAdderDialog.java b/NET/worlds/scape/ObjectAdderDialog.java
new file mode 100644
index 0000000..2b21bd0
--- /dev/null
+++ b/NET/worlds/scape/ObjectAdderDialog.java
@@ -0,0 +1,12 @@
+package NET.worlds.scape;
+
+class ObjectAdderDialog extends ObjectSelectorDialog {
+ ObjectAdderDialog(EditTile parent, String title, VectorProperty property, SuperRoot r, Class clas) {
+ super(parent, title, property, r, clas);
+ }
+
+ @Override
+ protected void addIt(Property p, Object obj) {
+ this.parent.addUndoableAdd((VectorProperty)p, obj, false);
+ }
+}
diff --git a/NET/worlds/scape/ObjectPropertyAdder.java b/NET/worlds/scape/ObjectPropertyAdder.java
new file mode 100644
index 0000000..3d9c13a
--- /dev/null
+++ b/NET/worlds/scape/ObjectPropertyAdder.java
@@ -0,0 +1,42 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.PolledDialog;
+
+public class ObjectPropertyAdder extends PropAdder {
+ SuperRoot root;
+ Class clas;
+
+ private ObjectPropertyAdder(VectorProperty property, SuperRoot r, Class clas) {
+ super(property);
+ this.root = r;
+ this.clas = clas;
+ }
+
+ @Override
+ public boolean hasAddDialog() {
+ return true;
+ }
+
+ @Override
+ public PolledDialog add(EditTile parent, String title) {
+ return new ObjectAdderDialog(parent, title, this.property, this.root, this.clas);
+ }
+
+ public static VectorProperty make(VectorProperty property, SuperRoot r, Class clas) {
+ return property.setAdder(new ObjectPropertyAdder(property, r, clas));
+ }
+
+ public static VectorProperty make(VectorProperty property, SuperRoot r, String clas) {
+ Class c = null;
+
+ try {
+ c = Class.forName(clas);
+ } catch (ClassNotFoundException var5) {
+ System.out.println("Couldn't find " + clas);
+
+ assert false;
+ }
+
+ return property.setAdder(new ObjectPropertyAdder(property, r, c));
+ }
+}
diff --git a/NET/worlds/scape/ObjectSelectorDialog.java b/NET/worlds/scape/ObjectSelectorDialog.java
new file mode 100644
index 0000000..f02a89e
--- /dev/null
+++ b/NET/worlds/scape/ObjectSelectorDialog.java
@@ -0,0 +1,91 @@
+package NET.worlds.scape;
+
+import NET.worlds.core.Std;
+import java.util.Enumeration;
+import java.util.Vector;
+
+abstract class ObjectSelectorDialog extends ListAdderDialog {
+ private Property property;
+ private Vector objectVector = null;
+ SuperRoot root = null;
+ Class clas = null;
+
+ ObjectSelectorDialog(EditTile parent, String title, Property property, SuperRoot r, Class clas) {
+ super(parent, title);
+ this.property = property;
+ this.root = r;
+ this.clas = clas;
+ this.ready();
+ }
+
+ private void quicksort(String[] objectList, int l, int r) {
+ if (r > l) {
+ String v = objectList[r];
+ int i = l - 1;
+ int j = r;
+
+ String tstr;
+ Object tobj;
+ do {
+ while (objectList[++i].compareTo(v) < 0) {
+ }
+
+ do {
+ j--;
+ } while (j > l && objectList[j].compareTo(v) > 0);
+
+ tstr = objectList[i];
+ objectList[i] = objectList[j];
+ objectList[j] = tstr;
+ tobj = this.objectVector.elementAt(i);
+ this.objectVector.setElementAt(this.objectVector.elementAt(j), i);
+ this.objectVector.setElementAt(tobj, j);
+ } while (j > i);
+
+ objectList[j] = objectList[i];
+ objectList[i] = objectList[r];
+ objectList[r] = tstr;
+ this.objectVector.setElementAt(this.objectVector.elementAt(i), j);
+ this.objectVector.setElementAt(this.objectVector.elementAt(r), i);
+ this.objectVector.setElementAt(tobj, r);
+ this.quicksort(objectList, l, i - 1);
+ this.quicksort(objectList, i + 1, r);
+ }
+ }
+
+ @Override
+ protected void build() {
+ this.objectVector = new Vector();
+ if (this.root != null) {
+ Enumeration e = this.root.getDeepOwned();
+
+ while (e.hasMoreElements()) {
+ Object obj = e.nextElement();
+ if (Std.instanceOf(obj, this.clas)) {
+ this.objectVector.addElement(obj);
+ }
+ }
+
+ String[] objectList = new String[this.objectVector.size()];
+
+ for (int i = 0; i < objectList.length; i++) {
+ objectList[i] = this.objectVector.elementAt(i).toString();
+ }
+
+ this.quicksort(objectList, 0, objectList.length - 1);
+ this.setListContents(objectList);
+ }
+
+ super.build();
+ }
+
+ protected abstract void addIt(Property var1, Object var2);
+
+ @Override
+ protected void add(int option) {
+ Object obj = this.objectVector.elementAt(option);
+ if (obj != null) {
+ this.addIt(this.property, obj);
+ }
+ }
+}
diff --git a/NET/worlds/scape/OpenURLAction.java b/NET/worlds/scape/OpenURLAction.java
new file mode 100644
index 0000000..16449f0
--- /dev/null
+++ b/NET/worlds/scape/OpenURLAction.java
@@ -0,0 +1,124 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.DefaultConsole;
+import NET.worlds.console.NoWebControlException;
+import NET.worlds.console.WebControl;
+import java.io.IOException;
+
+public class OpenURLAction extends Action {
+ String targetURL = "http://www.worlds.com";
+ int xPercent = 100;
+ int yPercent = 100;
+ boolean hasToolbar = true;
+ boolean isFixed = false;
+ private static Object classCookie = new Object();
+
+ @Override
+ public Persister trigger(Event e, Persister seqID) {
+ if (seqID != null) {
+ return seqID;
+ } else {
+ Console c = Console.getActive();
+ if (c != null && c instanceof DefaultConsole) {
+ System.out.println("Opening up a URL now.");
+ DefaultConsole dc = (DefaultConsole)c;
+
+ try {
+ WebControl wc = new WebControl(dc.getRender(), this.xPercent, this.yPercent, this.hasToolbar, this.isFixed, false);
+ wc.activate();
+ wc.setURL(this.targetURL);
+ } catch (NoWebControlException var6) {
+ }
+
+ new SuperRoot();
+ return this;
+ } else {
+ return null;
+ }
+ }
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Target URL"));
+ } else if (mode == 1) {
+ ret = this.targetURL;
+ } else if (mode == 2) {
+ this.targetURL = (String)value;
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = IntegerPropertyEditor.make(new Property(this, index, "X Overlay % or Width"), 0, 1024);
+ } else if (mode == 1) {
+ ret = new Integer(this.xPercent);
+ } else if (mode == 2) {
+ this.xPercent = (Integer)value;
+ }
+ break;
+ case 2:
+ if (mode == 0) {
+ ret = IntegerPropertyEditor.make(new Property(this, index, "Y Overlay % or Height"), 0, 1024);
+ } else if (mode == 1) {
+ ret = new Integer(this.yPercent);
+ } else if (mode == 2) {
+ this.yPercent = (Integer)value;
+ }
+ break;
+ case 3:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Has Toolbar"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(this.hasToolbar);
+ } else if (mode == 2) {
+ this.hasToolbar = (Boolean)value;
+ }
+ break;
+ case 4:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Fixed size"), "No - Percentage specified", "Yes - Pixels specified");
+ } else if (mode == 1) {
+ ret = new Boolean(this.isFixed);
+ } else if (mode == 2) {
+ this.isFixed = (Boolean)value;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 4, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(0, classCookie);
+ super.saveState(s);
+ s.saveString(this.targetURL);
+ s.saveInt(this.xPercent);
+ s.saveInt(this.yPercent);
+ s.saveBoolean(this.hasToolbar);
+ s.saveBoolean(this.isFixed);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ this.targetURL = r.restoreString();
+ this.xPercent = r.restoreInt();
+ this.yPercent = r.restoreInt();
+ this.hasToolbar = r.restoreBoolean();
+ this.isFixed = r.restoreBoolean();
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/ParallelAction.java b/NET/worlds/scape/ParallelAction.java
new file mode 100644
index 0000000..f2ece12
--- /dev/null
+++ b/NET/worlds/scape/ParallelAction.java
@@ -0,0 +1,140 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Vector;
+
+public class ParallelAction extends Action implements RunningActionCallback {
+ protected static final int NONE = 0;
+ protected static final int FIRST = 1;
+ protected static final int ALL = -1;
+ protected Vector actions = new Vector();
+ protected int waitState = -1;
+ protected int waitingFor = 0;
+ protected Object currentRun = null;
+ private static Object classCookie = new Object();
+
+ @Override
+ public Persister trigger(Event evt, Persister seqID) {
+ if (seqID == null) {
+ if (this.waitingFor == 0) {
+ this.currentRun = new Object();
+ if (this.waitState == -1) {
+ this.waitingFor = this.actions.size();
+ seqID = this;
+ } else if (this.waitState == 1) {
+ this.waitingFor = 1;
+ seqID = this;
+ } else {
+ this.waitingFor = 0;
+ seqID = null;
+ }
+
+ RunningActionHandler.trigger(this.actions, this.getWorld(), evt, this, this.currentRun);
+ }
+ } else if (this.waitingFor == 0) {
+ seqID = null;
+ }
+
+ return seqID;
+ }
+
+ @Override
+ public void actionDone(Action a, Event e, Object o) {
+ if (this.waitingFor > 0 && o == this.currentRun) {
+ this.waitingFor--;
+ }
+ }
+
+ public void setWaitForAll() {
+ this.waitState = -1;
+ }
+
+ public void setWaitForFirst() {
+ this.waitState = 1;
+ }
+
+ public void setWaitForNone() {
+ this.waitState = 0;
+ }
+
+ public void addComponent(Action act) {
+ assert act != null;
+
+ this.actions.addElement(act);
+ }
+
+ public void insertComponent(Action act, int index) {
+ assert act != null;
+
+ this.actions.insertElementAt(act, index);
+ }
+
+ public boolean removeComponent(Action act) {
+ assert act != null;
+
+ return this.actions.removeElement(act);
+ }
+
+ public Enumeration getComponents() {
+ return this.actions.elements();
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = ObjectPropertyAdder.make(new VectorProperty(this, index, "Components"), this.getRoot(), "NET.worlds.scape.Action");
+ } else if (mode == 1) {
+ ret = this.actions.clone();
+ } else if (mode == 4) {
+ this.actions.removeElement(value);
+ } else if (mode == 3) {
+ this.actions.addElement((Action)value);
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ String[] names = new String[]{"None", "First", "All"};
+ int[] values = new int[]{0, 1, -1};
+ ret = EnumPropertyEditor.make(new Property(this, index, "Wait for"), names, values);
+ } else if (mode == 1) {
+ ret = new Integer(this.waitState);
+ } else if (mode == 2) {
+ this.waitState = (Integer)value;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 2, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(2, classCookie);
+ super.saveState(s);
+ s.saveVector(this.actions);
+ s.saveInt(this.waitState);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 1:
+ super.restoreState(r);
+ this.actions = r.restoreVector();
+ break;
+ case 2:
+ super.restoreState(r);
+ this.actions = r.restoreVector();
+ this.waitState = r.restoreInt();
+ break;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/PassthroughBumpCalc.java b/NET/worlds/scape/PassthroughBumpCalc.java
new file mode 100644
index 0000000..9490684
--- /dev/null
+++ b/NET/worlds/scape/PassthroughBumpCalc.java
@@ -0,0 +1,33 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+public class PassthroughBumpCalc extends BumpCalc {
+ private static Object classCookie = new Object();
+
+ @Override
+ public void detectBump(BumpEventTemp b, WObject owner) {
+ Transform xfrm = owner.getObjectToWorldMatrix();
+ Point3Temp start = xfrm.getPosition();
+ Point3Temp d = owner.getPlaneExtent().vectorTimes(xfrm);
+ xfrm.recycle();
+ b.hitPlane(owner, start, d);
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(0, classCookie);
+ super.saveState(s);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/PasteWidget.java b/NET/worlds/scape/PasteWidget.java
new file mode 100644
index 0000000..a1b89b8
--- /dev/null
+++ b/NET/worlds/scape/PasteWidget.java
@@ -0,0 +1,14 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+
+class PasteWidget extends ClickWidget {
+ public PasteWidget(ToolBar toolbar) {
+ super(toolbar, "paste.gif", Console.message("Paste"));
+ }
+
+ @Override
+ public void perform() {
+ Console.getFrame().getEditTile().paste();
+ }
+}
diff --git a/NET/worlds/scape/PathMoveAction.java b/NET/worlds/scape/PathMoveAction.java
new file mode 100644
index 0000000..39645e2
--- /dev/null
+++ b/NET/worlds/scape/PathMoveAction.java
@@ -0,0 +1,24 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+public class PathMoveAction extends Action {
+ private static Object classCookie = new Object();
+
+ @Override
+ public Persister trigger(Event e, Persister seqID) {
+ return null;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ assert false;
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ MoveAction a = new MoveAction();
+ r.replace(this, a);
+ a.restoreStateMoveActionHelper(r, classCookie);
+ }
+}
diff --git a/NET/worlds/scape/PendingCacheDrone.java b/NET/worlds/scape/PendingCacheDrone.java
new file mode 100644
index 0000000..550b8ef
--- /dev/null
+++ b/NET/worlds/scape/PendingCacheDrone.java
@@ -0,0 +1,66 @@
+package NET.worlds.scape;
+
+import NET.worlds.core.IniFile;
+import NET.worlds.network.Cache;
+import NET.worlds.network.CacheFile;
+import NET.worlds.network.NetUpdate;
+import NET.worlds.network.URL;
+
+public class PendingCacheDrone extends PendingDrone {
+ static String upgradeDir = IniFile.gamma().getIniString("avatarDir", "avatar/");
+
+ static {
+ if (!upgradeDir.endsWith("/")) {
+ upgradeDir = upgradeDir + "/";
+ }
+
+ nativeInit();
+ }
+
+ public PendingCacheDrone(PosableDrone _drone, URL _url) {
+ super(_drone, _url);
+ }
+
+ @Override
+ public synchronized void download(URL avURL) {
+ }
+
+ public static native void nativeInit();
+
+ public static native void nativeDestroy();
+
+ public static synchronized native void notifySeqLoaded(int var0, String var1);
+
+ public static void downloadSeqFile(String seqFileName, boolean force, int nativeNotifyObject) {
+ seqFileName = seqFileName.toLowerCase();
+ if (!PosableDroneLoader.usingCache()) {
+ notifySeqLoaded(nativeNotifyObject, ".\\avatars\\" + seqFileName);
+ } else {
+ String path = NetUpdate.getUpgradeServerURL() + upgradeDir + seqFileName;
+ if (force) {
+ CacheFile cf = Cache.getFile(URL.make(path));
+ cf.waitUntilLoaded();
+ if (cf.error()) {
+ return;
+ }
+
+ notifySeqLoaded(nativeNotifyObject, cf.getLocalName());
+ } else {
+ new SeqFile(nativeNotifyObject, URL.make(path));
+ }
+ }
+ }
+
+ public static String getAvatarDatPath() {
+ if (!PosableDroneLoader.usingCache()) {
+ return ".\\avatars\\avatars.dat";
+ } else if (IniFile.gamma().getIniInt("localavatarsdat", 0) == 1) {
+ return ".\\avatars\\avatars.dat";
+ } else {
+ String datURL = NetUpdate.getUpgradeServerURL() + upgradeDir + "avatars.dat";
+ CacheFile cf = Cache.getFile(URL.make(datURL));
+ cf.waitUntilLoaded();
+ return cf.error() ? null : cf.getLocalName();
+ }
+ }
+}
diff --git a/NET/worlds/scape/PendingDrone.java b/NET/worlds/scape/PendingDrone.java
new file mode 100644
index 0000000..105851f
--- /dev/null
+++ b/NET/worlds/scape/PendingDrone.java
@@ -0,0 +1,303 @@
+package NET.worlds.scape;
+
+import NET.worlds.core.Archive;
+import NET.worlds.core.IniFile;
+import NET.worlds.network.Cache;
+import NET.worlds.network.CacheFile;
+import NET.worlds.network.NetUpdate;
+import NET.worlds.network.URL;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.util.Enumeration;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import java.util.zip.ZipOutputStream;
+
+public class PendingDrone {
+ static boolean doAvatarUpdates = true;
+ protected PosableDrone drone;
+ protected URL url;
+ protected boolean loaded;
+ static final boolean debug = false;
+
+ static {
+ doAvatarUpdates = IniFile.gamma().getIniInt("noAvUpdates", 0) == 0;
+ }
+
+ PendingDrone(PosableDrone _drone, URL _url) {
+ this.drone = _drone;
+ this.url = _url;
+ this.loaded = false;
+ }
+
+ public PosableDrone getDrone() {
+ return this.drone;
+ }
+
+ public URL getUrl() {
+ return this.url;
+ }
+
+ public boolean getLoaded() {
+ return this.loaded;
+ }
+
+ public void setLoaded() {
+ this.loaded = true;
+ }
+
+ public synchronized void download(URL avURL) {
+ if (doAvatarUpdates) {
+ if (avURL != null) {
+ try {
+ if (PosableDroneLoader.avatarExistsLocally(avURL)) {
+ return;
+ }
+ } catch (MalformedURLException var5) {
+ return;
+ }
+
+ String s = PosableDroneLoader.getAvatarBaseName(avURL);
+
+ assert s != null;
+
+ s = s.toLowerCase();
+ URL realFile = URL.make(NetUpdate.getUpgradeServerURL() + "AvatarUpgrades/" + s + ".zip");
+ CacheFile cf = Cache.getFile(realFile);
+ cf.waitUntilLoaded();
+ if (!cf.error()) {
+ this.finishDownload(cf.getLocalName());
+ cf.close();
+ }
+ }
+ }
+ }
+
+ public synchronized boolean finishDownload(String localName) {
+ ZipFile patchArchive;
+ try {
+ patchArchive = new ZipFile(localName);
+ } catch (IOException var11) {
+ this.notify();
+ return false;
+ }
+
+ Enumeration enums = patchArchive.entries();
+
+ while (enums.hasMoreElements()) {
+ ZipEntry ze = (ZipEntry)enums.nextElement();
+ String filename = ze.getName();
+ String avatarFile = URL.homeUnalias("avatars/" + filename);
+ String[] validExtensions = new String[]{".bod", ".seq", ".dat", ".cmp", ".mov"};
+ boolean validFile = false;
+
+ for (int idx = 0; idx < validExtensions.length; idx++) {
+ if (avatarFile.toString().endsWith(validExtensions[idx])) {
+ validFile = true;
+ break;
+ }
+ }
+
+ if (validFile) {
+ if (avatarFile.toString().endsWith("avatars.dat")) {
+ avatarFile = URL.homeUnalias("avatars/avatars.tmp");
+ this.CopyAvatarFile(patchArchive, ze, avatarFile);
+ this.AppendAvatarsDat();
+ } else {
+ this.CopyAvatarFile(patchArchive, ze, avatarFile);
+ }
+ }
+ }
+
+ try {
+ patchArchive.close();
+ } catch (IOException var10) {
+ }
+
+ this.notify();
+ return false;
+ }
+
+ public Room getBackgroundLoadRoom() {
+ return this.drone != null && this.drone.getOwner() != null ? this.drone.getOwner().getRoom() : null;
+ }
+
+ private void AppendAvatarsDat() {
+ String contentZip = URL.homeUnalias("avatars/content.zip");
+ Archive.flushAll();
+
+ ZipFile contentZipArchive;
+ try {
+ contentZipArchive = new ZipFile(contentZip);
+ } catch (IOException var12) {
+ contentZipArchive = null;
+ }
+
+ if (contentZipArchive != null) {
+ ZipEntry origAvatarDat = contentZipArchive.getEntry("avatars.dat");
+ if (origAvatarDat != null) {
+ this.CopyAvatarFile(contentZipArchive, origAvatarDat, URL.homeUnalias("avatars/avatars.dat"));
+ this.StripAvatarDat(contentZipArchive);
+ } else {
+ try {
+ contentZipArchive.close();
+ } catch (IOException var11) {
+ }
+ }
+ }
+
+ FileOutputStream avDat;
+ try {
+ avDat = new FileOutputStream(URL.homeUnalias("avatars/avatars.dat"), true);
+ } catch (IOException var10) {
+ System.out.println(var10);
+ return;
+ }
+
+ FileInputStream avTmp;
+ try {
+ avTmp = new FileInputStream(URL.homeUnalias("avatars/avatars.tmp"));
+ } catch (FileNotFoundException var9) {
+ try {
+ avDat.close();
+ } catch (IOException var7) {
+ }
+
+ return;
+ }
+
+ byte[] buf = new byte[1024];
+
+ while (true) {
+ try {
+ int bytesRead = avTmp.read(buf);
+ if (bytesRead == -1) {
+ break;
+ }
+
+ avDat.write(buf, 0, bytesRead);
+ } catch (IOException var13) {
+ break;
+ }
+ }
+
+ try {
+ avDat.close();
+ avTmp.close();
+ } catch (IOException var8) {
+ }
+
+ File avTmpFile = new File(URL.homeUnalias("avatars/avatars.tmp"));
+ avTmpFile.delete();
+ DroneAnimator.loadconfig(URL.make("home:avatars/avatars.dat").unalias());
+ }
+
+ private void StripAvatarDat(ZipFile contentZipArchive) {
+ FileOutputStream os;
+ try {
+ os = new FileOutputStream(URL.homeUnalias("avatars/content.tmp"));
+ } catch (IOException var13) {
+ return;
+ }
+
+ ZipOutputStream zs = new ZipOutputStream(os);
+ Enumeration enums = contentZipArchive.entries();
+
+ while (enums.hasMoreElements()) {
+ ZipEntry ze = (ZipEntry)enums.nextElement();
+ String filename = ze.getName();
+ if (!filename.equals("avatars.dat")) {
+ try {
+ InputStream is = contentZipArchive.getInputStream(ze);
+ ZipEntry ze2 = new ZipEntry(ze.getName());
+ zs.putNextEntry(ze2);
+ byte[] buffer = new byte[1024];
+
+ while (true) {
+ try {
+ int bytesRead = is.read(buffer);
+ if (bytesRead != -1) {
+ zs.write(buffer, 0, bytesRead);
+ continue;
+ }
+ } catch (IOException var14) {
+ System.out.println("IOException " + ze.getName() + " " + var14.getMessage());
+ }
+
+ zs.closeEntry();
+ is.close();
+ break;
+ }
+ } catch (IOException var15) {
+ System.out.println("IOException 2 " + var15.getMessage());
+ }
+ }
+ }
+
+ try {
+ contentZipArchive.close();
+ zs.close();
+ } catch (IOException var12) {
+ System.out.println("Error closing zip files " + var12);
+ }
+
+ File origFile = new File(URL.homeUnalias("avatars/content.zip"));
+ File newFile = new File(URL.homeUnalias("avatars/content.tmp"));
+ File oldFile = new File(URL.homeUnalias("avatars/content.old"));
+ Archive.flushAll();
+
+ try {
+ boolean b = origFile.renameTo(oldFile);
+ b = newFile.renameTo(origFile);
+ } catch (Exception var11) {
+ System.out.println(var11);
+ }
+ }
+
+ private void CopyAvatarFile(ZipFile patchArchive, ZipEntry ze, String avatarFile) {
+ InputStream is;
+ try {
+ is = patchArchive.getInputStream(ze);
+ } catch (IOException var11) {
+ return;
+ }
+
+ FileOutputStream os;
+ try {
+ os = new FileOutputStream(avatarFile);
+ } catch (IOException var10) {
+ try {
+ is.close();
+ } catch (IOException var8) {
+ }
+
+ return;
+ }
+
+ byte[] buffer = new byte[1024];
+
+ while (true) {
+ try {
+ int bytesRead = is.read(buffer);
+ if (bytesRead == -1) {
+ break;
+ }
+
+ os.write(buffer, 0, bytesRead);
+ } catch (IOException var12) {
+ break;
+ }
+ }
+
+ try {
+ is.close();
+ os.close();
+ } catch (IOException var9) {
+ }
+ }
+}
diff --git a/NET/worlds/scape/PeriodicTimeSensor.java b/NET/worlds/scape/PeriodicTimeSensor.java
new file mode 100644
index 0000000..d76e431
--- /dev/null
+++ b/NET/worlds/scape/PeriodicTimeSensor.java
@@ -0,0 +1,80 @@
+package NET.worlds.scape;
+
+import NET.worlds.core.Std;
+import java.io.IOException;
+
+public class PeriodicTimeSensor extends Sensor implements FrameHandler {
+ private float timeInterval = 1.0F;
+ private long lastTrigger;
+ private static Object classCookie = new Object();
+
+ public PeriodicTimeSensor(Action act) {
+ if (act != null) {
+ this.addAction(act);
+ }
+ }
+
+ public PeriodicTimeSensor() {
+ }
+
+ @Override
+ public boolean handle(FrameEvent e) {
+ long now = 0L;
+ if (e == null) {
+ now = Std.getFastTime();
+ } else {
+ now = e.time;
+ }
+
+ if (now - this.lastTrigger > (long)(1000.0F * this.timeInterval)) {
+ this.lastTrigger = now;
+ this.trigger(e);
+ }
+
+ return true;
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Time Interval (s)"));
+ } else if (mode == 1) {
+ ret = new Float(this.timeInterval);
+ } else if (mode == 2) {
+ this.timeInterval = (Float)value;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 1, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(1, classCookie);
+ super.saveState(s);
+ s.saveFloat(this.timeInterval);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 1:
+ super.restoreState(r);
+ this.timeInterval = r.restoreFloat();
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "*every " + this.timeInterval + " s";
+ }
+}
diff --git a/NET/worlds/scape/Persister.java b/NET/worlds/scape/Persister.java
new file mode 100644
index 0000000..31a45c4
--- /dev/null
+++ b/NET/worlds/scape/Persister.java
@@ -0,0 +1,11 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+public interface Persister {
+ void saveState(Saver var1) throws IOException;
+
+ void restoreState(Restorer var1) throws IOException, TooNewException;
+
+ void postRestore(int var1);
+}
diff --git a/NET/worlds/scape/PickEvent.java b/NET/worlds/scape/PickEvent.java
new file mode 100644
index 0000000..342879b
--- /dev/null
+++ b/NET/worlds/scape/PickEvent.java
@@ -0,0 +1,19 @@
+package NET.worlds.scape;
+
+public class PickEvent extends UserEvent {
+ public float x;
+ public float y;
+ public float z;
+
+ public PickEvent(int time, WObject target, float _x, float _y, float _z) {
+ super(time, null, target);
+ this.x = _x;
+ this.y = _y;
+ this.z = _z;
+ }
+
+ @Override
+ public boolean deliver(Object o) {
+ return o instanceof PickHandler && ((PickHandler)o).handle(this) ? true : super.deliver(o);
+ }
+}
diff --git a/NET/worlds/scape/PickHandler.java b/NET/worlds/scape/PickHandler.java
new file mode 100644
index 0000000..14a97b0
--- /dev/null
+++ b/NET/worlds/scape/PickHandler.java
@@ -0,0 +1,5 @@
+package NET.worlds.scape;
+
+public interface PickHandler {
+ boolean handle(PickEvent var1);
+}
diff --git a/NET/worlds/scape/PickUpAction.java b/NET/worlds/scape/PickUpAction.java
new file mode 100644
index 0000000..bd4b5cb
--- /dev/null
+++ b/NET/worlds/scape/PickUpAction.java
@@ -0,0 +1,33 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+public class PickUpAction extends Action {
+ private static Object classCookie = new Object();
+
+ @Override
+ public Persister trigger(Event arg, Persister seqID) {
+ WObject w = (WObject)this.getOwner();
+ w.detach();
+ w.raise(-Pilot.getActive().getZ());
+ Pilot.getActive().add(w);
+ return null;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(0, classCookie);
+ super.saveState(s);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/Pilot.java b/NET/worlds/scape/Pilot.java
new file mode 100644
index 0000000..6e60dc7
--- /dev/null
+++ b/NET/worlds/scape/Pilot.java
@@ -0,0 +1,853 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.AdPart;
+import NET.worlds.console.BBAnimateDroneCommand;
+import NET.worlds.console.BBMoveDroneCommand;
+import NET.worlds.console.BBTeleportCommand;
+import NET.worlds.console.BlackBox;
+import NET.worlds.console.Console;
+import NET.worlds.console.FramePart;
+import NET.worlds.console.RenderCanvas;
+import NET.worlds.core.Std;
+import NET.worlds.network.Galaxy;
+import NET.worlds.network.InfiniteWaitException;
+import NET.worlds.network.NetworkObject;
+import NET.worlds.network.OldPropertyList;
+import NET.worlds.network.PacketTooLargeException;
+import NET.worlds.network.PropertyList;
+import NET.worlds.network.PropertySetCmd;
+import NET.worlds.network.URL;
+import NET.worlds.network.WorldServer;
+import NET.worlds.network.longLocCmd;
+import NET.worlds.network.net2Property;
+import NET.worlds.network.netPacket;
+import NET.worlds.network.roomChangeCmd;
+import NET.worlds.network.teleportCmd;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Vector;
+
+public abstract class Pilot extends WObject implements NetworkObject, BumpHandler {
+ static Vector<Room> visibleRooms = new Vector<Room>();
+ static Vector<RoomSubscribeInfo> visibleRoomInfo = new Vector<RoomSubscribeInfo>();
+ int lastUpdateTime;
+ private static Vector<Room> nextVisibleRooms = new Vector<Room>();
+ private static Vector<RoomSubscribeInfo> nextVisibleRoomInfo = new Vector<RoomSubscribeInfo>();
+ int positionSentTime;
+ short lastx;
+ short lasty;
+ short lastz;
+ short lastdir;
+ Room lastroom;
+ Room lastFrameRoom;
+ private static Vector<Room> subscribers = new Vector<Room>();
+ private static int lastWarning;
+ private static Pilot active;
+ protected int cameraMode = 0;
+ protected int cameraSpeed = 0;
+ private static World lastWorld = null;
+ private Camera lastCam;
+ protected Console console;
+ private static Object classCookie = new Object();
+
+ static {
+ nativeInit();
+ }
+
+ public static native void nativeInit();
+
+ public float animate(String action) {
+ action = action.toLowerCase();
+ BlackBox.getInstance().submitEvent(new BBAnimateDroneCommand("@Pilot", action));
+ if (action.equals("sleep") || action.equals("s")) {
+ Console console = Console.getActive();
+ if (console != null) {
+ console.goToSleep();
+ }
+ } else if (this == getActive()) {
+ sendText("&|+action>" + action);
+ }
+
+ return 0.0F;
+ }
+
+ public Vector<String> getAnimationList() {
+ Vector<String> v = new Vector<String>();
+ v.addElement("sleep");
+ return v;
+ }
+
+ public void setSleepMode(String mode) {
+ }
+
+ public static void load(URL url, WobLoaded callback) {
+ if (!url.endsWith(".mov") && !url.endsWith(".rwx") && !url.endsWith(".rwg")) {
+ String s = url.getInternal();
+ if (s.endsWith(".drone")) {
+ s = s.substring(0, s.length() - 6) + ".pilot";
+ } else if (!s.endsWith(".pilot")) {
+ s = s + ".pilot";
+ }
+
+ new WobLoader(URL.make(s), callback);
+ } else {
+ callback.wobLoaded(null, new HoloPilot(url));
+ }
+ }
+
+ public void addInventory(WObject child) throws ClassCastException {
+ assert child.isDynamic();
+
+ this.add(child);
+ }
+
+ public void addInSlot(WObject child, int slot) {
+ assert child.isDynamic();
+
+ Sharer s = this.getSharer();
+ if (s.getAttribute(slot) != null) {
+ System.out.println("Attempting to add a second object (" + child.getName() + ") to slot number " + slot);
+ } else {
+ s.moveToSlot(child, slot);
+ }
+ }
+
+ @Override
+ public void add(WObject w) {
+ super.add(w);
+ }
+
+ public float distToVisibleObject(WObject w) {
+ return this.distToVisiblePoint(w.getRoom(), w.getWorldPosition());
+ }
+
+ public void aboutToDraw() {
+ }
+
+ public float distToVisiblePoint(Room r, Point3Temp pos) {
+ if (r == null) {
+ return 0.0F;
+ } else {
+ int i = visibleRooms.indexOf(r);
+ if (i == -1) {
+ return 0.0F;
+ } else {
+ RoomSubscribeInfo rsi = visibleRoomInfo.elementAt(i);
+ return rsi.d == 0.0F ? pos.minus(this.getWorldPosition()).length() : pos.minus(Point3Temp.make(rsi.x, rsi.y, rsi.z)).length() + rsi.d;
+ }
+ }
+ }
+
+ public static void addVisibleRoom(Room r, float x, float y, float z, float d) {
+ r.noteRef();
+ int i = nextVisibleRooms.indexOf(r);
+ if (i == -1) {
+ nextVisibleRooms.addElement(r);
+ nextVisibleRoomInfo.addElement(new RoomSubscribeInfo(x, y, z, d));
+ } else {
+ RoomSubscribeInfo info = nextVisibleRoomInfo.elementAt(i);
+ if (d < info.d) {
+ info.x = x;
+ info.y = y;
+ info.z = z;
+ info.d = d;
+ }
+ }
+ }
+
+ public void generateFrameEvents(FrameEvent f) {
+ Room currentRoom = this.getRoom();
+ if (currentRoom != null) {
+ addVisibleRoom(currentRoom, 0.0F, 0.0F, 0.0F, 0.0F);
+ }
+
+ synchronized (visibleRooms) {
+ Vector<RoomSubscribeInfo> t = visibleRoomInfo;
+ visibleRoomInfo = nextVisibleRoomInfo;
+ nextVisibleRoomInfo = t;
+ Vector<Room> j = nextVisibleRooms;
+ nextVisibleRooms = visibleRooms;
+ visibleRooms = j;
+ }
+
+ Vector<Room> prevVisibleRooms = nextVisibleRooms;
+ Object oldEventSource = f.source;
+ f.source = this;
+ int i = visibleRooms.size();
+
+ while (--i >= 0) {
+ Room r = visibleRooms.elementAt(i);
+ r.generateFrameEvents(f);
+ prevVisibleRooms.removeElement(r);
+ }
+
+ i = prevVisibleRooms.size();
+
+ while (--i >= 0) {
+ prevVisibleRooms.elementAt(i).generateFrameEvents(f);
+ }
+
+ nextVisibleRooms.removeAllElements();
+ nextVisibleRoomInfo.removeAllElements();
+ i = f.time - this.lastUpdateTime;
+ if (i > 500) {
+ this.subscribeRooms();
+ boolean hasMoved = this.pilotUpdate(f.time);
+ this.subscriptionUpdate(hasMoved);
+ this.updateUnsubscribes();
+ this.lastUpdateTime = f.time;
+ }
+
+ this.touchSubscribers();
+ f.source = oldEventSource;
+ }
+
+ public static void sendText(String msg) {
+ sendText(null, msg);
+ }
+
+ public static boolean containsWord(String word, String msg) {
+ int i = -1;
+
+ while ((i = msg.indexOf(word, i + 1)) >= 0) {
+ if (i == 0 || !Character.isLetter(msg.charAt(i - 1))) {
+ int end = i + word.length();
+ if (end >= msg.length() || !Character.isLetter(msg.charAt(end))) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ public static void sendText(String who, String msg) {
+ WorldServer server = active.getServer();
+ if (server != null) {
+ if (msg.contains("&|+action>")) {
+ PropertyList propList = new PropertyList();
+ String strUrl = getActive().getSourceURL().getAbsolute();
+ strUrl = strUrl + "#" + msg.substring(msg.indexOf(">") + 1, msg.length());
+ propList.addProperty(new net2Property(5, 64, 1, strUrl));
+
+ try {
+ server.sendNetworkMsg(new PropertySetCmd(propList));
+ } catch (PacketTooLargeException var7) {
+ } catch (InfiniteWaitException var8) {
+ }
+ }
+
+ server.sendText(who, msg);
+ if ((containsWord("brb", msg) || containsWord("ggp", msg)) && Console.getActive() != null) {
+ Console.getActive().goToSleep();
+ }
+
+ int i = msg.indexOf(42);
+
+ int next;
+ while (i >= 0 && (next = msg.indexOf(42, i + 1)) > i) {
+ int space = msg.indexOf(32, i);
+ if (next > i + 1 && (space == -1 || space > next)) {
+ String act = msg.substring(i + 1, next).toLowerCase();
+ if (who == null && active != null) {
+ active.animate(act);
+ } else {
+ sendText(who, "&|+action>" + act);
+ }
+ }
+
+ i = next;
+ }
+ } else if (!msg.startsWith("&|+")) {
+ Console.println(Console.message("No-server-connect"));
+ }
+ }
+
+ private static float round(float x, float mul) {
+ return mul * Math.round(x / mul);
+ }
+
+ public String getWorldRoomChannel(Room room) {
+ if (room == null) {
+ return null;
+ } else {
+ World world = room.getWorld();
+ if (world == null) {
+ return null;
+ } else {
+ URL url = world.getSourceURL();
+ if (url == null) {
+ return null;
+ } else {
+ String newURL = url.getAbsolute();
+ Galaxy g = room.getGalaxy();
+ String channelPart = g.getChannel();
+ return newURL + "#" + room.getName() + "<" + channelPart + ">";
+ }
+ }
+ }
+ }
+
+ public String getURL() {
+ Room room = this.getRoom();
+ String newURL = this.getWorldRoomChannel(room);
+ if (newURL == null) {
+ return null;
+ } else {
+ Point3Temp pos = this.getPosition();
+ float val = round(pos.x, 1.0F);
+ newURL = newURL + "@" + val;
+ val = round(pos.y, 1.0F);
+ newURL = newURL + "," + val;
+ val = round(pos.z, 1.0F);
+ newURL = newURL + "," + val;
+ Point3Temp camAxis = Point3Temp.make();
+ val = round(this.getSpin(camAxis), 1.0F);
+ newURL = newURL + "," + val;
+ val = round(camAxis.x, 0.001F);
+ newURL = newURL + "," + val;
+ val = round(camAxis.y, 0.001F);
+ newURL = newURL + "," + val;
+ val = round(camAxis.z, 0.001F);
+ return newURL + "," + val;
+ }
+ }
+
+ public String getTeleportURL() {
+ Camera tester = new Camera();
+ Room room = this.getRoom();
+ if (room == null) {
+ return null;
+ } else {
+ room.add(tester);
+ tester.yaw(220.0F);
+ tester.post(this);
+ boolean pBumpable = this.getBumpable();
+ this.setBumpable(false);
+ Transform t = tester.getObjectToWorldMatrix();
+ tester.moveThrough(Point3Temp.make(0.0F, -170.0F, 0.0F).times(t).minus(t.getPosition()));
+ t.recycle();
+ this.setBumpable(pBumpable);
+ room = tester.getRoom();
+ tester.detach();
+ String wrc = this.getWorldRoomChannel(room);
+ if (wrc == null) {
+ return null;
+ } else {
+ Point3Temp pos = tester.getPosition();
+ return wrc + "@" + (int)pos.x + "," + (int)pos.y + "," + (int)pos.z + "," + (int)tester.getYaw();
+ }
+ }
+ }
+
+ public Room getLastServedRoom() {
+ return this.lastroom;
+ }
+
+ public float getFootHeight() {
+ return 0.0F;
+ }
+
+ private static void sendToRoom(Room r, netPacket msg) {
+ if (r != null) {
+ synchronized (r) {
+ WorldServer s = r.getServer();
+ if (s != null) {
+ try {
+ s.sendNetworkMsg(msg);
+ } catch (InfiniteWaitException var5) {
+ } catch (PacketTooLargeException var6) {
+ }
+ }
+ }
+ }
+ }
+
+ private boolean validRoom(Room r) {
+ return r == null || r.getNetworkRoom().getRoomID() != 0;
+ }
+
+ public boolean pilotUpdate(int t) {
+ Point3Temp pos = this.getPosition();
+ short x = (short)pos.x;
+ short y = (short)pos.y;
+ short z = (short)this.getFootHeight();
+ short dir = (short)(-this.getYaw() + 90.0F);
+ dir = (short)(dir % 360);
+
+ while (dir < 0) {
+ dir = (short)(dir + 360);
+ }
+
+ Room room = this.getRoom();
+ if (room != this.lastFrameRoom) {
+ BlackBox.getInstance().submitEvent(new BBTeleportCommand(this.getURL()));
+ this.lastFrameRoom = this.getRoom();
+ }
+
+ if (room != null && !room.getNetworkRoom().isServed()) {
+ room = null;
+ }
+
+ if (this.lastroom != null && !this.lastroom.getNetworkRoom().isServed()) {
+ this.lastroom = null;
+ }
+
+ int diffTime = t - this.positionSentTime;
+ if (x == this.lastx && y == this.lasty && z == this.lastz && dir == this.lastdir && diffTime <= 40000 && room == this.lastroom) {
+ return false;
+ } else {
+ BlackBox.getInstance().submitEvent(new BBMoveDroneCommand("@Pilot", x, y, z, dir));
+ if (room != this.lastroom && this.validRoom(room) && this.validRoom(this.lastroom)) {
+ Galaxy lrGalaxy = null;
+ Galaxy rGalaxy = null;
+ if (room != null) {
+ rGalaxy = room.getGalaxy();
+ }
+
+ if (this.lastroom != null) {
+ lrGalaxy = this.lastroom.getGalaxy();
+ }
+
+ if (rGalaxy != lrGalaxy) {
+ if (room != null) {
+ sendToRoom(room, new teleportCmd(room, (byte)0, (byte)1, x, y, z, dir));
+ BlackBox.getInstance().submitEvent(new BBTeleportCommand(this.getURL()));
+ }
+
+ if (this.lastroom != null) {
+ sendToRoom(this.lastroom, new teleportCmd(null, (byte)1, (byte)0, x, y, z, dir));
+ }
+
+ BlackBox.getInstance().submitEvent(new BBTeleportCommand(this.getURL()));
+ } else if (room.getServer() != this.lastroom.getServer()) {
+ if (room != null) {
+ sendToRoom(room, new teleportCmd(room, (byte)0, (byte)1, x, y, z, dir));
+ BlackBox.getInstance().submitEvent(new BBTeleportCommand(this.getURL()));
+ }
+
+ if (this.lastroom != null) {
+ sendToRoom(this.lastroom, new teleportCmd(null, (byte)1, (byte)0, x, y, z, dir));
+ }
+ } else {
+ sendToRoom(this.lastroom, new roomChangeCmd(room, x, y, z, dir));
+ BlackBox.getInstance().submitEvent(new BBTeleportCommand(this.getURL()));
+ }
+
+ this.lastroom = room;
+ } else if (room != null) {
+ sendToRoom(room, new longLocCmd(x, y, z, dir));
+ }
+
+ this.positionSentTime = t;
+ this.lastx = x;
+ this.lasty = y;
+ this.lastz = z;
+ this.lastdir = dir;
+ return true;
+ }
+ }
+
+ private void updateUnsubscribes() {
+ int i = subscribers.size();
+
+ while (--i >= 0) {
+ if (!visibleRooms.contains(subscribers.elementAt(i))) {
+ subscribers.elementAt(i).unsubscribe();
+ subscribers.removeElementAt(i);
+ }
+ }
+ }
+
+ public void subscribeRooms() {
+ int i = visibleRooms.size();
+
+ while (--i >= 0) {
+ Room r = visibleRooms.elementAt(i);
+ if (!subscribers.contains(r)) {
+ RoomSubscribeInfo newInfo = visibleRoomInfo.elementAt(i);
+ r.subscribe(newInfo);
+ }
+ }
+ }
+
+ public boolean removeSubscribedRoom(Room suspect) {
+ int i = subscribers.size();
+
+ while (--i >= 0) {
+ if (subscribers.elementAt(i) == suspect) {
+ subscribers.removeElementAt(i);
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public void touchSubscribers() {
+ int i = subscribers.size();
+
+ while (--i >= 0) {
+ subscribers.elementAt(i).noteRef();
+ }
+ }
+
+ private void subscriptionUpdate(boolean hasMoved) {
+ Room camRoom = this.getRoom();
+ int i = visibleRooms.size();
+
+ while (--i >= 0) {
+ Room r = visibleRooms.elementAt(i);
+
+ assert r.getNetworkRoom() != null;
+
+ RoomSubscribeInfo newInfo = visibleRoomInfo.elementAt(i);
+ if (!subscribers.contains(r)) {
+ subscribers.addElement(r);
+ } else if (hasMoved && r.getNetworkRoom().isServed() && r != camRoom) {
+ r.subscribeDist(newInfo);
+ }
+ }
+ }
+
+ @Override
+ public void property(OldPropertyList propList) {
+ }
+
+ @Override
+ public void propertyUpdate(PropertyList propList) {
+ }
+
+ @Override
+ public void register() {
+ }
+
+ @Override
+ public void galaxyDisconnected() {
+ }
+
+ @Override
+ public void reacquireServer(WorldServer oldServ) {
+ }
+
+ @Override
+ public void changeChannel(Galaxy g, String oldChannel, String newChannel) {
+ sendToRoom(this.lastroom, new teleportCmd(null, (byte)1, (byte)0, this.lastx, this.lasty, this.lastz, this.lastdir));
+ BlackBox.getInstance().submitEvent(new BBTeleportCommand(this.getURL()));
+ this.lastroom = null;
+ }
+
+ @Override
+ public WorldServer getServer() {
+ Room r = this.getLastServedRoom();
+ if (r != null) {
+ return r.getServer();
+ } else {
+ return this.console == null ? null : this.console.getServerNew();
+ }
+ }
+
+ @Override
+ public String getLongID() {
+ return this.console != null ? this.console.getGalaxy().getChatname() : null;
+ }
+
+ @Override
+ public WObject changeRoom(Room newRoom, Transform invPos) {
+ assert this == active;
+
+ if (newRoom.getVIPOnly() && !newRoom.getWorld().getConsole().getVIP()) {
+ int now = Std.getFastTime();
+ if (now > lastWarning + 3000) {
+ lastWarning = now;
+ Console.println(Console.message("Only-VIPs-here"));
+ }
+
+ return null;
+ } else {
+ Room oldRoom = getActiveRoom();
+ if (oldRoom != null) {
+ oldRoom.removePostrenderHandler(BlackBox.getInstance());
+ oldRoom.removeFrameHandler(BlackBox.getInstance(), null);
+ }
+
+ WObject p = changeActiveRoom(newRoom);
+ p.makeIdentity();
+ p.pre(invPos);
+ if (oldRoom != null) {
+ oldRoom.move(oldRoom, newRoom);
+ }
+
+ if (newRoom != null) {
+ newRoom.move(oldRoom, newRoom);
+ }
+
+ return p;
+ }
+ }
+
+ public static Pilot getActive() {
+ return active;
+ }
+
+ public void setOutsideCameraMode(int camMode, int camSpeed) {
+ this.cameraMode = camMode;
+ this.cameraSpeed = camSpeed;
+ if (this.getMainCamera() != null) {
+ this.getMainCamera().lookAround.makeIdentity();
+ }
+ }
+
+ public int getOutsideCameraMode() {
+ return this.cameraMode;
+ }
+
+ public int getOutsideCameraSpeed() {
+ return this.cameraSpeed;
+ }
+
+ public static Room getActiveRoom() {
+ return active == null ? null : active.getRoom();
+ }
+
+ public static World getActiveWorld() {
+ return active == null ? null : active.getWorld();
+ }
+
+ public abstract void resetAvatarNow();
+
+ public static Pilot changeActiveRoom(Room newRoom) {
+ BackgroundLoader.activeRoomChanged(newRoom);
+ Console oldc = Console.getActive();
+ Console newc = oldc;
+ if (newRoom != null) {
+ newc = newRoom.getWorld().getConsole();
+ }
+
+ Pilot p = newc.getPilot();
+ if (p != active) {
+ p.transferFrom(active);
+ if (newRoom != null && active != null && newRoom == active.getRoom()) {
+ p.makeIdentity().post(active);
+ }
+ }
+
+ if (oldc != newc) {
+ newc.forPilotOnlyActivate();
+ }
+
+ if (oldc != null) {
+ active.detach();
+ }
+
+ active = p;
+ p.setUpCameras(newc);
+ if (newRoom != null) {
+ newRoom.add(p);
+ }
+
+ active.resetAvatarNow();
+ newc.checkCourtesyVIP();
+ if (active.getWorld() != lastWorld) {
+ lastWorld = active.getWorld();
+ newc.displayAds();
+ WorldScriptManager.getInstance().worldEntered(lastWorld.toString());
+ }
+
+ WorldScriptManager.getInstance().roomEntered(newRoom.toString());
+ newRoom.addPostrenderHandler(BlackBox.getInstance());
+ newRoom.addFrameHandler(BlackBox.getInstance(), null);
+ return active;
+ }
+
+ public void changeChannel(String newChannel) {
+ Galaxy g = this.console.getGalaxy();
+ g.changeChannel(newChannel);
+ }
+
+ private void setUpCameras(Console c) {
+ Enumeration<Camera> camList = (Enumeration<Camera>)this.getContents();
+ Enumeration<FramePart> e = c.getParts();
+
+ while (e.hasMoreElements()) {
+ Object o = e.nextElement();
+ if (o instanceof RenderCanvas && !(o instanceof AdPart)) {
+ ((RenderCanvas)o).setCamera(getNextCamera(camList));
+ }
+ }
+ }
+
+ public Camera getMainCamera() {
+ if (this.lastCam != null) {
+ SuperRoot o = this.lastCam.getOwner();
+ if (o == this || o != null && o.getOwner() == this) {
+ return this.lastCam;
+ }
+ }
+
+ return this.lastCam = getNextCamera(new DeepEnumeration<Camera>((Enumeration<Camera>)this.getContents()));
+ }
+
+ private static Camera getNextCamera(Enumeration<Camera> list) {
+ while (list.hasMoreElements()) {
+ Object o = list.nextElement();
+ if (o instanceof Camera) {
+ return (Camera)o;
+ }
+ }
+
+ return null;
+ }
+
+ protected void transferFrom(Pilot old) {
+ if (old != null) {
+ this.lastx = old.lastx;
+ this.lasty = old.lasty;
+ this.lastz = old.lastz;
+ this.lastdir = old.lastdir;
+ this.lastroom = old.lastroom;
+ this.positionSentTime = old.positionSentTime;
+ Enumeration<Object> ehs = this.getHandlers();
+
+ while (ehs.hasMoreElements()) {
+ Object eh = ehs.nextElement();
+ if (eh instanceof MomentumBehavior) {
+ ((MomentumBehavior)eh).transferFrom(old.getHandlers());
+ }
+ }
+
+ this.getMainCamera().transferFrom(old.getMainCamera());
+ }
+ }
+
+ @Override
+ public boolean handle(BumpEventTemp b) {
+ this.slideBumpHandler(b);
+ return true;
+ }
+
+ public void slideBumpHandler(BumpEventTemp b) {
+ if (b.receiver == b.source) {
+ Point3Temp bumpNormal = Point3Temp.make(b.bumpNormal).normalize();
+ b.postBumpPath.minus(Point3Temp.make(bumpNormal).times(b.postBumpPath.dot(bumpNormal)));
+ b.postBumpPath.plus(Point3Temp.make(b.bumpNormal).times(1.0E-6F));
+ }
+ }
+
+ @Override
+ public void makeShadow() {
+ }
+
+ public void setConsole(Console c) {
+ assert this.console == null;
+
+ this.console = c;
+ copySoul(c.getPilotSoulTemplate(), this);
+ }
+
+ private static void saveEnum(Saver s, Enumeration<?> e) throws IOException {
+ while (e.hasMoreElements()) {
+ Object o = e.nextElement();
+ if (o instanceof Persister && !(o instanceof NonPersister)) {
+ s.saveMaybeNull((Persister)o);
+ }
+ }
+
+ s.saveMaybeNull(null);
+ }
+
+ public static void copySoul(WObject source, WObject target) {
+ ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+
+ try {
+ Saver saver = new Saver(new DataOutputStream(buffer));
+ saveEnum(saver, source.getContents());
+ saveEnum(saver, source.getHandlers());
+ saveEnum(saver, source.getActions());
+ saveEnum(saver, source.getAttributes());
+ saver.done();
+ } catch (Exception var5) {
+ var5.printStackTrace(System.out);
+ throw new Error(var5.toString());
+ }
+
+ try {
+ Restorer r = new Restorer(new DataInputStream(new ByteArrayInputStream(buffer.toByteArray())));
+
+ Persister p;
+ while ((p = r.restoreMaybeNull()) != null) {
+ target.add((Transform)p);
+ }
+
+ while ((p = r.restoreMaybeNull()) != null) {
+ target.addHandler((SuperRoot)p);
+ }
+
+ while ((p = r.restoreMaybeNull()) != null) {
+ target.addAction((Action)p);
+ }
+
+ while ((p = r.restoreMaybeNull()) != null) {
+ target.addAttribute((Attribute)p);
+ }
+
+ r.done();
+ } catch (Exception var6) {
+ var6.printStackTrace(System.out);
+ throw new Error(var6.toString());
+ }
+ }
+
+ @Override
+ protected void noteUnadding(SuperRoot child) {
+ if (child instanceof WObject) {
+ WObject w = (WObject)child;
+ w.isDynamic();
+ }
+
+ super.noteUnadding(child);
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = new Property(this, index, "Console");
+ } else if (mode == 1) {
+ ret = this.console;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 1, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ if (this.console != null) {
+ System.out.println("Warning: saving pilot " + this.getName() + " with soul, which won't restore correctly!");
+ }
+
+ s.saveVersion(0, classCookie);
+ super.saveState(s);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/PitchDriver.java b/NET/worlds/scape/PitchDriver.java
new file mode 100644
index 0000000..8d2210c
--- /dev/null
+++ b/NET/worlds/scape/PitchDriver.java
@@ -0,0 +1,196 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+import java.util.Enumeration;
+
+public class PitchDriver extends SwitchableBehavior implements KeyUpHandler, KeyDownHandler, FrameHandler, Persister, MomentumBehavior {
+ protected float pitch_force;
+ protected float pitch_vel;
+ protected int lastTime;
+ protected float maxdvpitch = 166.0F;
+ protected float pitch_damp = -5.0F;
+ protected float minpitch_vel = 3.0F;
+ protected float pitch_key = 500.0F;
+ private static Object cookie = new Object();
+
+ public void applyFrameForce(Event e) {
+ if (e.receiver instanceof Pilot) {
+ Camera cam = ((Pilot)e.receiver).getMainCamera();
+ int now = e.time;
+ float dt = (now - this.lastTime) / 1000.0F;
+ if (!(dt <= 0.0F)) {
+ this.lastTime = now;
+ float dTheta = this.pitch_vel * dt;
+ float dv = 0.0F;
+ if (this.pitch_force != 0.0F) {
+ dv += this.pitch_force * dt;
+ dv = this.maxdvpitch * (float)Math.atan(dv / this.maxdvpitch);
+ this.pitch_vel += dv;
+ dTheta += dv * dt;
+ }
+
+ if (dTheta != 0.0F) {
+ Point3Temp axis = Point3Temp.make();
+ float angle = cam.lookAround.getSpin(axis);
+ if (axis.x < 0.0F) {
+ angle = -angle;
+ }
+
+ if (angle + dTheta > 90.0F) {
+ dTheta = 90.0F - angle;
+ } else if (angle + dTheta < -90.0F) {
+ dTheta = -90.0F - angle;
+ }
+
+ cam.lookAround.spin(1.0F, 0.0F, 0.0F, dTheta);
+ }
+
+ this.pitch_vel = (float)(this.pitch_vel * Math.exp(this.pitch_damp * dt));
+ if (Math.abs(this.pitch_vel) < this.minpitch_vel) {
+ this.pitch_vel = 0.0F;
+ }
+ }
+ }
+ }
+
+ @Override
+ public boolean handle(FrameEvent e) {
+ this.applyFrameForce(e);
+ return true;
+ }
+
+ public void resetPitch(Event e) {
+ Camera cam = ((Pilot)e.receiver).getMainCamera();
+ cam.lookAround.makeIdentity();
+ }
+
+ @Override
+ public boolean handle(KeyDownEvent e) {
+ float pitch;
+ if (e.getKey() == '\ue321') {
+ pitch = this.pitch_key;
+ } else {
+ if (e.getKey() != '\ue322') {
+ if (e.getKey() == '\ue324') {
+ this.resetPitch(e);
+ }
+
+ return true;
+ }
+
+ pitch = -this.pitch_key;
+ }
+
+ this.applyFrameForce(e);
+ this.pitch_force = pitch;
+ return true;
+ }
+
+ @Override
+ public boolean handle(KeyUpEvent e) {
+ if (e.getKey() == '\ue321' || e.getKey() == '\ue322') {
+ this.applyFrameForce(e);
+ this.pitch_force = 0.0F;
+ }
+
+ return true;
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Pitch max acceleration"));
+ } else if (mode == 1) {
+ ret = new Float(this.maxdvpitch);
+ } else if (mode == 2) {
+ this.maxdvpitch = ((Float)value).intValue();
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Pitch rate damping"));
+ } else if (mode == 1) {
+ ret = new Float(this.pitch_damp);
+ } else if (mode == 2) {
+ this.pitch_damp = ((Float)value).intValue();
+ }
+ break;
+ case 2:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Pitch min rate"));
+ } else if (mode == 1) {
+ ret = new Float(this.minpitch_vel);
+ } else if (mode == 2) {
+ this.minpitch_vel = ((Float)value).intValue();
+ }
+ break;
+ case 3:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Pitch rate increment for up/down arrow keys"));
+ } else if (mode == 1) {
+ ret = new Float(this.pitch_key);
+ } else if (mode == 2) {
+ this.pitch_key = ((Float)value).intValue();
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 12, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(1, cookie);
+ super.saveState(s);
+ s.saveFloat(this.pitch_vel);
+ s.saveFloat(this.maxdvpitch);
+ s.saveFloat(this.pitch_damp);
+ s.saveFloat(this.minpitch_vel);
+ s.saveFloat(this.pitch_key);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(cookie)) {
+ case 0:
+ r.setOldFlag();
+ super.restoreState(r);
+ r.restoreFloat();
+ this.pitch_vel = r.restoreFloat();
+ this.maxdvpitch = r.restoreFloat();
+ this.pitch_damp = r.restoreFloat();
+ this.minpitch_vel = r.restoreFloat();
+ this.pitch_key = r.restoreFloat();
+ break;
+ case 1:
+ super.restoreState(r);
+ this.pitch_vel = r.restoreFloat();
+ this.maxdvpitch = r.restoreFloat();
+ this.pitch_damp = r.restoreFloat();
+ this.minpitch_vel = r.restoreFloat();
+ this.pitch_key = r.restoreFloat();
+ break;
+ default:
+ throw new TooNewException();
+ }
+ }
+
+ @Override
+ public void transferFrom(Enumeration oldMBs) {
+ while (oldMBs.hasMoreElements()) {
+ SuperRoot sr = (SuperRoot)oldMBs.nextElement();
+ if (sr instanceof PitchDriver) {
+ PitchDriver pd = (PitchDriver)sr;
+ this.pitch_vel = pd.pitch_vel;
+ this.pitch_force = pd.pitch_force;
+ this.lastTime = pd.lastTime;
+ break;
+ }
+ }
+ }
+}
diff --git a/NET/worlds/scape/PitchWidget.java b/NET/worlds/scape/PitchWidget.java
new file mode 100644
index 0000000..c6e741a
--- /dev/null
+++ b/NET/worlds/scape/PitchWidget.java
@@ -0,0 +1,19 @@
+package NET.worlds.scape;
+
+class PitchWidget extends WidgetButton {
+ public PitchWidget(ToolBar toolbar) {
+ super(toolbar, "pitch.gif", "Pitch");
+ }
+
+ @Override
+ public String drag(boolean initialDrag, float deltax, float deltay) {
+ if (Math.abs(deltax) > Math.abs(deltay)) {
+ deltay = 0.0F;
+ }
+
+ Transform t = Transform.make();
+ this.applyWorldTransform(initialDrag, t.spin(this.getWorldAxis(1, 0, 0), -deltay));
+ t.recycle();
+ return "Pitch";
+ }
+}
diff --git a/NET/worlds/scape/PlaneBumpCalc.java b/NET/worlds/scape/PlaneBumpCalc.java
new file mode 100644
index 0000000..83fed14
--- /dev/null
+++ b/NET/worlds/scape/PlaneBumpCalc.java
@@ -0,0 +1,65 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+public class PlaneBumpCalc extends BumpCalc {
+ private static Object classCookie = new Object();
+
+ @Override
+ public void detectBump(BumpEventTemp b, WObject owner) {
+ WObject source = (WObject)b.source;
+ Point3Temp sourceStart = source.getWorldPosition();
+ Transform xfrm = owner.getObjectToWorldMatrix();
+ Point3Temp start = xfrm.getPosition();
+ Point3Temp right = owner.getPlaneExtent().times(xfrm);
+ Point3Temp d = Point3Temp.make(right).minus(start);
+ xfrm.recycle();
+ BoundBoxTemp sourceBox = source.getBoundBox();
+ Point2 corner;
+ if (d.x > 0.0F) {
+ if (d.y > 0.0F) {
+ corner = new Point2(sourceBox.lo.x, sourceBox.hi.y);
+ } else {
+ corner = new Point2(sourceBox.hi.x, sourceBox.hi.y);
+ }
+ } else if (d.y > 0.0F) {
+ corner = new Point2(sourceBox.lo.x, sourceBox.lo.y);
+ } else {
+ corner = new Point2(sourceBox.hi.x, sourceBox.lo.y);
+ }
+
+ Point2 dn = new Point2(-d.y, d.x).normalize();
+ corner.x = corner.x - sourceStart.x;
+ corner.y = corner.y - sourceStart.y;
+ float dist = corner.dot(dn);
+ Point3Temp extent = Point3Temp.make(dn.x * dist, dn.y * dist, 0.0F);
+ if (!b.hitRegion(owner, Point3Temp.make(start).minus(extent), d, extent)) {
+ Point3Temp ccwNormal = Point3Temp.make(extent.y, -extent.x, 0.0F);
+ d = Point3Temp.make(ccwNormal).minus(extent);
+ Point3Temp extentL = Point3Temp.make(-d.y, d.x, 0.0F).normalize().times(dist / 1.5F);
+ Point3Temp startL = Point3Temp.make(start).minus(ccwNormal);
+ if (!b.hitRegion(owner, startL, d, extentL)) {
+ if (!b.hitRegion(owner, Point3Temp.make(right).minus(extent), Point3Temp.make(-d.y, d.x, 0.0F), Point3Temp.make(-extentL.y, extentL.x, 0.0F))) {
+ ;
+ }
+ }
+ }
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(0, classCookie);
+ super.saveState(s);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/PlaybackRecordingAction.java b/NET/worlds/scape/PlaybackRecordingAction.java
new file mode 100644
index 0000000..3b9e7d8
--- /dev/null
+++ b/NET/worlds/scape/PlaybackRecordingAction.java
@@ -0,0 +1,59 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.BlackBox;
+import NET.worlds.network.URL;
+import java.io.IOException;
+
+public class PlaybackRecordingAction extends Action {
+ private String filename = "home:record.rec";
+ private static Object classCookie = new Object();
+
+ public void setFilename(String m) {
+ this.filename = m;
+ }
+
+ @Override
+ public Persister trigger(Event e, Persister seqId) {
+ BlackBox.getInstance().play(URL.make(this.filename));
+ return null;
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Filename"));
+ } else if (mode == 1) {
+ ret = new String(this.filename);
+ } else if (mode == 2) {
+ this.filename = (String)value;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 1, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(1, classCookie);
+ super.saveState(s);
+ s.saveString(this.filename);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 1:
+ super.restoreState(r);
+ this.filename = r.restoreString();
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/Point2.java b/NET/worlds/scape/Point2.java
new file mode 100644
index 0000000..3b471b7
--- /dev/null
+++ b/NET/worlds/scape/Point2.java
@@ -0,0 +1,129 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+public class Point2 implements Persister {
+ public float x;
+ public float y;
+ private static Object classCookie = new Object();
+
+ public Point2() {
+ }
+
+ public Point2(float _x, float _y) {
+ this.set(_x, _y);
+ }
+
+ public Point2(Point2 p) {
+ this.x = p.x;
+ this.y = p.y;
+ }
+
+ public Point2 copy(Point2 b) {
+ this.x = b.x;
+ this.y = b.y;
+ return this;
+ }
+
+ public void set(float _x, float _y) {
+ this.x = _x;
+ this.y = _y;
+ }
+
+ public float length() {
+ return (float)Math.sqrt(this.x * this.x + this.y * this.y);
+ }
+
+ public Point2 normalize() {
+ float len = this.length();
+ if (len > 0.0F) {
+ this.dividedBy(len);
+ }
+
+ return this;
+ }
+
+ public Point2 negate() {
+ this.x = -this.x;
+ this.y = -this.y;
+ return this;
+ }
+
+ public Point2 plus(Point2 p) {
+ this.x = this.x + p.x;
+ this.y = this.y + p.y;
+ return this;
+ }
+
+ public Point2 plus(float v) {
+ this.x += v;
+ this.y += v;
+ return this;
+ }
+
+ public Point2 minus(float v) {
+ return this.plus(-v);
+ }
+
+ public Point2 minus(Point2 p) {
+ this.x = this.x - p.x;
+ this.y = this.y - p.y;
+ return this;
+ }
+
+ public Point2 times(float v) {
+ this.x *= v;
+ this.y *= v;
+ return this;
+ }
+
+ public Point2 times(Point2 p) {
+ this.x = this.x * p.x;
+ this.y = this.y * p.y;
+ return this;
+ }
+
+ public Point2 dividedBy(float v) {
+ this.x /= v;
+ this.y /= v;
+ return this;
+ }
+
+ public Point2 dividedBy(Point2 p) {
+ this.x = this.x / p.x;
+ this.y = this.y / p.y;
+ return this;
+ }
+
+ public float dot(Point2 p) {
+ return p.x * this.x + p.y * this.y;
+ }
+
+ @Override
+ public String toString() {
+ return this.x + "," + this.y;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(0, classCookie);
+ s.saveFloat(this.x);
+ s.saveFloat(this.y);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ this.x = r.restoreFloat();
+ this.y = r.restoreFloat();
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+
+ @Override
+ public void postRestore(int version) {
+ }
+}
diff --git a/NET/worlds/scape/Point2EditorDialog.java b/NET/worlds/scape/Point2EditorDialog.java
new file mode 100644
index 0000000..61f62e6
--- /dev/null
+++ b/NET/worlds/scape/Point2EditorDialog.java
@@ -0,0 +1,66 @@
+package NET.worlds.scape;
+
+import java.util.StringTokenizer;
+
+class Point2EditorDialog extends ListEditorDialog {
+ protected Property property;
+ protected Point2 p;
+
+ Point2EditorDialog(EditTile parent, String title, Property property) {
+ super(parent, title);
+ this.property = property;
+ this.ready();
+ }
+
+ @Override
+ protected void build() {
+ this.p = (Point2)this.property.get();
+ super.build();
+ }
+
+ @Override
+ protected int getElementCount() {
+ return 2;
+ }
+
+ @Override
+ protected String getElement(int index) {
+ switch (index) {
+ case 0:
+ return "" + this.p.x;
+ default:
+ return "" + this.p.y;
+ }
+ }
+
+ @Override
+ protected boolean setElements(StringTokenizer e) {
+ Point2 p = new Point2();
+ int count = 0;
+
+ while (e.hasMoreTokens()) {
+ try {
+ float tmp = Float.valueOf(e.nextToken());
+ switch (count++) {
+ case 0:
+ p.x = tmp;
+ break;
+ case 1:
+ p.y = tmp;
+ break;
+ default:
+ return false;
+ }
+ } catch (Exception var5) {
+ return false;
+ }
+ }
+
+ if (count != 2) {
+ return false;
+ } else {
+ this.parent.addUndoableSet(this.property, p);
+ return true;
+ }
+ }
+}
diff --git a/NET/worlds/scape/Point2PropertyEditor.java b/NET/worlds/scape/Point2PropertyEditor.java
new file mode 100644
index 0000000..58ea863
--- /dev/null
+++ b/NET/worlds/scape/Point2PropertyEditor.java
@@ -0,0 +1,19 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.PolledDialog;
+
+public class Point2PropertyEditor extends PropEditor {
+ private Point2PropertyEditor(Property property) {
+ super(property);
+ }
+
+ @Override
+ public PolledDialog edit(EditTile parent, String title) {
+ return new Point2EditorDialog(parent, title, this.property);
+ }
+
+ public static Property make(Property property) {
+ property.setPropertyType(7);
+ return property.setEditor(new Point2PropertyEditor(property));
+ }
+}
diff --git a/NET/worlds/scape/Point3.java b/NET/worlds/scape/Point3.java
new file mode 100644
index 0000000..b4c4921
--- /dev/null
+++ b/NET/worlds/scape/Point3.java
@@ -0,0 +1,47 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+public class Point3 extends Point3Temp implements Persister {
+ private static Object classCookie = new Object();
+
+ public Point3() {
+ super(0);
+ }
+
+ public Point3(float x, float y, float z) {
+ super(0);
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ public Point3(Point3Temp p) {
+ this(p.x, p.y, p.z);
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(0, classCookie);
+ s.saveFloat(this.x);
+ s.saveFloat(this.y);
+ s.saveFloat(this.z);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ this.x = r.restoreFloat();
+ this.y = r.restoreFloat();
+ this.z = r.restoreFloat();
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+
+ @Override
+ public void postRestore(int version) {
+ }
+}
diff --git a/NET/worlds/scape/Point3EditorDialog.java b/NET/worlds/scape/Point3EditorDialog.java
new file mode 100644
index 0000000..02134cb
--- /dev/null
+++ b/NET/worlds/scape/Point3EditorDialog.java
@@ -0,0 +1,71 @@
+package NET.worlds.scape;
+
+import java.util.StringTokenizer;
+
+class Point3EditorDialog extends ListEditorDialog {
+ protected Property property;
+ protected Point3 p;
+
+ Point3EditorDialog(EditTile parent, String title, Property property) {
+ super(parent, title);
+ this.property = property;
+ this.ready();
+ }
+
+ @Override
+ protected void build() {
+ this.p = (Point3)this.property.get();
+ super.build();
+ }
+
+ @Override
+ protected int getElementCount() {
+ return 3;
+ }
+
+ @Override
+ protected String getElement(int index) {
+ switch (index) {
+ case 0:
+ return "" + this.p.x;
+ case 1:
+ return "" + this.p.y;
+ default:
+ return "" + this.p.z;
+ }
+ }
+
+ @Override
+ protected boolean setElements(StringTokenizer e) {
+ Point3 p = new Point3();
+ int count = 0;
+
+ while (e.hasMoreTokens()) {
+ try {
+ float tmp = Float.valueOf(e.nextToken());
+ switch (count++) {
+ case 0:
+ p.x = tmp;
+ break;
+ case 1:
+ p.y = tmp;
+ break;
+ case 2:
+ p.z = tmp;
+ break;
+ default:
+ return false;
+ }
+ } catch (Exception var5) {
+ return false;
+ }
+ }
+
+ if (count != 3) {
+ return false;
+ } else {
+ this.parent.addUndoableSet(this.property, p);
+ return true;
+ }
+ }
+}
diff --git a/NET/worlds/scape/Point3PropertyEditor.java b/NET/worlds/scape/Point3PropertyEditor.java
new file mode 100644
index 0000000..6f0c01c
--- /dev/null
+++ b/NET/worlds/scape/Point3PropertyEditor.java
@@ -0,0 +1,19 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.PolledDialog;
+
+public class Point3PropertyEditor extends PropEditor {
+ private Point3PropertyEditor(Property property) {
+ super(property);
+ }
+
+ @Override
+ public PolledDialog edit(EditTile parent, String title) {
+ return new Point3EditorDialog(parent, title, this.property);
+ }
+
+ public static Property make(Property property) {
+ property.setPropertyType(8);
+ return property.setEditor(new Point3PropertyEditor(property));
+ }
+}
diff --git a/NET/worlds/scape/Point3Temp.java b/NET/worlds/scape/Point3Temp.java
new file mode 100644
index 0000000..361b578
--- /dev/null
+++ b/NET/worlds/scape/Point3Temp.java
@@ -0,0 +1,168 @@
+package NET.worlds.scape;
+
+public class Point3Temp {
+ public float x;
+ public float y;
+ public float z;
+ private static Recycler recycler = new Recycler();
+
+ static {
+ nativeInit();
+ }
+
+ public static native void nativeInit();
+
+ public static Point3Temp make(float x, float y, float z) {
+ Point3Temp p = (Point3Temp)recycler.alloc();
+ if (p == null) {
+ recycler.recycle(new Point3Temp(0));
+ p = (Point3Temp)recycler.alloc();
+ }
+
+ p.x = x;
+ p.y = y;
+ p.z = z;
+ return p;
+ }
+
+ public static Point3Temp make() {
+ return make(0.0F, 0.0F, 0.0F);
+ }
+
+ public static Point3Temp make(Point3Temp p) {
+ return make(p.x, p.y, p.z);
+ }
+
+ protected Point3Temp(int dummy) {
+ }
+
+ public Point3Temp copy(Point3Temp b) {
+ this.set(b.x, b.y, b.z);
+ return this;
+ }
+
+ public void set(float _x, float _y, float _z) {
+ this.x = _x;
+ this.y = _y;
+ this.z = _z;
+ }
+
+ public float length() {
+ return (float)Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
+ }
+
+ public float squaredLength() {
+ return this.x * this.x + this.y * this.y + this.z * this.z;
+ }
+
+ public native Point3Temp times(Transform var1);
+
+ public native Point3Temp vectorTimes(Transform var1);
+
+ public Point3Temp normalize() {
+ float len = this.length();
+ if (len > 0.0F) {
+ this.dividedBy(len);
+ }
+
+ return this;
+ }
+
+ public Point3Temp negate() {
+ this.x = -this.x;
+ this.y = -this.y;
+ this.z = -this.z;
+ return this;
+ }
+
+ public Point3Temp abs() {
+ this.x = Math.abs(this.x);
+ this.y = Math.abs(this.y);
+ this.z = Math.abs(this.z);
+ return this;
+ }
+
+ public static Point3Temp getDirVector(float amount, float angle) {
+ angle = (float)(angle * (Math.PI / 180.0));
+ return make(-amount * (float)Math.sin(angle), amount * (float)Math.cos(angle), 0.0F);
+ }
+
+ public Point3Temp plus(Point3Temp p) {
+ this.x = this.x + p.x;
+ this.y = this.y + p.y;
+ this.z = this.z + p.z;
+ return this;
+ }
+
+ public Point3Temp cross(Point3Temp p) {
+ float xNew = this.y * p.z - this.z * p.y;
+ float yNew = this.z * p.x - this.x * p.z;
+ this.z = this.x * p.y - this.y * p.x;
+ this.x = xNew;
+ this.y = yNew;
+ return this;
+ }
+
+ public Point3Temp plus(float v) {
+ this.x += v;
+ this.y += v;
+ this.z += v;
+ return this;
+ }
+
+ public Point3Temp minus(float v) {
+ return this.plus(-v);
+ }
+
+ public Point3Temp minus(Point3Temp p) {
+ this.x = this.x - p.x;
+ this.y = this.y - p.y;
+ this.z = this.z - p.z;
+ return this;
+ }
+
+ public Point3Temp times(float v) {
+ this.x *= v;
+ this.y *= v;
+ this.z *= v;
+ return this;
+ }
+
+ public Point3Temp times(Point3Temp p) {
+ this.x = this.x * p.x;
+ this.y = this.y * p.y;
+ this.z = this.z * p.z;
+ return this;
+ }
+
+ public Point3Temp dividedBy(float v) {
+ this.x /= v;
+ this.y /= v;
+ this.z /= v;
+ return this;
+ }
+
+ public Point3Temp dividedBy(Point3Temp p) {
+ this.x = this.x / p.x;
+ this.y = this.y / p.y;
+ this.z = this.z / p.z;
+ return this;
+ }
+
+ public float dot(Point3Temp p) {
+ return p.x * this.x + p.y * this.y + p.z * this.z;
+ }
+
+ public float det(Point3Temp a, Point3Temp b) {
+ return this.x * a.y * b.z + a.x * b.y * this.z + b.x * this.y * a.z - this.z * a.y * b.x - a.z * b.y * this.x - b.z * this.y * a.x;
+ }
+
+ public boolean sameValue(Point3Temp p) {
+ return p == null ? false : this.x == p.x && this.y == p.y && this.z == p.z;
+ }
+
+ @Override
+ public String toString() {
+ return this.x + "," + this.y + "," + this.z;
+ }
+}
diff --git a/NET/worlds/scape/Polygon.java b/NET/worlds/scape/Polygon.java
new file mode 100644
index 0000000..7305c86
--- /dev/null
+++ b/NET/worlds/scape/Polygon.java
@@ -0,0 +1,75 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+public class Polygon extends Surface {
+ protected float[] vertices;
+ private static Object classCookie = new Object();
+
+ public Polygon(int numVertices, Material material) {
+ this(new float[5 * numVertices], material);
+ }
+
+ public Polygon(float[] vertices, Material material) {
+ super(material);
+
+ assert vertices.length % 5 == 0;
+
+ this.vertices = vertices;
+ }
+
+ public Polygon() {
+ }
+
+ public void setVertex(int i, float x, float y, float z, float u, float v) {
+ i *= 5;
+ this.vertices[i] = x;
+ this.vertices[i + 1] = y;
+ this.vertices[i + 2] = z;
+ this.vertices[i + 3] = u;
+ this.vertices[i + 4] = v;
+ this.nativeSetVertex(i, x, y, z, u, v);
+ }
+
+ public native void nativeSetVertex(int var1, float var2, float var3, float var4, float var5, float var6);
+
+ @Override
+ protected void addRwChildren(WObject parent) {
+ this.addNewRwChild(parent);
+
+ for (int i = 0; i < this.vertices.length; i += 5) {
+ this.addVertex(this.vertices[i], this.vertices[i + 1], this.vertices[i + 2], this.vertices[i + 3], this.vertices[i + 4]);
+ }
+
+ this.doneWithEditing();
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(0, classCookie);
+ super.saveState(s);
+ s.saveInt(this.vertices.length);
+
+ for (int i = 0; i < this.vertices.length; i++) {
+ s.saveFloat(this.vertices[i]);
+ }
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ int length = r.restoreInt();
+ this.vertices = new float[length];
+
+ for (int i = 0; i < length; i++) {
+ this.vertices[i] = r.restoreFloat();
+ }
+
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/Portal.java b/NET/worlds/scape/Portal.java
new file mode 100644
index 0000000..e2f05b6
--- /dev/null
+++ b/NET/worlds/scape/Portal.java
@@ -0,0 +1,831 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.Main;
+import NET.worlds.console.MainCallback;
+import NET.worlds.network.NetUpdate;
+import NET.worlds.network.URL;
+import java.awt.Color;
+import java.io.IOException;
+import java.text.MessageFormat;
+import java.util.Vector;
+
+public class Portal extends Rect implements BumpHandler, Prerenderable, Postrenderable, Properties, Persister, LoadedURLSelf {
+ static final int UNCONNECTED = -1;
+ static final int INITIAL = 0;
+ static final int DOWNLOADING = 1;
+ static final int DONE = 2;
+ private int _state = -1;
+ private Portal _farSidePortal = null;
+ String _farSidePortalName = null;
+ private boolean _farSideIsPortal = true;
+ private boolean _allowDownload = true;
+ String _farSideRoomName = null;
+ private URL _farSideWorld = null;
+ private Room _farSideRoom = null;
+ private float _farx;
+ private float _fary;
+ private float _farz;
+ private float _fartheta;
+ private float _userFarx;
+ private float _userFary;
+ private float _userFarz;
+ private float _userFartheta;
+ private boolean frozeFrameEvents;
+ private Transform _p2pxform = null;
+ private int _changeNum = 0;
+ private int _farChangeNum = -1;
+ static BumpCalc standardPassthroughBumpCalc = new PassthroughBumpCalc();
+ private static Object classCookie = new Object();
+
+ static {
+ nativeInit();
+ standardPassthroughBumpCalc.setName("defaultPassthroughBumpCalc");
+ }
+
+ protected Room getFarSideRoom() {
+ return this._farSideRoom;
+ }
+
+ public Portal(float w, float h) {
+ super(w, h, null);
+ }
+
+ public Portal(float llx, float lly, float llz, float urx, float ury, float urz) {
+ super(llx, lly, llz, urx, ury, urz, null);
+ }
+
+ public Portal() {
+ }
+
+ public void setFarSideInfo(URL world, String room, String portal) {
+ this._farSideWorld = world;
+ this._farSideRoomName = room;
+ this._farSidePortalName = portal;
+ }
+
+ public Portal(Point3Temp llc, Point3Temp urc) {
+ super(llc, urc, null);
+ }
+
+ public static Portal findByName(Room r, String portalName) {
+ SuperRoot sr = SuperRoot.nameSearch(r.getDeepOwned(), portalName);
+ return sr != null && sr instanceof Portal ? (Portal)sr : null;
+ }
+
+ public Portal connectTo(Portal far) {
+ assert this._state == -1;
+
+ this._farSideIsPortal = true;
+ this._farSidePortal = far;
+ this.newFarSide();
+ return this;
+ }
+
+ public Portal connectTo(URL farworld, String farroom, Point3Temp llc, Point3Temp urc) {
+ return this.connectTo(farworld, farroom, llc.x, llc.y, llc.z, urc.x, urc.y, urc.z);
+ }
+
+ public Portal connectTo(Room r, Point3Temp llc, Point3Temp urc) {
+ System.out.println("Warning! Old style Portal.connectTo called!");
+ Thread.dumpStack();
+
+ assert this._state == -1;
+
+ this._farSideWorld = r.getWorld().getSourceURL();
+ this._farSideRoomName = r.getName();
+ this.setFarSideRoom(r);
+ this._farx = this._userFarx = urc.x;
+ this._fary = this._userFary = urc.y;
+ this._farz = this._userFarz = llc.z;
+ this._userFartheta = (float)(Math.atan2(llc.y - urc.y, llc.x - urc.x) * 180.0 / Math.PI);
+ this._fartheta = this._userFartheta;
+ this._state = 2;
+ this._farSideIsPortal = false;
+ this.setTransform();
+ this.updateVisible();
+ return this;
+ }
+
+ public Portal connectTo(URL farworld, String farroom, float llx, float lly, float llz, float urx, float ury, float urz) {
+ float theta = (float)(Math.atan2(lly - ury, llx - urx) * 180.0 / Math.PI);
+ return this.connectTo(farworld, farroom, urx, ury, llz, theta);
+ }
+
+ public Portal connectTo(URL farworld, String farroom, float x, float y, float z, float theta) {
+ assert this._state == -1;
+
+ this._farSideWorld = farworld;
+ this._farSideRoomName = farroom;
+ this._farx = this._userFarx = x;
+ this._fary = this._userFary = y;
+ this._farz = this._userFarz = z;
+ this._fartheta = this._userFartheta = theta;
+ this._farSideIsPortal = false;
+ this.reset();
+ return this;
+ }
+
+ public Portal remotify() {
+ RPAction rpa = new RPAction();
+ this.addAction(rpa);
+ this.addHandler(new SameRoomSensor(rpa));
+ return this;
+ }
+
+ private void findFarSidePortal(boolean showmessage) {
+ if (this._farSideIsPortal) {
+ if (this._farSidePortalName == null) {
+ this._state = -1;
+ } else {
+ this._farSidePortal = null;
+ Vector portals = this._farSideRoom.getOutgoingPortals();
+ int len = portals.size();
+
+ for (int i = 0; i < len; i++) {
+ Portal p = (Portal)portals.elementAt(i);
+ if (p.getName().equals(this._farSidePortalName)) {
+ this._farSidePortal = p;
+ break;
+ }
+ }
+
+ if (this._farSidePortal == null) {
+ if (showmessage) {
+ Object[] arguments = new Object[]{
+ new String(this.getName()), new String("" + this._farSideWorld), new String(this._farSideRoomName), new String(this._farSidePortalName)
+ };
+ Console.println(MessageFormat.format(Console.message("Portal-doesnt"), arguments));
+ }
+
+ this._state = -1;
+ }
+ }
+
+ if (this._farSidePortal != null) {
+ this.newFarSide();
+ }
+ } else {
+ this._farSidePortal = null;
+ this._farx = this._userFarx;
+ this._fary = this._userFary;
+ this._farz = this._userFarz;
+ this._fartheta = this._userFartheta;
+ this._p2pxform = null;
+ }
+ }
+
+ public void reset() {
+ this.reset(true);
+ }
+
+ public void reset(boolean showmessage) {
+ this.setFarSideRoom(null);
+ if (this._farSideRoomName == null || (this.flags & 262144) != 0) {
+ this._state = -1;
+ } else if (this._farSideWorld == null) {
+ Room r = this.getRoom();
+ if (r != null) {
+ World w = r.getWorld();
+ if (w != null) {
+ this.setFarSideRoom(w.getRoom(this._farSideRoomName));
+ }
+ }
+
+ if (this._farSideRoom != null) {
+ this.findFarSidePortal(showmessage);
+ } else {
+ this._state = -1;
+ this._farSidePortal = null;
+ if (showmessage) {
+ Object[] arguments = new Object[]{
+ new String(this.getName()), new String("" + this.getRoom()), new String(this._farSideRoomName), new String(this._farSidePortalName)
+ };
+ Console.println(MessageFormat.format(Console.message("Room-doesnt"), arguments));
+ }
+ }
+ } else {
+ if (this._farSidePortalName == null) {
+ this._farSidePortal = null;
+ }
+
+ this._state = 0;
+ }
+
+ this.setTransform();
+ this.updateVisible();
+ }
+
+ @Override
+ public void discard() {
+ Portal far = this._farSidePortal;
+ this.setFarSideRoom(null);
+ this._state = 0;
+ super.discard();
+ if (far != null && far.getRoom() != null && this._farSideWorld != null) {
+ far.reset();
+ }
+ }
+
+ private void recomputeFarPosition() {
+ this.setFarSideRoom(this._farSidePortal.getRoom());
+ if (this._farSideRoom != null) {
+ this._farSideRoomName = this._farSideRoom.getName();
+ }
+
+ this._farSidePortalName = this._farSidePortal.getName();
+ Point3Temp farext = Point3Temp.make(1.0F, 0.0F, 1.0F).vectorTimes(this._farSidePortal);
+ Point3Temp farlrc = this._farSidePortal.getPosition();
+ if ((this.flags & 4) == 0) {
+ farlrc.x = farlrc.x + farext.x;
+ farlrc.y = farlrc.y + farext.y;
+ }
+
+ this._farx = farlrc.x;
+ this._fary = farlrc.y;
+ this._farz = farlrc.z;
+ this._fartheta = (-this._farSidePortal.getYaw() + 180.0F) % 360.0F;
+ this._farChangeNum = this._farSidePortal._changeNum;
+ this._p2pxform = null;
+ }
+
+ public Portal biconnect(Portal far) {
+ this.connectTo(far);
+ far.connectTo(this);
+ return this;
+ }
+
+ public void disconnect() {
+ this._farSideWorld = null;
+ this._farSideRoomName = null;
+ this.setFarSideRoom(null);
+ this._farSidePortal = null;
+ this._farSideIsPortal = true;
+ this._farSidePortalName = null;
+ this._state = -1;
+ this.updateVisible();
+ this.discardTransform();
+ }
+
+ public void bidisconnect() {
+ this._farSidePortal.disconnect();
+ this.disconnect();
+ }
+
+ public boolean connected() {
+ return this._farSidePortal != null || this._farSideRoomName != null && !this._farSideIsPortal;
+ }
+
+ public boolean active() {
+ return this._state == 2;
+ }
+
+ public boolean unconnected() {
+ return this._state == -1;
+ }
+
+ public boolean remote() {
+ return this._farSideWorld != null;
+ }
+
+ public Portal farSide() {
+ return this._farSideIsPortal ? this._farSidePortal : null;
+ }
+
+ public Room farSideRoom() {
+ return this._farSideRoom;
+ }
+
+ private void setFarSideRoom(Room far) {
+ this._farSideRoom = far;
+ }
+
+ @Override
+ protected void noteAddingTo(SuperRoot s) {
+ this.addToRoom(s);
+ super.noteAddingTo(s);
+ }
+
+ private void addToRoom(SuperRoot s) {
+ if (s instanceof WObject) {
+ Room r = ((WObject)s).getRoom();
+ if (r != null) {
+ r.addOutgoingPortal(this);
+ }
+ }
+ }
+
+ @Override
+ public void detach() {
+ Room r = this.getRoom();
+ if (r != null) {
+ r.removeOutgoingPortal(this);
+ }
+
+ super.detach();
+ }
+
+ public String farRoom() {
+ return this._farSideRoomName;
+ }
+
+ public URL farWorld() {
+ return this._farSideWorld;
+ }
+
+ public Transform p2pXform() {
+ return this._p2pxform;
+ }
+
+ @Override
+ protected void addRwChildren(WObject parent) {
+ if (this._farSidePortal != null && this._farSidePortal instanceof TwoWayPortal && !this._farSidePortal.isActive()) {
+ Main.register(new MainCallback() {
+ @Override
+ public void mainCallback() {
+ Portal.this.detach();
+ Main.unregister(this);
+ }
+ });
+ }
+
+ super.addRwChildren(parent);
+ this.updateVisible();
+ this.setTransform();
+ this.getRoom().prependPrerenderHandler(this);
+ this.getRoom().prependPostrenderHandler(this);
+ }
+
+ @Override
+ protected void markVoid() {
+ this.getRoom().removePrerenderHandler(this);
+ this.getRoom().removePostrenderHandler(this);
+ super.markVoid();
+ }
+
+ @Override
+ protected void noteTransformChange() {
+ this._changeNum++;
+ super.noteTransformChange();
+ this.discardTransform();
+ }
+
+ public static native void nativeInit();
+
+ @Override
+ protected native void updateVisible();
+
+ native void setTransform();
+
+ public void discardTransform() {
+ if (this._p2pxform != null) {
+ this._p2pxform = null;
+ if (this._farSidePortal != null) {
+ this._farSidePortal.discardTransform();
+ }
+ }
+ }
+
+ @Override
+ public native void prerender(Camera var1);
+
+ @Override
+ public native void postrender(Camera var1);
+
+ @Override
+ public BumpCalc getBumpCalc(BumpEventTemp b) {
+ if (this._farSidePortal == null
+ || !(b.source instanceof Camera)
+ || (this.flags & 4) == 0 && this._farSidePortal.active() && this._farSidePortal._p2pxform != null && this._farSidePortal.getVisible()) {
+ if (this.bumpCalc != null) {
+ return this.bumpCalc;
+ } else if (this._farSideRoomName == null) {
+ return standardPassthroughBumpCalc;
+ } else {
+ if (this.connected() && (this.flags & 262144) == 0) {
+ if (this._farSideRoom == null && this._farSideIsPortal && this._farSidePortal != null) {
+ this.setFarSideRoom(this._farSidePortal.getRoom());
+ }
+
+ if (this._farSideRoom != null && this._farSideRoom.isActive()) {
+ return standardPassthroughBumpCalc;
+ }
+ }
+
+ return super.getBumpCalc(b);
+ }
+ } else {
+ return super.getBumpCalc(b);
+ }
+ }
+
+ @Override
+ public boolean handle(BumpEventTemp b) {
+ if (this._farSidePortal == null
+ || !(b.source instanceof Camera)
+ || (this.flags & 4) == 0 && this._farSidePortal.active() && this._farSidePortal._p2pxform != null && this._farSidePortal.getVisible()) {
+ this.portalBumpHandler(b);
+ return true;
+ } else {
+ return true;
+ }
+ }
+
+ public void portalBumpHandler(BumpEventTemp b) {
+ if (b.target == this && this._state == 2) {
+ if (this._farSideRoom == null && this._farSideIsPortal && this._farSidePortal != null) {
+ this.setFarSideRoom(this._farSidePortal.getRoom());
+ }
+
+ if (this._farSideRoom != null && this._farSideRoom.isActive()) {
+ if (this._p2pxform == null) {
+ this.setTransform();
+ if (this._p2pxform == null) {
+ return;
+ }
+ }
+
+ b.postBumpRoom = this._farSideRoom;
+ Transform t = ((WObject)b.source).getObjectToWorldMatrix();
+ b.postBumpPosition.setTransform(t);
+ t.recycle();
+ b.postBumpPosition.moveBy(b.path).post(this._p2pxform);
+ b.postBumpPath = new Point3(b.fullPath).times(1.0F - b.fraction).vectorTimes(this._p2pxform);
+ }
+ } else {
+ if (this._state == 1 && this._farSideWorld != null && !this._farSideWorld.isRemote() && !this.frozeFrameEvents) {
+ this.frozeFrameEvents = true;
+ Console.setFreezeFrameEvents(true);
+ }
+ }
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = URLPropertyEditor.make(new Property(this, index, "Destination World URL (null means this world)").allowSetNull(), "world");
+ } else if (mode == 1) {
+ ret = this._farSideWorld;
+ } else if (mode == 2) {
+ this._farSideWorld = (URL)value;
+ this.reset();
+ this.triggerLoad();
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Destination Room Name").allowSetNull());
+ } else if (mode == 1) {
+ ret = this._farSideRoomName == null ? "" : this._farSideRoomName;
+ } else if (mode == 2) {
+ this._farSideRoomName = (String)value;
+ if ("".equals(this._farSideRoomName)) {
+ this._farSideRoomName = null;
+ }
+
+ this.reset();
+ this.triggerLoad();
+ }
+ break;
+ case 2:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Connect to a portal"), "Use location and orientation", "Use portal");
+ } else if (mode == 1) {
+ ret = new Boolean(this._farSideIsPortal);
+ } else if (mode == 2) {
+ boolean tmp = (Boolean)value;
+ this._farSideIsPortal = tmp;
+ this.reset();
+ this.triggerLoad();
+ }
+ break;
+ case 3:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Download if world not present"), "Never download", "Allow download");
+ } else if (mode == 1) {
+ ret = new Boolean(this._allowDownload);
+ } else if (mode == 2) {
+ boolean tmp = (Boolean)value;
+ this._allowDownload = tmp;
+ }
+ break;
+ case 4:
+ if (mode == 0) {
+ ret = new Property(this, index, "Destination Portal Name");
+ if (this._farSideIsPortal) {
+ ret = StringPropertyEditor.make((Property)ret);
+ }
+ } else if (mode == 1) {
+ ret = this._farSidePortalName == null ? "" : this._farSidePortalName;
+ } else if (mode == 2) {
+ this._farSidePortalName = (String)value;
+ if ("".equals(this._farSidePortalName)) {
+ this._farSidePortalName = null;
+ }
+
+ this.reset();
+ this.triggerLoad();
+ }
+ break;
+ case 5:
+ if (mode == 0) {
+ ret = new Property(this, index, "Destination position");
+ if (!this._farSideIsPortal) {
+ ret = Point3PropertyEditor.make((Property)ret);
+ }
+ } else if (mode == 1) {
+ ret = new Point3(this._userFarx, this._userFary, this._userFarz);
+ } else if (mode == 2) {
+ Point3 p = (Point3)value;
+ this._farx = this._userFarx = p.x;
+ this._fary = this._userFary = p.y;
+ this._farz = this._userFarz = p.z;
+ this.reset();
+ this.triggerLoad();
+ }
+ break;
+ case 6:
+ if (mode == 0) {
+ ret = new Property(this, index, "Destination orientation (degrees, clockwise from North)");
+ if (!this._farSideIsPortal) {
+ ret = FloatPropertyEditor.make((Property)ret, 0.0F, 360.0F);
+ }
+ } else if (mode == 1) {
+ ret = new Float(this._userFartheta);
+ } else if (mode == 2) {
+ this._fartheta = this._userFartheta = (Float)value;
+ this.reset();
+ this.triggerLoad();
+ }
+ break;
+ case 7:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Mirrored"), "Normal", "Mirrored");
+ } else if (mode == 1) {
+ ret = new Boolean((this.flags & 4) != 0);
+ } else if (mode == 2) {
+ if ((Boolean)value) {
+ this.flags |= 4;
+ } else {
+ this.flags &= -5;
+ }
+
+ this.reset();
+ this.triggerLoad();
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 8, mode, value);
+ }
+
+ return ret;
+ }
+
+ private void newFarSide() {
+ this._farSidePortalName = this._farSidePortal.getName();
+ if (this._state == -1 && (this.flags & 262144) == 0) {
+ this._state = 2;
+ }
+
+ this.recomputeFarPosition();
+ this.setTransform();
+ this.updateVisible();
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ Portal tmp = null;
+ if (this._farSideWorld != null || this._farSidePortal != null && (!this._farSidePortal.isActive() || this._farSidePortal instanceof NonPersister)) {
+ tmp = this._farSidePortal;
+ this._farSidePortal = null;
+ }
+
+ s.saveVersion(9, classCookie);
+ super.saveState(s);
+ s.saveBoolean(this._farSideIsPortal);
+ s.saveBoolean(this._allowDownload);
+ s.saveString(this._farSidePortalName);
+ s.saveMaybeNull(this._farSidePortal);
+ URL.save(s, this._farSideWorld);
+ s.saveString(this._farSideRoomName);
+ s.saveFloat(this._userFarx);
+ s.saveFloat(this._userFary);
+ s.saveFloat(this._userFarz);
+ s.saveFloat(this._userFartheta);
+ if (tmp != null) {
+ this._farSidePortal = tmp;
+ }
+ }
+
+ public void superRestoreState(Restorer r) throws IOException, TooNewException {
+ this.restoreWObjectState(r);
+ this.setMaterial(new Material(Color.black));
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ float x = 0.0F;
+ float y = 0.0F;
+ float z = 0.0F;
+ int vers = r.restoreVersion(classCookie);
+ switch (vers) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ r.setOldFlag();
+ this.superRestoreState(r);
+ if (vers < 6) {
+ if (vers == 0) {
+ r.restoreInt();
+ }
+
+ x = r.restoreFloat();
+ y = r.restoreFloat();
+ z = r.restoreFloat();
+ this.scale(x, 1.0F, z);
+ }
+
+ if (r.restoreBoolean()) {
+ this.flags |= 4;
+ }
+
+ if (vers >= 4) {
+ this._farSidePortalName = r.restoreString();
+ }
+
+ this._farSidePortal = (Portal)r.restoreMaybeNull();
+ if (vers == 1) {
+ String n = r.restoreString();
+ if (!"".equals(n)) {
+ this.setName(n);
+ }
+ } else if (vers >= 3) {
+ if (vers >= 7) {
+ this._farSideWorld = URL.restore(r);
+ } else {
+ this._farSideWorld = URL.restore(r, ".world");
+ }
+
+ this._farSideRoomName = r.restoreString();
+ this._farx = r.restoreFloat();
+ this._fary = r.restoreFloat();
+ this._farz = r.restoreFloat();
+ this._fartheta = r.restoreFloat();
+ Material initialCover = Material.restore(r);
+ Material downloadCover = Material.restore(r);
+ if (initialCover != null) {
+ this.setMaterial(initialCover);
+ if (downloadCover != null && (initialCover.textureName == null || !initialCover.textureName.equals(downloadCover.textureName))) {
+ System.out
+ .println(
+ "Both initial and download covers, "
+ + initialCover.textureName
+ + " and "
+ + downloadCover.textureName
+ + ", in "
+ + this.getName()
+ + " -- using initial."
+ );
+ }
+ } else {
+ this.setMaterial(downloadCover);
+ }
+
+ if (vers >= 5) {
+ this._farSideIsPortal = r.restoreBoolean();
+ }
+ }
+ break;
+ case 8:
+ case 9:
+ super.restoreState(r);
+ this._farSideIsPortal = r.restoreBoolean();
+ if (vers >= 9) {
+ this._allowDownload = r.restoreBoolean();
+ }
+
+ this._farSidePortalName = r.restoreString();
+ this._farSidePortal = (Portal)r.restoreMaybeNull();
+ this._farSideWorld = URL.restore(r);
+ this._farSideRoomName = r.restoreString();
+ this._farx = r.restoreFloat();
+ this._fary = r.restoreFloat();
+ this._farz = r.restoreFloat();
+ this._fartheta = r.restoreFloat();
+ break;
+ default:
+ throw new TooNewException();
+ }
+
+ if (vers <= 4 && this._farSideRoomName != null && this._farSidePortal == null && this._farSidePortalName == null) {
+ this._farSideIsPortal = false;
+ }
+
+ this._userFarx = this._farx;
+ this._userFary = this._fary;
+ this._userFarz = this._farz;
+ this._userFartheta = this._fartheta;
+ }
+
+ @Override
+ public void postRestore(int version) {
+ super.postRestore(version);
+ if (this.getOwner() != null) {
+ this.addToRoom(this.getOwner());
+ Room r = this.getOwner().getRoom();
+ if (this._farSidePortal == null) {
+ this.reset();
+ } else {
+ this.newFarSide();
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ String to;
+ if (this._state == -1) {
+ to = "(not connected)";
+ } else {
+ if (this._farSideWorld != null) {
+ to = this._farSideWorld.toString();
+ } else {
+ to = "";
+ }
+
+ if (this._farSideRoom != null) {
+ to = to + "#" + this._farSideRoomName;
+ }
+
+ if (this._farSidePortalName != null) {
+ to = to + "#" + this._farSidePortalName;
+ }
+ }
+
+ return super.toString() + "[Connected To " + to + "]";
+ }
+
+ public Portal triggerLoad() {
+ if (this._farSideWorld != null && this._farSideRoomName != null) {
+ if (this._farSidePortal != null && !this._farSidePortal.isActive()) {
+ this.reset();
+ }
+
+ if (this._state == 0) {
+ this._state = 1;
+ World.load(this._farSideWorld, this);
+ }
+ }
+
+ return this;
+ }
+
+ @Override
+ public void loadedURLSelf(URLSelf o, URL url, String err) {
+ if (this.frozeFrameEvents) {
+ this.frozeFrameEvents = false;
+ Console.setFreezeFrameEvents(false);
+ }
+
+ if (this._state == 1) {
+ if (err == null && o instanceof World) {
+ World w = (World)o;
+ this.setFarSideRoom(w.getRoom(this._farSideRoomName));
+ if (this._farSideRoom != null) {
+ this._state = 2;
+ this.findFarSidePortal(true);
+ } else {
+ Object[] arguments = new Object[]{new String(this._farSideRoomName), new String("" + this._farSideWorld)};
+ Console.println(MessageFormat.format(Console.message("Cant-find-remote"), arguments));
+ this._state = -1;
+ }
+ } else {
+ if (err == null) {
+ err = "doesn't contain a World";
+ o.decRef();
+ }
+
+ String readable = TeleportAction.getReadableNameOfWorld(url);
+ this._state = -1;
+ if (this._allowDownload && !World.isProscribed(url, false)) {
+ Object[] arguments = new Object[]{new String(readable)};
+ Console.println(MessageFormat.format(Console.message("Dont-have-world"), arguments));
+ String packageName = TeleportAction.getPackageNameOfWorld(url);
+ if (packageName != null) {
+ NetUpdate.loadWorld(packageName, false);
+ }
+ }
+ }
+
+ this.updateVisible();
+ }
+ }
+}
diff --git a/NET/worlds/scape/PosableAction.java b/NET/worlds/scape/PosableAction.java
new file mode 100644
index 0000000..cab8508
--- /dev/null
+++ b/NET/worlds/scape/PosableAction.java
@@ -0,0 +1,74 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+public class PosableAction extends Action {
+ private String action = "wave";
+ private static Object classCookie = new Object();
+
+ public PosableAction() {
+ }
+
+ public PosableAction(String action) {
+ this.action = action;
+ this.rightMenuLabel = action;
+ }
+
+ @Override
+ public Persister trigger(Event e, Persister seqID) {
+ SuperRoot o = this.getOwner();
+ if (o instanceof PosableShape) {
+ ((PosableShape)o).animate(this.action);
+ } else if (o instanceof Drone) {
+ ((Drone)o).animate(this.action);
+ } else if (o instanceof Pilot) {
+ ((Pilot)o).animate(this.action);
+ }
+
+ return null;
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Action Name"));
+ } else if (mode == 1) {
+ ret = new String(this.action);
+ } else if (mode == 2) {
+ this.action = (String)value;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 1, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + "[action " + this.action + "]";
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(0, classCookie);
+ super.saveState(s);
+ s.saveString(this.action);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ this.action = r.restoreString();
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/PosableDrone.java b/NET/worlds/scape/PosableDrone.java
new file mode 100644
index 0000000..d6b6ec3
--- /dev/null
+++ b/NET/worlds/scape/PosableDrone.java
@@ -0,0 +1,197 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.BBAnimateDroneCommand;
+import NET.worlds.console.BlackBox;
+import NET.worlds.console.Console;
+import NET.worlds.core.IniFile;
+import NET.worlds.network.ObjID;
+import NET.worlds.network.URL;
+import NET.worlds.network.WorldServer;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.util.Enumeration;
+import java.util.Vector;
+
+public class PosableDrone extends Drone implements FrameHandler {
+ static PosableDroneLoader droneLoader = new PosableDroneLoader();
+ public static boolean threadDroneLoads = IniFile.gamma().getIniInt("ThreadDroneLoading", 0) == 1;
+ static boolean droneLoaderStarted = false;
+ private PosableShape pendingShape = null;
+ private static Object classCookie = new Object();
+
+ public void SetPendingShape(PosableShape ps) {
+ this.pendingShape = ps;
+ }
+
+ @Override
+ public boolean handle(FrameEvent evt) {
+ if (this.pendingShape != null) {
+ PosableShape ps = this.getInternalPosableShape();
+ if (ps != null) {
+ ps.detach();
+ }
+
+ this.add(this.pendingShape);
+ this.pendingShape = null;
+ }
+
+ return super.handle(evt);
+ }
+
+ public PosableDrone(ObjID objID, WorldServer serv, URL url) {
+ super(objID, serv);
+ this.makeFigure(url);
+ }
+
+ public PosableDrone(ObjID objID, WorldServer serv) {
+ super(objID, serv);
+ this.loadInit();
+ }
+
+ public PosableDrone() {
+ }
+
+ @Override
+ public void loadInit() {
+ this.makeFigure(PosableShape.getDefaultURL());
+ }
+
+ public synchronized URL getPosableShapeURL() {
+ PosableShape ps = this.getInternalPosableShape();
+ return ps == null ? null : ps.getURL();
+ }
+
+ @Override
+ public Drone setAvatarNow(URL url) {
+ if (!this.shouldBeMuted() && (url.endsWith(".rwx") || url.endsWith(".rwg"))) {
+ if (this.shouldBeForcedHuman()) {
+ url = PosableShape.getHuman(url);
+ }
+
+ url = PosableShape.getPermitted(url, this.getWorld());
+ PosableShape ps = this.getInternalPosableShape();
+ if (ps != null) {
+ if (url.equals(ps.getURL())) {
+ return this;
+ }
+
+ ps.detach();
+ }
+
+ this.makeFigure(url);
+ return this;
+ } else {
+ return super.setAvatarNow(url);
+ }
+ }
+
+ public void makeFigure(URL url) {
+ boolean isPilot = false;
+ if (Console.getActive() != null && Console.getActive().getPilot() != null && Console.getActive().getPilot().hasContents()) {
+ isPilot = Console.getActive().getPilot().contentsContain(this);
+ }
+
+ if (!isPilot) {
+ isPilot = this.isPilotDrone(url);
+ }
+
+ boolean loadAsynchronously = false;
+
+ try {
+ if (!PosableDroneLoader.avatarExistsLocally(url)) {
+ loadAsynchronously = true;
+ } else {
+ loadAsynchronously = !isPilot && !url.toString().equals(PosableShape.getDefaultURL().toString());
+ }
+ } catch (MalformedURLException var5) {
+ loadAsynchronously = false;
+ }
+
+ if (loadAsynchronously && threadDroneLoads) {
+ if (!droneLoaderStarted) {
+ droneLoaderStarted = true;
+ Thread t = new Thread(droneLoader, "DroneLoaderDaemon");
+ t.setDaemon(true);
+ t.setPriority(1);
+ t.start();
+ }
+
+ droneLoader.load(this, url);
+ } else {
+ PosableShape ps;
+ if (VehicleShape.isVehicle(url)) {
+ ps = new VehicleShape(url);
+ } else {
+ ps = new PosableShape(url);
+ }
+
+ ps.setVisible(true);
+ ps.setBumpable(false);
+ if (!this.isPilotDrone(url)) {
+ ps.enableLOD(true);
+ }
+
+ this.add(ps);
+ }
+ }
+
+ public PosableShape getInternalPosableShape() {
+ Enumeration e = this.getContents();
+
+ while (e.hasMoreElements()) {
+ Object o = e.nextElement();
+ if (o instanceof PosableShape) {
+ return (PosableShape)o;
+ }
+ }
+
+ return null;
+ }
+
+ public boolean isPilotDrone(URL url) {
+ return Console.getActive() != null && Console.getActive().pendingPilot.equals(url.toString());
+ }
+
+ @Override
+ public float animate(String action) {
+ super.animate(action);
+ BlackBox.getInstance().submitEvent(new BBAnimateDroneCommand(this.getName(), action));
+ PosableShape ps = this.getInternalPosableShape();
+ return ps != null ? ps.animate(action) : 0.0F;
+ }
+
+ @Override
+ public Vector getAnimationList() {
+ PosableShape ps = this.getInternalPosableShape();
+ return ps != null ? ps.getAnimationList() : super.getAnimationList();
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(2, classCookie);
+ super.saveState(s);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ int vers = r.restoreVersion(classCookie);
+ switch (vers) {
+ case 0:
+ case 1:
+ if (vers == 0) {
+ this.restoreStateDrone(r);
+ } else {
+ super.restoreState(r);
+ }
+
+ r.setOldFlag();
+ this.makeFigure(URL.make("avatar:" + r.restoreString() + ".rwx"));
+ break;
+ case 2:
+ super.restoreState(r);
+ break;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/PosableDroneLoader.java b/NET/worlds/scape/PosableDroneLoader.java
new file mode 100644
index 0000000..191ef6d
--- /dev/null
+++ b/NET/worlds/scape/PosableDroneLoader.java
@@ -0,0 +1,84 @@
+package NET.worlds.scape;
+
+import NET.worlds.core.Archive;
+import NET.worlds.network.URL;
+import java.net.MalformedURLException;
+import java.util.Enumeration;
+import java.util.Vector;
+
+public class PosableDroneLoader implements Runnable {
+ static final boolean debug = false;
+ DroneLoader loader;
+ private static boolean useCachedFiles = URL.usingCachedAvatars();
+ private Vector droneList = new Vector();
+
+ PosableDroneLoader() {
+ }
+
+ public static boolean usingCache() {
+ return useCachedFiles;
+ }
+
+ public static PendingDrone makePendingDrone(PosableDrone _drone, URL _url) {
+ return (PendingDrone)(useCachedFiles ? new PendingCacheDrone(_drone, _url) : new PendingDrone(_drone, _url));
+ }
+
+ public void load(PosableDrone _drone, URL _url) {
+ PendingDrone pd = makePendingDrone(_drone, _url);
+ this.droneList.addElement(pd);
+ if (this.loader != null) {
+ this.loader.wakeUp();
+ }
+ }
+
+ public boolean isPending(PosableDrone _drone, URL _url) {
+ Vector listCopy = (Vector)this.droneList.clone();
+ Enumeration enums = listCopy.elements();
+
+ while (enums.hasMoreElements()) {
+ PendingDrone pd = (PendingDrone)enums.nextElement();
+ if (pd.getUrl().toString().equals(_url.toString()) && pd.getDrone().toString().equals(_drone.toString())) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ @Override
+ public void run() {
+ this.loader = new DroneLoader();
+
+ while (true) {
+ this.loader.load(this.droneList);
+ }
+ }
+
+ public static String getAvatarBaseName(URL pUrl) {
+ String s = null;
+ int dot = pUrl.getAbsolute().indexOf(46);
+ if (dot != -1) {
+ s = pUrl.getAbsolute().substring(7, dot);
+ }
+
+ return s;
+ }
+
+ public static boolean avatarExistsLocally(URL pUrl) throws MalformedURLException {
+ if (useCachedFiles) {
+ return false;
+ } else if (pUrl.toString().equals(PosableShape.getDefaultURL().toString())) {
+ return true;
+ } else if (!pUrl.getAbsolute().substring(0, 7).equals("avatar:")) {
+ throw new MalformedURLException("Not an avatar URL");
+ } else {
+ String s = getAvatarBaseName(pUrl);
+ if (s == null) {
+ throw new MalformedURLException("No file extension");
+ } else {
+ URL realFile = URL.make(pUrl, s + ".bod");
+ return Archive.exists(realFile.unalias());
+ }
+ }
+ }
+}
diff --git a/NET/worlds/scape/PosableShape.java b/NET/worlds/scape/PosableShape.java
new file mode 100644
index 0000000..7ed5610
--- /dev/null
+++ b/NET/worlds/scape/PosableShape.java
@@ -0,0 +1,1331 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.AvMenu;
+import NET.worlds.console.Console;
+import NET.worlds.console.DefaultConsole;
+import NET.worlds.core.IniFile;
+import NET.worlds.core.ServerTableManager;
+import NET.worlds.core.Std;
+import NET.worlds.core.Timer;
+import NET.worlds.core.TimerCallback;
+import NET.worlds.network.Cache;
+import NET.worlds.network.CacheFile;
+import NET.worlds.network.NetUpdate;
+import NET.worlds.network.URL;
+import NET.worlds.network.WorldServer;
+import java.awt.Color;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.net.MalformedURLException;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+public class PosableShape extends Shape implements FrameHandler, Prerenderable, MouseDownHandler, ShapeLoaderListener, TimerCallback {
+ protected int figureType = -1;
+ private float closestView = 10000.0F;
+ private int farViewCount;
+ private Vector<String> animationList;
+ private boolean COG;
+ private boolean setPrepFigure = true;
+ private boolean runPrepFigure = this.setPrepFigure;
+ private static URL defaultURL = URL.make("avatar:aura.0PG.rwg");
+ protected DroneAnimator animator = null;
+ private boolean recomputeHeight = false;
+ private boolean firstURL = true;
+ private Shape subparts;
+ public static Color[] colorTable = new Color[]{
+ new Color(0, 0, 0),
+ new Color(51, 102, 204),
+ new Color(234, 162, 115),
+ new Color(255, 102, 51),
+ new Color(255, 153, 204),
+ new Color(139, 232, 0),
+ new Color(43, 131, 0),
+ new Color(51, 51, 153),
+ new Color(145, 51, 204),
+ new Color(153, 204, 255),
+ new Color(204, 51, 102),
+ new Color(0, 204, 102),
+ new Color(255, 204, 102),
+ new Color(102, 102, 102),
+ new Color(254, 123, 26),
+ new Color(255, 51, 153),
+ new Color(188, 51, 204),
+ new Color(204, 0, 38),
+ new Color(118, 0, 0),
+ new Color(153, 102, 51),
+ new Color(196, 196, 196),
+ new Color(204, 153, 255),
+ new Color(255, 255, 255),
+ new Color(255, 179, 2),
+ new Color(247, 227, 2),
+ new Color(255, 255, 153)
+ };
+ private Hashtable<Object, Vector<Object>> actions;
+ private int scanPos;
+ private static Material origMat = new Material(null);
+ public static String base64 = "-0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+";
+ private static String[] permittedList = ServerTableManager.instance().getTable("permittedList");
+ private static String[] faceList = ServerTableManager.instance().getTable("faceList");
+ private static String[] humanList = ServerTableManager.instance().getTable("humanList");
+ private static String[] secretList = ServerTableManager.instance().getTable("secretList");
+ private static Hashtable<String, String> permittedHash = new Hashtable<String, String>();
+ private static Vector<String> permittedNames = new Vector<String>();
+ private static Vector<String> faceNames = new Vector<String>();
+ private static Hashtable<String, String> humanHash = new Hashtable<String, String>();
+ private static Hashtable<String, Vector<String>> worldHash = new Hashtable<String, Vector<String>>();
+ private static Hashtable<String, String> secretNames = new Hashtable<String, String>();
+ private static Hashtable<String, String> faceTextures = new Hashtable<String, String>();
+ static boolean gotServerAvatarList;
+ static boolean serverAvatarListError;
+ private Enumeration<String> animations;
+ private boolean doLOD = false;
+ protected int expressionStart;
+ protected int nextChange;
+ protected Vector<PosableShape.TimedMatChange> expressionChanges;
+ private static Object classCookie;
+
+ static {
+ if (!NetUpdate.isInternalVersion()) {
+ for (int i = 0; i < secretList.length; i++) {
+ secretNames.put(secretList[i], secretList[i]);
+ }
+ }
+
+ for (int i = 0; i < permittedList.length; i += 2) {
+ if (secretNames.get(permittedList[i]) == null) {
+ permittedNames.addElement(permittedList[i]);
+ if (permittedList[i + 1].indexOf("DgT") >= 0) {
+ faceNames.addElement(permittedList[i]);
+ }
+ }
+
+ if (permittedList[i + 1] != null) {
+ permittedHash.put(permittedList[i], permittedList[i + 1]);
+ }
+ }
+
+ for (int i = 1; i < humanList.length; i += 2) {
+ humanHash.put(humanList[i - 1], humanList[i]);
+ }
+
+ for (int i = 0; i < faceList.length; i += 2) {
+ faceTextures.put(faceList[i], faceList[i + 1]);
+ }
+
+ gotServerAvatarList = false;
+ serverAvatarListError = false;
+ classCookie = new Object();
+ }
+
+ public static URL getDefaultURL() {
+ return defaultURL;
+ }
+
+ public PosableShape(URL url) {
+ this.setURL(url);
+ }
+
+ public PosableShape(URL url, boolean isAW) {
+ this.setPrepFigure = isAW;
+ this.runPrepFigure = this.setPrepFigure;
+ this.setURL(url);
+ }
+
+ public PosableShape() {
+ }
+
+ @Override
+ public void loadInit() {
+ this.setURL(defaultURL);
+ }
+
+ @Override
+ public void markVoid() throws ClassCastException {
+ if (this.animator != null) {
+ this.animator.endanimations();
+ if (this.figureType != -1) {
+ this.animator.delayedDeltype(this.figureType);
+ }
+ }
+
+ this.animator = null;
+ this.getRoom().removePrerenderHandler(this);
+ super.markVoid();
+ }
+
+ @Override
+ public synchronized void recursiveAddRwChildren(WObject parent) {
+ if (!this.hasClump()) {
+ super.recursiveAddRwChildren(parent);
+ this.getRoom().addPrerenderHandler(this);
+ if (this.isFullyLoaded() && this.figureType != -1) {
+ DroneAnimator.addtype(this.figureType);
+ if (this.runPrepFigure) {
+ DroneAnimator.prepFigure(this, this.COG);
+ }
+
+ this.animator = new DroneAnimator();
+ }
+ }
+ }
+
+ @Override
+ public void notifyShapeLoaded(Shape s) {
+ this.recomputeHeight = true;
+ }
+
+ @Override
+ public Transform getObjectToWorldMatrix() {
+ return this.clumpID != 0 ? this.getJointedObjectToWorldMatrix(Transform.make()) : super.getObjectToWorldMatrix();
+ }
+
+ public static int getFigureType(URL url) {
+ String bodyType = getBodyType(url);
+ return bodyType == null ? -1 : DroneAnimator.getnameindex(bodyType);
+ }
+
+ public static int getFigureType(String bodyType) {
+ bodyType = getBodyType(bodyType);
+ return bodyType == null ? -1 : DroneAnimator.getnameindex(bodyType);
+ }
+
+ protected void download(URL pUrl) {
+ PendingDrone pd = PosableDroneLoader.makePendingDrone(null, pUrl);
+ Enumeration<String> e = getComponentAvatars(pd.getUrl());
+ if (e != null) {
+ while (e.hasMoreElements()) {
+ String avURL = e.nextElement();
+ pd.download(URL.make(avURL));
+ }
+ }
+ }
+
+ @Override
+ public synchronized void setURL(URL newName) {
+ if (newName != this.url && (newName == null || !newName.equals(this.url))) {
+ if (newName == null || !newName.toString().startsWith("avatar:lod")) {
+ if (newName != null) {
+ this.download(newName);
+ int newType = getFigureType(newName);
+ if (newType != this.figureType) {
+ if (this.animator != null) {
+ this.animator.endanimations();
+ if (this.figureType != -1) {
+ this.animator.delayedDeltype(this.figureType);
+ }
+ }
+
+ this.animator = null;
+ this.figureType = newType;
+ this.animationList = null;
+ }
+ }
+
+ this.setBaseLODURL(newName);
+ if (forceLODLevel != -1 && this.numDetailLevels > 0 && this.doLOD) {
+ this.setLOD(0.0F);
+ return;
+ }
+ }
+
+ this.removeSubparts();
+ if (newName != null && newName.getAbsolute().startsWith("avatar:")) {
+ try {
+ this.createSubparts(newName);
+ } catch (MalformedURLException var3) {
+ System.out.println("Received bogus PosableShape URL: " + newName);
+ return;
+ }
+ }
+
+ super.setURL(newName);
+ }
+ }
+
+ private String scanName(String s) {
+ int start = this.scanPos;
+
+ char c;
+ while ((c = s.charAt(this.scanPos)) >= 'a' && c <= 'z' || c == '_') {
+ this.scanPos++;
+ }
+
+ return s.substring(start, this.scanPos);
+ }
+
+ public static String readName(String s, int pos) {
+ int start = pos;
+
+ char c;
+ try {
+ while ((c = s.charAt(pos)) >= 'a' && c <= 'z' || c == '_') {
+ pos++;
+ }
+ } catch (StringIndexOutOfBoundsException var4) {
+ }
+
+ return s.substring(start, pos);
+ }
+
+ private int scanInt(String s) {
+ int start = this.scanPos;
+
+ int val;
+ char c;
+ for (val = 0; (c = s.charAt(this.scanPos)) >= '0' && c <= '9'; this.scanPos++) {
+ val = 10 * val + (c - '0');
+ }
+
+ return val;
+ }
+
+ private static Material scanTexture(String name, int frame) {
+ if (frame <= 0) {
+ name = "avatar:" + name + ".cmp";
+ } else {
+ name = "avatar:" + name + frame + "s*.mov";
+ }
+
+ Material m = new Material(0.32F, 0.55F, 0.0F, colorTable[3], null, 1.0F, true, false);
+ m.loadTexture(URL.make(name));
+ return m;
+ }
+
+ public static Material readTexture(String s, int p) {
+ int frame = 0;
+
+ char c;
+ while ((c = s.charAt(p)) >= '0' && c <= '9') {
+ frame = 10 * frame + (c - '0');
+ p++;
+ }
+
+ return scanTexture(readName(s, p), frame);
+ }
+
+ public static boolean isValidTexture(String s) {
+ int len = s.length();
+ int i = 0;
+
+ char c;
+ while (i < len && (c = s.charAt(i)) >= '0' && c <= '9') {
+ i++;
+ }
+
+ while (i < len) {
+ if (((c = s.charAt(i)) < 'a' || c > 'z') && c != '_') {
+ return false;
+ }
+
+ i++;
+ }
+
+ return true;
+ }
+
+ private static int scanBase64(char c) {
+ int i = base64.indexOf(c);
+ return i < 0 ? 0 : i;
+ }
+
+ public static Material readColor(String s, int p) {
+ char c = s.charAt(p++);
+ Material m = null;
+ if (c == '_') {
+ int color = s.charAt(p++) - 'A';
+ if (color >= 0 && color < colorTable.length) {
+ m = new Material(0.32F, 0.55F, 0.0F, colorTable[color], null, 1.0F, true, false);
+ } else {
+ m = origMat;
+ }
+ } else {
+ int r = 4 * scanBase64(c);
+ int g = 4 * scanBase64(s.charAt(p++));
+ int b = 4 * scanBase64(s.charAt(p++));
+ m = new Material(0.32F, 0.55F, 0.0F, new Color(r, g, b), null, 1.0F, true, false);
+ }
+
+ return m;
+ }
+
+ private Material scanColor(String s) {
+ Material m = readColor(s, this.scanPos);
+ if (s.charAt(this.scanPos) == '_') {
+ this.scanPos += 2;
+ } else {
+ this.scanPos += 3;
+ }
+
+ return m;
+ }
+
+ private float getScale(char c) {
+ if (c >= 'a' && c <= 'z') {
+ return 1.0F - (c - 'a' + 1) * 0.025615385F;
+ } else {
+ return c >= 'A' && c <= 'Z' ? 1.0F / (1.0F - (c - 'A' + 1) * 0.025615385F) : 1.0F;
+ }
+ }
+
+ private Material getMat(char c, Vector<Material> mats) {
+ int matNum = c - 'a';
+ if (matNum < mats.size()) {
+ Material m = mats.elementAt(matNum);
+ return m == origMat ? origMat : (Material)m.clone();
+ } else {
+ return null;
+ }
+ }
+
+ private Shape getLimb(String s, String bodyType, int pos, int partNum, Shape parent, Vector<Material> mats, boolean loadNow) {
+ int end = s.length() - 4;
+ if (bodyType == null) {
+ if (parent instanceof PosableShape) {
+ bodyType = "";
+ } else {
+ bodyType = Shape.getBodBase(parent.getURL());
+ if (parent.getURL().toString().indexOf("lod/") != -1) {
+ bodyType = "lod/" + bodyType;
+ }
+ }
+ }
+
+ Shape shape = new Shape();
+ Shape subshape = shape;
+ shape.setURL(URL.make("avatar:" + bodyType + partNum / 10 + partNum % 10 + ".bod"));
+ int clumpsUsed = 0;
+ Material lastMat = null;
+ int delay = 0;
+ int lastTime = 0;
+ String actName = null;
+ boolean haveAddedChange = false;
+ if (pos > 0) {
+ this.scanPos = pos + 1;
+
+ while (true) {
+ char c = s.charAt(this.scanPos++);
+ if (c >= 'A' && c <= 'Z') {
+ if (c == 'G') {
+ int num = this.scanInt(s);
+ if (num <= 0 || num > 99) {
+ num = partNum;
+ }
+
+ bodyType = this.scanName(s);
+ if (bodyType.equals("")) {
+ break;
+ }
+
+ subshape.setURL(URL.make("avatar:" + bodyType + num / 10 + num % 10 + ".bod"));
+ } else if (c == 'S') {
+ char xScale = s.charAt(this.scanPos++);
+ char yScale = s.charAt(this.scanPos++);
+ char zScale = s.charAt(this.scanPos++);
+ if (xScale == 'Z' && yScale == 'Z' && zScale == 'Z') {
+ this.runPrepFigure = false;
+ }
+
+ subshape.scale(this.getScale(xScale), this.getScale(yScale), this.getScale(zScale));
+ } else if (c != 'Q') {
+ if (c == 'C') {
+ assert false;
+ } else if (c == 'D') {
+ delay += (int)(1000.0 * (Math.pow(1.0932, scanBase64(s.charAt(this.scanPos++))) - 0.9F));
+ } else if (c == 'A') {
+ actName = this.scanName(s);
+ this.animationList = null;
+ } else {
+ if (c != 'T' && c != 'C') {
+ this.scanPos--;
+ break;
+ }
+
+ System.out.println("Illegal av " + this.url);
+ }
+ }
+ } else if (c >= 'a') {
+ Material m = this.getMat(c, mats);
+ if (m != null) {
+ if (delay == 0) {
+ delay = 50;
+ }
+
+ lastTime += delay;
+ if (lastMat != null) {
+ if (!haveAddedChange) {
+ haveAddedChange = true;
+ this.addChange(lastTime - delay, lastMat, subshape);
+ }
+
+ this.addChange(lastTime, m, subshape);
+ }
+
+ if (m != origMat) {
+ subshape.setMaterial(m);
+ }
+
+ lastMat = m;
+ delay = 0;
+ }
+ } else {
+ if (c < '0' || c > '9') {
+ break;
+ }
+
+ this.scanPos--;
+ int clumpNum = this.scanInt(s) - clumpsUsed;
+ clumpsUsed++;
+ subshape = new SubclumpShape();
+ subshape.setURL(URL.make("system:subclump" + clumpNum));
+ shape.add(subshape);
+ lastMat = null;
+ haveAddedChange = false;
+ lastTime = 0;
+ delay = 0;
+ }
+
+ if (this.scanPos > end) {
+ this.scanPos = end;
+ return parent;
+ }
+ }
+ }
+
+ if (bodyType.equals("")) {
+ return parent;
+ } else {
+ shape.addLoadListener(this);
+ if (ProgressiveAdder.get().enabled() && !loadNow) {
+ ProgressiveAdder.get().scheduleForAdd(parent, shape);
+ } else {
+ parent.add(shape);
+ }
+
+ if (this.subparts == null) {
+ this.subparts = shape;
+ }
+
+ return shape;
+ }
+ }
+
+ private void addChange(int when, Material mat, Shape s) {
+ PosableShape.TimedMatChange t = new PosableShape.TimedMatChange();
+ t.when = when;
+ t.mat = mat;
+ t.limb = s;
+ mat.setKeepLoaded(true);
+ int i = 0;
+ if (this.expressionChanges == null) {
+ this.expressionChanges = new Vector<PosableShape.TimedMatChange>();
+ this.expressionStart = Std.getRealTime();
+ this.nextChange = 0;
+ } else {
+ for (i = this.expressionChanges.size(); i > 0; i--) {
+ PosableShape.TimedMatChange o = this.expressionChanges.elementAt(i - 1);
+ if (when >= o.when) {
+ break;
+ }
+ }
+ }
+
+ this.expressionChanges.insertElementAt(t, i);
+ }
+
+ public static Enumeration<String> getComponentAvatars(URL pUrl) {
+ if (pUrl == null) {
+ return null;
+ } else {
+ Vector<String> v = new Vector<String>();
+ String urlString = pUrl.getAbsolute();
+ if (urlString.startsWith("avatar:") && urlString.endsWith(".rwg")) {
+ String baseAv = urlString.substring(7, urlString.indexOf(46));
+ v.addElement("avatar:" + baseAv + ".rwg");
+ int pos = urlString.indexOf(46);
+ int len = urlString.length() - 4;
+
+ label82:
+ while (pos < len) {
+ char c = urlString.charAt(pos++);
+ if (c >= 'A' && c <= 'Z') {
+ switch (c) {
+ case 'A':
+ case 'Q':
+ case 'T':
+ default:
+ break;
+ case 'C':
+ c = urlString.charAt(pos++);
+ if (c == '_') {
+ pos++;
+ } else {
+ pos += 2;
+ }
+ break;
+ case 'D':
+ pos++;
+ break;
+ case 'G':
+ while (pos < len) {
+ c = urlString.charAt(pos);
+ if (c < '0' || c > '9') {
+ break;
+ }
+
+ pos++;
+ }
+
+ String bodyType = "";
+
+ while (true) {
+ if (pos < len) {
+ c = urlString.charAt(pos);
+ if ((c < '0' || c > '9') && c >= 'a' && c <= 'z') {
+ bodyType = bodyType + c;
+ pos++;
+ continue;
+ }
+ }
+
+ if (bodyType != "" && bodyType.length() > 1) {
+ v.addElement("avatar:" + bodyType + ".rwg");
+ }
+ continue label82;
+ }
+ case 'S':
+ pos += 3;
+ }
+ }
+ }
+
+ return v.elements();
+ } else {
+ return null;
+ }
+ }
+ }
+
+ public static int skipLimb(String s, int pos) {
+ int len = s.length() - 4;
+
+ while (pos < len) {
+ char c = s.charAt(pos++);
+ if (c >= 'A' && c <= 'Z') {
+ switch (c) {
+ case 'A':
+ case 'G':
+ case 'Q':
+ case 'T':
+ break;
+ case 'C':
+ c = s.charAt(pos++);
+ if (c == '_') {
+ pos++;
+ } else {
+ pos += 2;
+ }
+ break;
+ case 'D':
+ pos++;
+ break;
+ case 'S':
+ pos += 3;
+ break;
+ default:
+ return pos - 1;
+ }
+ } else if ((c < 'a' || c > 'z') && (c < '0' || c > '9')) {
+ break;
+ }
+ }
+
+ return -1;
+ }
+
+ private String findStarts(String s, int end, int[] offs, String bodyType, Vector<Material> mats) {
+ String lastTextureName = bodyType;
+
+ while (this.scanPos < end) {
+ char section = s.charAt(this.scanPos);
+ if (section < 'A' || section > 'Z') {
+ return s;
+ }
+
+ offs[section - 'A'] = this.scanPos++;
+
+ while (this.scanPos < end) {
+ char c = s.charAt(this.scanPos++);
+ if (c < 'A' || c > 'Z') {
+ if ((c < '0' || c > '9') && (c < 'a' || c > 'z')) {
+ return s.substring(0, this.scanPos - 1) + ".rwg";
+ }
+ } else if (c == 'G') {
+ this.scanInt(s);
+ this.scanName(s);
+ } else if (c == 'S') {
+ this.scanPos += 3;
+ } else if (c != 'Q') {
+ if (c == 'C' || c == 'T') {
+ int start = this.scanPos - 1;
+ char letter = (char)(97 + mats.size());
+ Material mat;
+ if (c == 'C') {
+ mat = this.scanColor(s);
+ } else {
+ int num = this.scanInt(s);
+ String name = this.scanName(s);
+ if (name.equals("")) {
+ name = lastTextureName;
+ } else {
+ lastTextureName = name;
+ }
+
+ mat = scanTexture(name, num);
+ }
+
+ mats.addElement(mat);
+ s = s.substring(0, start) + 'Q' + letter + s.substring(this.scanPos);
+ int cutLen = this.scanPos - start - 2;
+ this.scanPos -= cutLen;
+ end -= cutLen;
+ } else if (c == 'D') {
+ this.scanPos++;
+ } else {
+ if (c != 'A') {
+ this.scanPos--;
+ break;
+ }
+
+ this.scanName(s);
+ }
+ }
+ }
+ }
+
+ return s;
+ }
+
+ public static Vector<String> getPermittedNames() {
+ return permittedNames;
+ }
+
+ public static String[] getPermittedList() {
+ return permittedList;
+ }
+
+ public static void downloadPermittedNames() {
+ if (!gotServerAvatarList) {
+ serverAvatarListError = false;
+ WorldServer w = Pilot.getActive().getServer();
+ if (w != null && w.getGalaxy() != null) {
+ String avatarList = Console.getActive().getScriptServer() + "getavlist.pl?u=" + w.getGalaxy().getChatname();
+ if (w.getGalaxy().getSerialNum() != null) {
+ avatarList = avatarList + "&s=" + w.getGalaxy().getSerialNum();
+ }
+
+ URL avatarListURL = URL.make(avatarList);
+ CacheFile cf = Cache.getFile(avatarListURL, true);
+ cf.waitUntilLoaded();
+ if (!cf.error()) {
+ permittedNames.removeAllElements();
+ humanHash.clear();
+ worldHash.clear();
+
+ try {
+ RandomAccessFile f = new RandomAccessFile(cf.getLocalName(), "r");
+
+ while (f.getFilePointer() < f.length()) {
+ String line = f.readLine();
+ if (!line.startsWith("//")) {
+ StringTokenizer st = new StringTokenizer(line);
+ if (st.countTokens() > 2) {
+ String name = st.nextToken();
+ permittedNames.addElement(name);
+ String gender = st.nextToken();
+ if (gender.equals("m") || gender.equals("f")) {
+ humanHash.put(name, gender);
+ }
+
+ Vector<String> worldList = new Vector<String>();
+
+ while (st.hasMoreTokens()) {
+ worldList.addElement(st.nextToken());
+ }
+
+ worldHash.put(name, worldList);
+ }
+ }
+ }
+
+ f.close();
+ } catch (Exception var10) {
+ System.out.println("Error parsing avatar list: " + var10.toString());
+ serverAvatarListError = true;
+ return;
+ }
+
+ gotServerAvatarList = true;
+ Console c = Console.getActive();
+ if (c instanceof DefaultConsole) {
+ DefaultConsole dc = (DefaultConsole)c;
+ dc.getAvatarMenu().rebuildVIPMenu();
+ }
+
+ if (c.getPilot() != null) {
+ c.getPilot().resetAvatarNow();
+ }
+
+ AvMenu.rebuildHeadList();
+ } else {
+ serverAvatarListError = true;
+ }
+ }
+ }
+ }
+
+ public static URL getPermitted(URL in, World world) {
+ if (in.endsWith(".mov")) {
+ return in;
+ } else if (NetUpdate.isInternalVersion()) {
+ return in;
+ } else if (!gotServerAvatarList && !serverAvatarListError) {
+ return in;
+ } else if (serverAvatarListError) {
+ return validateAvatar(in.getAbsolute()) ? in : getDefAv();
+ } else {
+ Enumeration<String> e = getComponentAvatars(in);
+
+ while (e != null && e.hasMoreElements()) {
+ String baseAv = e.nextElement();
+ String s = getBodyType(URL.make(baseAv));
+ if (s == null) {
+ return getDefAv();
+ }
+
+ Vector<String> allowedWorlds = worldHash.get(s);
+ if (allowedWorlds == null) {
+ return getDefAv();
+ }
+
+ boolean worldOK = false;
+ Enumeration<String> we = allowedWorlds.elements();
+
+ while (true) {
+ if (we.hasMoreElements()) {
+ String thisWorld = we.nextElement();
+ if (thisWorld == null) {
+ return getDefAv();
+ }
+
+ if (thisWorld.equals("all")) {
+ worldOK = true;
+ } else {
+ thisWorld = thisWorld.replace('_', ' ').toLowerCase().trim();
+ if (world == null) {
+ worldOK = true;
+ continue;
+ }
+
+ if (!thisWorld.equals(world.toString().toLowerCase().trim())) {
+ continue;
+ }
+
+ worldOK = true;
+ }
+ }
+
+ if (!worldOK) {
+ return getDefAv();
+ }
+ break;
+ }
+ }
+
+ return in;
+ }
+ }
+
+ public static Vector<String> getFaceNames() {
+ return faceNames;
+ }
+
+ public static URL getAvURL(String bodyType) {
+ Object newName = permittedHash.get(bodyType);
+ return newName instanceof String ? URL.make("avatar:" + (String)newName) : null;
+ }
+
+ public static boolean validateAvatar(String av) {
+ System.out.println("Validating " + av);
+ String baseAv = getBodyType(URL.make(av));
+ return baseAv == null ? false : permittedHash.get(baseAv) != null;
+ }
+
+ public static String convertLODToParent(String bodyType) {
+ String result = bodyType;
+ if (bodyType.startsWith("lod/")) {
+ result = bodyType.substring(4, bodyType.length() - 1);
+ }
+
+ return result;
+ }
+
+ public static String getBodyType(URL url) {
+ if (url == null) {
+ return null;
+ } else {
+ String str = url.getAbsolute();
+ if (str.startsWith("avatar:") && (str.endsWith(".rwg") || str.endsWith(".RWG")) && str.charAt(7) != '.') {
+ int pos = str.indexOf(".", 7);
+ String bodyType = str.substring(7, pos).toLowerCase();
+ bodyType = convertLODToParent(bodyType);
+ if (str.charAt(pos + 1) != '0') {
+ bodyType = getBodyType(bodyType);
+ }
+
+ return bodyType;
+ } else {
+ return null;
+ }
+ }
+ }
+
+ static URL getDefAv() {
+ return URL.make(IniFile.override().getIniString("DefaultArticAv", "avatar:willy.rwg"));
+ }
+
+ public static URL getHuman(URL url) {
+ if (url.endsWith(".mov")) {
+ return HoloDrone.getHuman(url);
+ } else {
+ String s = getBodyType(url);
+ if (s == null) {
+ return getDefAv();
+ } else {
+ String gender = humanHash.get(s);
+ if (gender == null) {
+ return getDefAv();
+ } else {
+ URL def = URL.make("avatar:" + s + ".rwg");
+ String str = url.getAbsolute();
+ int pos = str.indexOf(".0EC_");
+ if (pos >= 0 && str.length() >= pos + 7 && "_AC".indexOf(str.charAt(pos + 5)) >= 0) {
+ if (!gender.equals("m")
+ || str.indexOf("yank") < 0
+ || str.regionMatches(pos + 6, "TyankshirtC_", 0, 12) && str.regionMatches(pos + 19, "C-2bTyankstripe", 0, 15)) {
+ pos = str.lastIndexOf("HDgT2");
+ if (pos >= 0 && str.length() >= pos + 7) {
+ String faceGender = humanHash.get(readName(str, pos + 5));
+ if (faceGender != null && faceGender.equals(gender)) {
+ pos = str.lastIndexOf("NS");
+ if (pos >= 0 && str.length() >= pos + 3 && "0abcdABCD".indexOf(str.charAt(pos + 2)) >= 0) {
+ pos += 5;
+ if (str.length() < pos + 2) {
+ return def;
+ } else {
+ if (str.charAt(pos) == 'G') {
+ String headGender = humanHash.get(readName(str, pos + 1));
+ if (headGender == null || !headGender.equals(gender)) {
+ return def;
+ }
+ }
+
+ return url;
+ }
+ } else {
+ return def;
+ }
+ } else {
+ return def;
+ }
+ } else {
+ return def;
+ }
+ } else {
+ return def;
+ }
+ } else {
+ return def;
+ }
+ }
+ }
+ }
+ }
+
+ public URL getHuman() {
+ return getHuman(this.getURL());
+ }
+
+ public static String getBodyType(String basename) {
+ String str = permittedHash.get(basename);
+ if (str != null) {
+ basename = str.substring(0, str.indexOf("."));
+ }
+
+ return basename;
+ }
+
+ public static int getMatPosition(String str, char type) {
+ int index = "abcdef".indexOf(type);
+ if (index >= 0) {
+ int p = str.indexOf(".0E");
+ if (p >= 0) {
+ p += 3;
+
+ for (int i = 0; i < index; i++) {
+ p = skipMat(str, p);
+ }
+ }
+
+ return p;
+ } else {
+ int p = str.indexOf(".0E");
+ if (p >= 0) {
+ for (p += 2; p >= 0; p = skipLimb(str, p)) {
+ if (str.charAt(p++) == type) {
+ return p;
+ }
+ }
+ }
+
+ return p;
+ }
+ }
+
+ public static String getCurrentAvCustomizable() {
+ URL av = Pilot.getActive().getSourceURL();
+ String str = av.getAbsolute();
+ if (str.startsWith("avatar:") && (str.endsWith(".rwg") || str.endsWith(".RWG")) && str.charAt(7) != '.') {
+ int pos = str.indexOf(".", 7);
+ if (!str.regionMatches(pos, ".0E", 0, 3)) {
+ av = getAvURL(str.substring(7, pos).toLowerCase());
+ if (av == null) {
+ if (!str.substring(pos).equalsIgnoreCase(".rwg")) {
+ Console.println(Console.message("cant-cust-av"));
+ return null;
+ }
+
+ str = "avatar:" + str.substring(7, pos) + ".0EC__C__C__C__C__C__" + "PeBbLcMcOaRcUcVaWeXeYIeJeK" + "NS000QaHDgT2tonyT3T2T1Q0f.rwg";
+ } else {
+ str = av.getAbsolute();
+ }
+ }
+
+ return str;
+ } else {
+ Console.println(Console.message("non-cust-av"));
+ return null;
+ }
+ }
+
+ public static int skipMat(String s, int i) {
+ char c = s.charAt(i);
+ int matEnd = i;
+ if (c == 'C') {
+ c = s.charAt(i + 1);
+ if (c == '_') {
+ matEnd = i + 3;
+ } else {
+ matEnd = i + 4;
+ }
+ } else if (c == 'T') {
+ matEnd = i + 1;
+
+ while ((c = s.charAt(matEnd)) >= '0' && c <= '9') {
+ matEnd++;
+ }
+
+ while ((c = s.charAt(matEnd)) >= 'a' && c <= 'z') {
+ matEnd++;
+ }
+ } else if (c >= 'a' && c <= 'z') {
+ matEnd = i + 1;
+ }
+
+ return matEnd;
+ }
+
+ public static String getFace(String bodyType) {
+ Object face = faceTextures.get(bodyType);
+ return face != null ? (String)face : "1" + bodyType;
+ }
+
+ private void createSubparts(URL url) throws MalformedURLException {
+ String str = url.getAbsolute();
+ int len = str.length();
+ String bodyType = null;
+ this.runPrepFigure = this.setPrepFigure;
+ if (str.startsWith("avatar:") && (str.endsWith(".rwg") || str.endsWith(".RWG")) && str.charAt(7) != '.') {
+ this.scanPos = str.indexOf(".", 7);
+ bodyType = str.substring(7, this.scanPos).toLowerCase();
+ if (str.charAt(this.scanPos + 1) != '0') {
+ this.scanPos = len - 4;
+ Object newName = permittedHash.get(bodyType);
+ if (newName != null) {
+ str = (String)newName;
+ this.scanPos = 0;
+ bodyType = this.scanName(str);
+ if (str.charAt(this.scanPos) != '.') {
+ throw new MalformedURLException();
+ }
+
+ if (str.charAt(this.scanPos + 1) != '0') {
+ throw new MalformedURLException();
+ }
+
+ this.scanPos += 2;
+ }
+ } else {
+ this.scanPos += 2;
+ }
+ } else {
+ this.scanPos = 0;
+ str = ".rwg";
+ bodyType = "aura";
+ }
+
+ Vector<Material> mats = new Vector<Material>();
+ int[] offsets = new int[26];
+ str = this.findStarts(str, str.length() - 4, offsets, bodyType, mats);
+ if (this.subparts != null) {
+ throw new MalformedURLException();
+ } else {
+ Shape groi = this.getLimb(str, bodyType, offsets[15], 1, this, mats, true);
+ Shape back = this.getLimb(str, null, offsets[1], 2, groi, mats, false);
+ Shape neck = this.getLimb(str, null, offsets[13], 3, back, mats, false);
+ Shape head = this.getLimb(str, null, offsets[7], 4, neck, mats, false);
+ Shape lupa = this.getLimb(str, null, offsets[11], 11, back, mats, false);
+ Shape lfor = this.getLimb(str, null, offsets[12], 12, lupa, mats, false);
+ Shape lhan = this.getLimb(str, null, offsets[14], 13, lfor, mats, false);
+ Shape rupa = this.getLimb(str, null, offsets[17], 6, back, mats, false);
+ Shape rfor = this.getLimb(str, null, offsets[20], 7, rupa, mats, false);
+ Shape rhan = this.getLimb(str, null, offsets[21], 8, rfor, mats, false);
+ Shape lthi = this.getLimb(str, null, offsets[8], 19, groi, mats, false);
+ Shape lcal = this.getLimb(str, null, offsets[9], 20, lthi, mats, false);
+ Shape lfoo = this.getLimb(str, null, offsets[10], 21, lcal, mats, false);
+ Shape rthi = this.getLimb(str, null, offsets[22], 15, groi, mats, false);
+ Shape rcal = this.getLimb(str, null, offsets[23], 16, rthi, mats, false);
+ Shape rfoo = this.getLimb(str, null, offsets[24], 17, rcal, mats, false);
+ Shape tail = this.getLimb(str, null, offsets[25], 24, groi, mats, false);
+ }
+ }
+
+ protected void removeSubparts() {
+ if (this.subparts != null) {
+ this.subparts.discard();
+ this.subparts = null;
+ this.actions = null;
+ }
+ }
+
+ @Override
+ public void prerender(Camera cam) {
+ if (this.getVisible()) {
+ Point3Temp p = this.inCamSpace(cam);
+ boolean v = p != null && p.z > 1.0F && p.x < p.z && -p.x < p.z;
+ if (v) {
+ if (this.closestView > p.z) {
+ this.closestView = p.z;
+ }
+
+ if (p.z > 700.0F && ++this.farViewCount > 10) {
+ if (this.closestView > 400.0F) {
+ this.closestView = 400.0F;
+ }
+
+ this.farViewCount = 0;
+ }
+ }
+ }
+ }
+
+ public float animate(String action) {
+ if (this.animator == null) {
+ return 0.0F;
+ } else {
+ if (action.length() == 1) {
+ char lower = action.toLowerCase().charAt(0);
+ char upper = action.toUpperCase().charAt(0);
+ Vector<String> al = this.getAnimationList();
+ int len = al.size();
+
+ for (int i = 0; i < len; i++) {
+ String[] actionAliases = ServerTableManager.instance().getTable("actionAliases");
+ String displayName = al.elementAt(i);
+ if (actionAliases != null) {
+ for (int j = 0; j < actionAliases.length; j += 2) {
+ if (displayName.toLowerCase().equals(actionAliases[j].toLowerCase())) {
+ displayName = actionAliases[j + 1];
+ break;
+ }
+ }
+ }
+
+ char c = displayName.charAt(0);
+ if (c == lower || c == upper) {
+ action = al.elementAt(i);
+ break;
+ }
+ }
+ }
+
+ return this.performAnimationSequence(action);
+ }
+ }
+
+ @Override
+ public void timerDone() {
+ if (this.animations.hasMoreElements()) {
+ String nextAnim = this.animations.nextElement();
+ float time = this.animator.getAnimationTime(this.figureType, nextAnim);
+ this.animator.animate(this.figureType, nextAnim, Std.getRealTime());
+ Timer tm = new Timer(time, this);
+ tm.start();
+ }
+ }
+
+ private float performAnimationSequence(String action) {
+ float totalTime = 0.0F;
+ Vector<String> vanimations = new Vector<String>();
+ StringTokenizer tok = new StringTokenizer(action, "&\t\n\r");
+
+ while (tok.hasMoreTokens()) {
+ String subAction = tok.nextToken();
+ totalTime += this.animator.getAnimationTime(this.figureType, subAction);
+ vanimations.addElement(subAction);
+ }
+
+ this.animations = vanimations.elements();
+ this.timerDone();
+ return totalTime;
+ }
+
+ public Vector<String> getAnimationList() {
+ if (this.animationList != null) {
+ return this.animationList;
+ } else {
+ this.animationList = DroneAnimator.getActionList(this.figureType);
+ return this.animationList;
+ }
+ }
+
+ public void enableLOD(boolean flag) {
+ this.doLOD = flag;
+ }
+
+ @Override
+ public boolean handle(MouseDownEvent e) {
+ return false;
+ }
+
+ @Override
+ public boolean handle(FrameEvent fe) {
+ float dist = this.closestView;
+ this.closestView = 10000.0F;
+ if (this.animator != null && !(dist > 900.0F) && this.hasClump()) {
+ if (this.recomputeHeight) {
+ if (this.runPrepFigure) {
+ DroneAnimator.prepFigure(this, this.COG);
+ }
+
+ this.recomputeHeight = false;
+ }
+
+ if (this.doLOD && this.setLOD(dist)) {
+ return true;
+ } else {
+ int time = Std.getRealTime();
+ Transform t = this.getObjectToWorldMatrix();
+ this.animator.moveto(this.figureType, (short)t.getX(), (short)t.getY(), (short)t.getZ(), (short)(-t.getYaw()), time - 1);
+ this.animator.update(null, this, time, t.getScaleX(), dist > 700.0F);
+ t.recycle();
+ if (this.expressionStart > 0) {
+ time -= this.expressionStart;
+
+ while (true) {
+ PosableShape.TimedMatChange tx = this.expressionChanges.elementAt(this.nextChange);
+ if (time < tx.when) {
+ break;
+ }
+
+ if (tx.mat != origMat) {
+ tx.limb.setMaterial(tx.mat);
+ }
+
+ if (++this.nextChange >= this.expressionChanges.size()) {
+ this.nextChange = 0;
+ this.expressionStart += time;
+ break;
+ }
+ }
+ }
+
+ return true;
+ }
+ } else {
+ return true;
+ }
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Center of Gravity"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(this.COG);
+ } else if (mode == 2) {
+ this.COG = (Boolean)value;
+ URL u = this.getURL();
+ this.setURL(defaultURL);
+ this.setURL(u);
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 1, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(1, classCookie);
+ s.saveBoolean(this.COG);
+ if (this.subparts != null) {
+ this.subparts.detach();
+ super.saveState(s);
+ this.add(this.subparts);
+ } else {
+ super.saveState(s);
+ }
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 1:
+ this.COG = r.restoreBoolean();
+ case 0:
+ super.restoreState(r);
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+
+ @Override
+ public String toString() {
+ return this.getName();
+ }
+
+ class TimedMatChange {
+ Shape limb;
+ Material mat;
+ int when;
+ }
+}
diff --git a/NET/worlds/scape/Postrenderable.java b/NET/worlds/scape/Postrenderable.java
new file mode 100644
index 0000000..c1f0994
--- /dev/null
+++ b/NET/worlds/scape/Postrenderable.java
@@ -0,0 +1,5 @@
+package NET.worlds.scape;
+
+public interface Postrenderable {
+ void postrender(Camera var1);
+}
diff --git a/NET/worlds/scape/PostspinBehavior.java b/NET/worlds/scape/PostspinBehavior.java
new file mode 100644
index 0000000..a95efca
--- /dev/null
+++ b/NET/worlds/scape/PostspinBehavior.java
@@ -0,0 +1,130 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+public class PostspinBehavior extends SpinBehavior implements FrameHandler {
+ private float xCenter;
+ private float yCenter;
+ private float zCenter;
+ private static Object classCookie = new Object();
+
+ public PostspinBehavior(float x, float y, float z, float cycleTime) {
+ this(x, y, z, 0.0F, 0.0F, 1.0F, cycleTime);
+ }
+
+ public PostspinBehavior(float x, float y, float z, float ax, float ay, float az) {
+ this(x, y, z, ax, ay, az, 5.0F);
+ }
+
+ public PostspinBehavior(float x, float y, float z, float ax, float ay, float az, float cycleTime) {
+ super(cycleTime, ax, ay, az);
+ this.xCenter = x;
+ this.yCenter = y;
+ this.zCenter = z;
+ }
+
+ public PostspinBehavior() {
+ }
+
+ public float getXCenter() {
+ return this.xCenter;
+ }
+
+ public float getYCenter() {
+ return this.yCenter;
+ }
+
+ public float getZCenter() {
+ return this.zCenter;
+ }
+
+ public Point3Temp getCenter() {
+ return Point3Temp.make(this.xCenter, this.yCenter, this.zCenter);
+ }
+
+ public void setXCenter(float c) {
+ this.xCenter = c;
+ }
+
+ public void setYCenter(float c) {
+ this.yCenter = c;
+ }
+
+ public void setZCenter(float c) {
+ this.zCenter = c;
+ }
+
+ public void setCenter(Point3Temp center) {
+ this.xCenter = center.x;
+ this.yCenter = center.y;
+ this.zCenter = center.z;
+ }
+
+ @Override
+ public boolean handle(FrameEvent e) {
+ if (this.enabled && this.cycleTime > 0.0F) {
+ e.receiver.moveBy(-this.xCenter, -this.yCenter, -this.zCenter);
+ e.receiver.postspin(this.ax, this.ay, this.az, 0.36F * e.dt / this.cycleTime);
+ e.receiver.moveBy(this.xCenter, this.yCenter, this.zCenter);
+ }
+
+ return true;
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = Point3PropertyEditor.make(new Property(this, index, "Center"));
+ } else if (mode == 1) {
+ ret = new Point3(this.getCenter());
+ } else if (mode == 2) {
+ this.setCenter((Point3)value);
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 1, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public String toString() {
+ return super.toString()
+ + "[center "
+ + this.getCenter()
+ + ", axis "
+ + this.getAxis()
+ + ", cycleTime "
+ + this.cycleTime
+ + ", enabled "
+ + this.enabled
+ + "]";
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(0, classCookie);
+ super.saveState(s);
+ s.saveFloat(this.xCenter);
+ s.saveFloat(this.yCenter);
+ s.saveFloat(this.zCenter);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ this.xCenter = r.restoreFloat();
+ this.yCenter = r.restoreFloat();
+ this.zCenter = r.restoreFloat();
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/Prerenderable.java b/NET/worlds/scape/Prerenderable.java
new file mode 100644
index 0000000..fac20c9
--- /dev/null
+++ b/NET/worlds/scape/Prerenderable.java
@@ -0,0 +1,5 @@
+package NET.worlds.scape;
+
+public interface Prerenderable {
+ void prerender(Camera var1);
+}
diff --git a/NET/worlds/scape/PrintAction.java b/NET/worlds/scape/PrintAction.java
new file mode 100644
index 0000000..569079f
--- /dev/null
+++ b/NET/worlds/scape/PrintAction.java
@@ -0,0 +1,71 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import java.io.IOException;
+
+public class PrintAction extends Action {
+ String txt = null;
+ private static Object classCookie = new Object();
+
+ public PrintAction() {
+ }
+
+ public PrintAction(String text) {
+ this.txt = text;
+ }
+
+ @Override
+ public Persister trigger(Event arg, Persister seqID) {
+ String msg = this.txt;
+ if (msg == null) {
+ msg = this.getName() + "Has-no-text";
+ }
+
+ Console.println(msg);
+ return null;
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Text Out"));
+ } else if (mode == 1) {
+ ret = this.txt;
+ } else if (mode == 2) {
+ this.txt = (String)value;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 1, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(0, classCookie);
+ super.saveState(s);
+ s.saveString(this.txt);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ this.txt = r.restoreString();
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + "[" + this.txt + "]";
+ }
+}
diff --git a/NET/worlds/scape/ProgressiveAdder.java b/NET/worlds/scape/ProgressiveAdder.java
new file mode 100644
index 0000000..29696c2
--- /dev/null
+++ b/NET/worlds/scape/ProgressiveAdder.java
@@ -0,0 +1,49 @@
+package NET.worlds.scape;
+
+import NET.worlds.core.IniFile;
+import java.util.Vector;
+
+public class ProgressiveAdder implements FrameHandler {
+ Vector addList = new Vector();
+ static ProgressiveAdder theProgressiveAdder = null;
+
+ public static ProgressiveAdder get() {
+ if (theProgressiveAdder == null) {
+ theProgressiveAdder = new ProgressiveAdder();
+ }
+
+ return theProgressiveAdder;
+ }
+
+ ProgressiveAdder() {
+ }
+
+ public boolean enabled() {
+ return IniFile.gamma().getIniInt("ProgressiveAvLoading", 0) == 1;
+ }
+
+ void scheduleForAdd(WObject parent, WObject child) {
+ synchronized (this.addList) {
+ WObject[] objs = new WObject[]{parent, child};
+ this.addList.addElement(objs);
+ }
+ }
+
+ @Override
+ public boolean handle(FrameEvent fe) {
+ synchronized (this.addList) {
+ if (this.addList.size() > 0) {
+ WObject[] objs = (WObject[])this.addList.elementAt(0);
+ WObject parent = objs[0];
+ WObject child = objs[1];
+ if (!parent.discarded && !child.discarded) {
+ parent.add(child);
+ }
+
+ this.addList.removeElementAt(0);
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/NET/worlds/scape/PropAdder.java b/NET/worlds/scape/PropAdder.java
new file mode 100644
index 0000000..2ead54d
--- /dev/null
+++ b/NET/worlds/scape/PropAdder.java
@@ -0,0 +1,48 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.PolledDialog;
+
+public class PropAdder implements LibraryDrop {
+ protected VectorProperty property;
+
+ protected PropAdder(VectorProperty property) {
+ this.property = property;
+ }
+
+ public static VectorProperty make(VectorProperty property) {
+ return property.setAdder(new PropAdder(property));
+ }
+
+ public PolledDialog add(EditTile parent, String title) {
+ assert false;
+
+ return null;
+ }
+
+ public boolean hasAddDialog() {
+ return false;
+ }
+
+ protected boolean checkObject(Object obj) {
+ return this.property.addTest(obj);
+ }
+
+ @Override
+ public boolean libraryDrop(EditTile target, Object obj, boolean isPaste, boolean doDrop) {
+ if (this.checkObject(obj)) {
+ if (doDrop) {
+ if (isPaste) {
+ target.addUndoablePaste(this.property, obj);
+ } else {
+ target.addUndoableAdd(this.property, obj, true);
+ }
+
+ return !(obj instanceof SuperRoot) || ((SuperRoot)obj).getOwner() != null;
+ } else {
+ return true;
+ }
+ } else {
+ return false;
+ }
+ }
+}
diff --git a/NET/worlds/scape/PropEditor.java b/NET/worlds/scape/PropEditor.java
new file mode 100644
index 0000000..dfe2202
--- /dev/null
+++ b/NET/worlds/scape/PropEditor.java
@@ -0,0 +1,18 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.PolledDialog;
+
+public abstract class PropEditor implements LibraryDrop {
+ protected Property property;
+
+ protected PropEditor(Property property) {
+ this.property = property;
+ }
+
+ public abstract PolledDialog edit(EditTile var1, String var2);
+
+ @Override
+ public boolean libraryDrop(EditTile target, Object obj, boolean isPaste, boolean doDrop) {
+ return false;
+ }
+}
diff --git a/NET/worlds/scape/PropList.java b/NET/worlds/scape/PropList.java
new file mode 100644
index 0000000..2a9d3a4
--- /dev/null
+++ b/NET/worlds/scape/PropList.java
@@ -0,0 +1,119 @@
+package NET.worlds.scape;
+
+import NET.worlds.core.IniFile;
+import java.awt.List;
+import java.util.Enumeration;
+import java.util.Vector;
+
+public class PropList extends List {
+ private Object obj;
+ private Vector properties;
+ private static String[] sortOrder = new String[]{
+ "Name",
+ "Tilesize",
+ "Transform",
+ "From",
+ "To",
+ "Extent",
+ "Bumpable",
+ "Collision Extent",
+ "Visible",
+ "Optimizable",
+ "DrawFirstOnIntersection",
+ "DrawOrderUnimportant"
+ };
+
+ static {
+ int numUserPreferences = IniFile.gamma().getIniInt("PropertyOrderCount", -1);
+ if (numUserPreferences >= 0) {
+ sortOrder = new String[numUserPreferences];
+
+ for (int i = 0; i < numUserPreferences; i++) {
+ sortOrder[i] = IniFile.gamma().getIniString("PropertyOrder" + i, "");
+ }
+ }
+ }
+
+ public static void setPreferences(String[] prefs) {
+ sortOrder = prefs;
+ }
+
+ public Object getObject() {
+ return this.obj;
+ }
+
+ public void setObject(Object obj) {
+ int selected = this.getSelectedIndex();
+ if (obj != this.obj) {
+ selected = -1;
+ }
+
+ this.obj = obj;
+ int count = this.countItems();
+ if (count != 0) {
+ this.delItems(0, count - 1);
+ }
+
+ Vector unsorted = new Vector();
+ Enumeration e = new EnumProperties(obj);
+
+ for (int var11 = 0; e.hasMoreElements(); var11++) {
+ Property p = (Property)e.nextElement();
+ if (!(p instanceof VectorProperty) && (p.getEditor() != null || !(p.get() instanceof Properties))) {
+ unsorted.addElement(p);
+ }
+ }
+
+ this.properties = new Vector(unsorted.size());
+
+ for (int sortItem = 0; sortItem < sortOrder.length; sortItem++) {
+ String s = sortOrder[sortItem];
+ int size = unsorted.size();
+
+ for (int i = 0; i < size; i++) {
+ Property p = (Property)unsorted.elementAt(i);
+ if (p.getName().equals(s)) {
+ this.properties.addElement(p);
+ unsorted.removeElementAt(i);
+ break;
+ }
+ }
+ }
+
+ int size = unsorted.size();
+
+ for (int ix = 0; ix < size; ix++) {
+ this.properties.addElement(unsorted.elementAt(ix));
+ }
+
+ size = this.properties.size();
+
+ for (int ix = 0; ix < size; ix++) {
+ Property prop = (Property)this.properties.elementAt(ix);
+ this.addItem(prop.getName() + " (" + prop.getPropertyType() + ")" + " (" + prop.get() + ")");
+ }
+
+ count = this.countItems();
+ if (count != 0 && selected != -1) {
+ if (selected >= count) {
+ selected = count - 1;
+ }
+
+ this.select(selected);
+ }
+ }
+
+ public Property getSelectedProperty() {
+ int i = this.getSelectedIndex();
+ return i != -1 ? (Property)this.properties.elementAt(i) : null;
+ }
+
+ @Override
+ public void addItem(String s) {
+ if (s.length() > 128) {
+ s = s.substring(0, 125) + "...";
+ }
+
+ super.addItem(s);
+ }
+}
diff --git a/NET/worlds/scape/PropPropEditor.java b/NET/worlds/scape/PropPropEditor.java
new file mode 100644
index 0000000..7d83be1
--- /dev/null
+++ b/NET/worlds/scape/PropPropEditor.java
@@ -0,0 +1,27 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.PolledDialog;
+
+public class PropPropEditor extends PropEditor {
+ private boolean _nullHandling;
+ private SuperRoot _target;
+
+ private PropPropEditor(Property property, SuperRoot target, boolean nullHandling) {
+ super(property);
+ this._target = target;
+ this._nullHandling = nullHandling;
+ }
+
+ @Override
+ public PolledDialog edit(EditTile parent, String title) {
+ return new PropPropEditorDialog(parent, title, this.property, this._target, this._nullHandling);
+ }
+
+ public static Property make(Property property, SuperRoot target) {
+ return property.setEditor(new PropPropEditor(property, target, false));
+ }
+
+ public static Property make(Property property, SuperRoot target, boolean nullHandling) {
+ return property.setEditor(new PropPropEditor(property, target, nullHandling));
+ }
+}
diff --git a/NET/worlds/scape/PropPropEditorDialog.java b/NET/worlds/scape/PropPropEditorDialog.java
new file mode 100644
index 0000000..4852b5a
--- /dev/null
+++ b/NET/worlds/scape/PropPropEditorDialog.java
@@ -0,0 +1,55 @@
+package NET.worlds.scape;
+
+class PropPropEditorDialog extends ListChooserDialog {
+ private SuperRoot _target;
+ private Property _property;
+ private boolean _nullHandling;
+
+ PropPropEditorDialog(EditTile parent, String title, Property property, SuperRoot target, boolean nullHandling) {
+ super(parent, title);
+ this._target = target;
+ this._property = property;
+ this._nullHandling = nullHandling;
+ this.ready();
+ }
+
+ @Override
+ protected String getEntry(int index) {
+ Property p = null;
+
+ try {
+ p = (Property)this._target.properties(index, 0, 0, null);
+ } catch (NoSuchPropertyException var4) {
+ }
+
+ return p == null ? null : p.getName();
+ }
+
+ @Override
+ protected int getSelected() {
+ if (this._property == null) {
+ return -1;
+ } else {
+ Property val = (Property)this._property.get();
+ return val == null ? -1 : val.getIndex();
+ }
+ }
+
+ @Override
+ protected boolean setValue(String text, int index) {
+ if (index == -1 && !this._nullHandling) {
+ return false;
+ } else {
+ Object val = null;
+
+ try {
+ val = this._target.properties(index, 0, 0, null);
+ } catch (NoSuchPropertyException var5) {
+ assert false;
+ }
+
+ this._parent.addUndoableSet(this._property, val);
+ return true;
+ }
+ }
+}
diff --git a/NET/worlds/scape/PropTreeNode.java b/NET/worlds/scape/PropTreeNode.java
new file mode 100644
index 0000000..a064dec
--- /dev/null
+++ b/NET/worlds/scape/PropTreeNode.java
@@ -0,0 +1,142 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.TreeNode;
+import java.util.Enumeration;
+import java.util.Vector;
+
+class PropTreeNode extends TreeNode {
+ private Object obj;
+ private boolean allowSorting = true;
+
+ public PropTreeNode(Object obj) {
+ super(null);
+ this.obj = obj;
+
+ assert obj != null;
+ }
+
+ public PropTreeNode(Object obj, TreeNode parent) {
+ super(parent);
+ this.obj = obj;
+
+ assert obj != null;
+ }
+
+ @Override
+ public boolean shouldSort() {
+ return this.allowSorting;
+ }
+
+ @Override
+ public Vector getChildren() {
+ Vector ret = null;
+ Object obj = this.obj;
+ if (obj instanceof VectorProperty) {
+ VectorProperty vp = (VectorProperty)obj;
+ this.allowSorting = vp.shouldSort();
+ ret = new Vector();
+ Vector v = (Vector)vp.get();
+ if (v != null) {
+ int count = v.size();
+
+ for (int i = 0; i < count; i++) {
+ Object child = v.elementAt(i);
+ if (child == null) {
+ System.out.println("Error: VectorProperty " + vp.getName() + " of " + vp.getOwner() + " was null.");
+ } else {
+ ret.addElement(new PropTreeNode(child, this));
+ }
+ }
+ }
+ } else {
+ if (obj instanceof Property) {
+ obj = ((Property)obj).get();
+ }
+
+ if (obj instanceof Properties) {
+ ret = new Vector();
+ Enumeration e = new EnumProperties(obj);
+
+ while (e.hasMoreElements()) {
+ Property p = (Property)e.nextElement();
+ if (p instanceof VectorProperty || p.getEditor() == null && p.get() instanceof Properties) {
+ ret.addElement(new PropTreeNode(p, this));
+ }
+ }
+ }
+ }
+
+ return ret;
+ }
+
+ @Override
+ public Object getObject() {
+ return this.obj;
+ }
+
+ @Override
+ public boolean displayAsTitle() {
+ return this.obj instanceof VectorProperty || this.obj instanceof Property;
+ }
+
+ public boolean canEdit() {
+ return false;
+ }
+
+ public VectorProperty getContainingVectorProperty() {
+ Object obj = this.obj;
+ TreeNode e = this.getParent();
+ return !(obj instanceof VectorProperty) && (e == null || !((obj = e.getObject()) instanceof VectorProperty)) ? null : (VectorProperty)obj;
+ }
+
+ public PropAdder getAdder() {
+ VectorProperty vec = this.getContainingVectorProperty();
+ return vec != null ? vec.getAdder() : null;
+ }
+
+ public String getContainerName() {
+ return this.getContainingVectorProperty().getName();
+ }
+
+ public boolean canAdd() {
+ PropAdder adder = this.getAdder();
+ return adder != null && adder.hasAddDialog();
+ }
+
+ public boolean canDelete() {
+ TreeNode e = this.getParent();
+ Object obj;
+ Object var3;
+ return e != null
+ && (
+ (obj = e.getObject()) instanceof VectorProperty && ((VectorProperty)obj).getAdder() != null
+ || (var3 = this.getObject()) instanceof Property && ((Property)var3).canSetNull() && ((Property)var3).get() != null
+ );
+ }
+
+ public Undoable delete(boolean isCut) {
+ assert this.canDelete();
+
+ Object o = this.getParent().getObject();
+ if (o instanceof VectorProperty) {
+ VectorProperty owner = (VectorProperty)o;
+ Vector v = (Vector)owner.get();
+ int i = v.indexOf(this.obj);
+
+ assert i != -1;
+
+ return (Undoable)(isCut ? new UndoablCut(owner, i) : new UndoablDelete(owner, i));
+ } else {
+ return new UndoablSet((Property)this.getObject(), null);
+ }
+ }
+
+ @Override
+ public String toString() {
+ if (this.obj instanceof SuperRoot) {
+ return ((SuperRoot)this.obj).getName();
+ } else {
+ return this.obj instanceof Property ? ((Property)this.obj).getName() : this.obj.toString();
+ }
+ }
+}
diff --git a/NET/worlds/scape/Properties.java b/NET/worlds/scape/Properties.java
new file mode 100644
index 0000000..f75b5f4
--- /dev/null
+++ b/NET/worlds/scape/Properties.java
@@ -0,0 +1,14 @@
+package NET.worlds.scape;
+
+public interface Properties {
+ int ENUM = 0;
+ int GET = 1;
+ int SET = 2;
+ int ADD = 3;
+ int DEL = 4;
+ int ADD_TEST = 5;
+
+ Object properties(int var1, int var2, int var3, Object var4) throws NoSuchPropertyException;
+
+ Object propertyParent();
+}
diff --git a/NET/worlds/scape/Property.java b/NET/worlds/scape/Property.java
new file mode 100644
index 0000000..31b797a
--- /dev/null
+++ b/NET/worlds/scape/Property.java
@@ -0,0 +1,153 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Main;
+
+public class Property {
+ protected Properties owner;
+ public static final int BOOL_TYPE = 0;
+ public static final int INT_TYPE = 1;
+ public static final int FLOAT_TYPE = 2;
+ public static final int STRING_TYPE = 3;
+ public static final int COLOR_TYPE = 4;
+ public static final int ENUM_TYPE = 5;
+ public static final int FLOAT_ARRAY_TYPE = 6;
+ public static final int POINT2_TYPE = 7;
+ public static final int POINT3_TYPE = 8;
+ public static final int TRANSFORM_TYPE = 9;
+ public static final int URL_TYPE = 10;
+ protected int index;
+ protected String name;
+ protected int propertyType = 3;
+ protected PropEditor editor;
+ public boolean helpExists = false;
+ protected boolean canSetNull = false;
+
+ public Property(Properties owner, int index, String name) {
+ this.owner = owner;
+ this.index = index;
+ this.name = name;
+ }
+
+ public Property(Properties owner, int index, String name, boolean haveHelp) {
+ this.owner = owner;
+ this.index = index;
+ this.name = name;
+ this.helpExists = haveHelp;
+ }
+
+ Property setEditor(PropEditor editor) {
+ this.editor = editor;
+ return this;
+ }
+
+ public PropEditor getEditor() {
+ return this.editor;
+ }
+
+ public Property allowSetNull() {
+ this.canSetNull = true;
+ return this;
+ }
+
+ public boolean canSetNull() {
+ return this.canSetNull;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public int getIndex() {
+ return this.index;
+ }
+
+ public Properties getOwner() {
+ return this.owner;
+ }
+
+ public Object get() {
+ return this.operate(1, null);
+ }
+
+ public Object set(Object obj) {
+ return this.operate(2, obj);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return obj instanceof Property && ((Property)obj).owner == this.owner && ((Property)obj).index == this.index;
+ }
+
+ @Override
+ public int hashCode() {
+ return this.owner.hashCode() ^ this.index;
+ }
+
+ protected Object operate(int func, Object value) {
+ return Main.isMainThread() ? this.safeOperate(func, value) : new CallbackPropertyOperator(this, func, value).getValue();
+ }
+
+ Object safeOperate(int func, Object value) {
+ try {
+ Object ret = this.owner.properties(this.index, 0, func, value);
+ if (func > 1 && func < 5 && this.owner instanceof SuperRoot) {
+ ((SuperRoot)this.owner).markEdited();
+ }
+
+ return ret;
+ } catch (NoSuchPropertyException var4) {
+ assert false;
+
+ return null;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return this.getName();
+ }
+
+ public void setPropertyType(int type) {
+ this.propertyType = type;
+ }
+
+ public String getPropertyType() {
+ String retVal;
+ switch (this.propertyType) {
+ case 0:
+ retVal = "Boolean";
+ break;
+ case 1:
+ retVal = "Integer";
+ break;
+ case 2:
+ retVal = "Float";
+ break;
+ case 3:
+ retVal = "String";
+ break;
+ case 4:
+ retVal = "Color";
+ break;
+ case 5:
+ retVal = "Enumeration";
+ break;
+ case 6:
+ retVal = "Float Array";
+ break;
+ case 7:
+ retVal = "2D Point";
+ break;
+ case 8:
+ retVal = "3D Point";
+ break;
+ case 9:
+ retVal = "Transform";
+ break;
+ default:
+ retVal = "URL";
+ }
+
+ return retVal;
+ }
+}
diff --git a/NET/worlds/scape/ProximitySensor.java b/NET/worlds/scape/ProximitySensor.java
new file mode 100644
index 0000000..4ae5b64
--- /dev/null
+++ b/NET/worlds/scape/ProximitySensor.java
@@ -0,0 +1,149 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+public class ProximitySensor extends Sensor implements FrameHandler {
+ private boolean _wasin = false;
+ private Point3 _start = new Point3(0.0F, 0.0F, 0.0F);
+ private Point3 _end = new Point3(1.0F, 1.0F, 1.0F);
+ private boolean _triggerin = true;
+ private boolean _triggerout = false;
+ private boolean _silentTeleport = false;
+ private Room _lastRoom;
+ private static Object classCookie = new Object();
+
+ public ProximitySensor(Action a) {
+ if (a != null) {
+ this.addAction(a);
+ }
+ }
+
+ public ProximitySensor() {
+ }
+
+ @Override
+ public boolean handle(FrameEvent e) {
+ SuperRoot owner = this.getOwner();
+ if (!(owner instanceof WObject)) {
+ return true;
+ } else {
+ WObject wo = (WObject)owner;
+ Pilot pilot = Pilot.getActive();
+ Room room = pilot.getRoom();
+ boolean teleport = room != this._lastRoom;
+ this._lastRoom = room;
+ Point3Temp pos = pilot.getPosition();
+ BoundBoxTemp bbt = BoundBoxTemp.make(Point3Temp.make(this._start).times(wo), Point3Temp.make(this._end).times(wo));
+ if (pilot.getRoom() == wo.getRoom() && bbt.contains(pos)) {
+ if (!this._wasin) {
+ this._wasin = true;
+ if (this._triggerin && (!teleport || !this._silentTeleport)) {
+ this.trigger(e);
+ }
+ }
+ } else if (this._wasin) {
+ this._wasin = false;
+ if (this._triggerout && (!teleport || !this._silentTeleport)) {
+ this.trigger(e);
+ }
+ }
+
+ return true;
+ }
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = Point3PropertyEditor.make(new Property(this, index, "Start"));
+ } else if (mode == 1) {
+ ret = new Point3(this._start);
+ } else if (mode == 2) {
+ this._start = (Point3)value;
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = Point3PropertyEditor.make(new Property(this, index, "End"));
+ } else if (mode == 1) {
+ ret = new Point3(this._end);
+ } else if (mode == 2) {
+ this._end = (Point3)value;
+ }
+ break;
+ case 2:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Trigger on entry"), "Don't trigger when entered", "Trigger when entered");
+ } else if (mode == 1) {
+ ret = new Boolean(this._triggerin);
+ } else if (mode == 2) {
+ this._triggerin = (Boolean)value;
+ }
+ break;
+ case 3:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Trigger on exit"), "Don't trigger when exited", "Trigger when exited");
+ } else if (mode == 1) {
+ ret = new Boolean(this._triggerout);
+ } else if (mode == 2) {
+ this._triggerout = (Boolean)value;
+ }
+ break;
+ case 4:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Teleport trigger"), "Don't trigger on teleports", "Trigger on teleports");
+ } else if (mode == 1) {
+ ret = new Boolean(!this._silentTeleport);
+ } else if (mode == 2) {
+ this._silentTeleport = !(Boolean)value;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 5, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(2, classCookie);
+ super.saveState(s);
+ s.saveBoolean(this._triggerin);
+ s.saveBoolean(this._triggerout);
+ s.saveBoolean(this._silentTeleport);
+ s.save(this._start);
+ s.save(this._end);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 1:
+ super.restoreState(r);
+ this._triggerin = r.restoreBoolean();
+ this._triggerout = r.restoreBoolean();
+ this._start = (Point3)r.restore();
+ this._end = (Point3)r.restore();
+ break;
+ case 2:
+ super.restoreState(r);
+ this._triggerin = r.restoreBoolean();
+ this._triggerout = r.restoreBoolean();
+ this._silentTeleport = r.restoreBoolean();
+ this._start = (Point3)r.restore();
+ this._end = (Point3)r.restore();
+ break;
+ default:
+ throw new TooNewException();
+ }
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + "[" + (this._triggerin ? "I" : " ") + (this._triggerout ? "O" : " ") + this._start + " to " + this._end + "]";
+ }
+}
diff --git a/NET/worlds/scape/RPAction.java b/NET/worlds/scape/RPAction.java
new file mode 100644
index 0000000..2fc9f4a
--- /dev/null
+++ b/NET/worlds/scape/RPAction.java
@@ -0,0 +1,12 @@
+package NET.worlds.scape;
+
+public class RPAction extends Action {
+ @Override
+ public Persister trigger(Event e, Persister seqID) {
+ if (this.getOwner() instanceof Portal) {
+ ((Portal)this.getOwner()).triggerLoad();
+ }
+
+ return null;
+ }
+}
diff --git a/NET/worlds/scape/Rect.java b/NET/worlds/scape/Rect.java
new file mode 100644
index 0000000..9613dd3
--- /dev/null
+++ b/NET/worlds/scape/Rect.java
@@ -0,0 +1,421 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.DefaultConsole;
+import java.io.IOException;
+
+public class Rect extends Surface implements MouseDownHandler, FrameHandler, Prerenderable {
+ static BumpCalc standardPlaneBumpCalc = new PlaneBumpCalc();
+ Billboard _billboardAttribute = null;
+ VideoTexture _videoAttribute = null;
+ boolean visible = false;
+ protected float u = 1.0F;
+ protected float v = 1.0F;
+ protected float uOff;
+ protected float vOff;
+ private static Object classCookie = new Object();
+
+ static {
+ standardPlaneBumpCalc.setName("defaultPlaneBumpCalc");
+ }
+
+ public Rect(float w, float h, Material material) {
+ super(material);
+ this.scale(w, h, h);
+ }
+
+ public Rect(float x, float y, float z, Material material) {
+ super(material);
+ this.setFarCorner(Point3Temp.make(x, y, z));
+ }
+
+ public Rect(float llx, float lly, float llz, float urx, float ury, float urz, Material material) {
+ super(material);
+ this.moveBy(llx, lly, llz);
+ this.setFarCorner(Point3Temp.make(urx, ury, urz));
+ }
+
+ public Rect(Point3Temp llc, Point3Temp urc, Material material) {
+ this(llc.x, llc.y, llc.z, urc.x, urc.y, urc.z, material);
+ }
+
+ Rect() {
+ }
+
+ public static boolean setFarCornerHelper(Transform t, Point3Temp newCorner) {
+ t.scale(1.0F / t.getScaleX(), 1.0F / t.getScaleY(), 1.0F / t.getScaleZ());
+ Point3Temp lookRight = Point3Temp.make(1.0F, 0.0F, 0.0F).vectorTimes(t);
+ Point3Temp lookOut = Point3Temp.make(0.0F, 1.0F, 0.0F).vectorTimes(t);
+ Point3Temp lookUp = Point3Temp.make(0.0F, 0.0F, 1.0F).vectorTimes(t);
+ Point3Temp newEndOffset = Point3Temp.make(newCorner).minus(t.getPosition());
+ float x = newEndOffset.dot(lookRight);
+ float y = newEndOffset.dot(lookOut);
+ float z = newEndOffset.dot(lookUp);
+ if (!(z >= 0.0F)) {
+ return false;
+ } else {
+ if (x != 0.0F || y != 0.0F) {
+ t.spin(0.0F, 0.0F, 1.0F, (float)(Math.atan2(y, x) * 180.0 / Math.PI));
+ }
+
+ t.scale((float)Math.sqrt(x * x + y * y), z, z);
+ return true;
+ }
+ }
+
+ public boolean setFarCorner(Point3Temp newCorner) {
+ Transform t = this.getTransform();
+ if (setFarCornerHelper(t, newCorner)) {
+ this.setTransform(t);
+ t.recycle();
+ return true;
+ } else {
+ t.recycle();
+ Console.println(Console.message("cant-rot-rect"));
+ return false;
+ }
+ }
+
+ public Point3Temp getFarCorner() {
+ Point3Temp ret = Point3Temp.make(1.0F, 0.0F, 1.0F);
+ if (this.hasClump()) {
+ Transform t = this.getObjectToWorldMatrix();
+ ret.times(t);
+ t.recycle();
+ } else {
+ ret.times(this);
+ }
+
+ return ret;
+ }
+
+ public Point3Temp getFarCornerLocal() {
+ Point3Temp ret = Point3Temp.make(1.0F, 0.0F, 1.0F);
+ if (this.hasClump()) {
+ Transform t = this.getTransform();
+ ret.times(t);
+ t.recycle();
+ } else {
+ ret.times(this);
+ }
+
+ return ret;
+ }
+
+ public void setNearCorner(Point3Temp from) {
+ Point3Temp oldEnd = this.getFarCornerLocal();
+ Point3Temp oldStart = this.getPosition();
+ this.moveTo(from);
+ if (!this.setFarCorner(oldEnd)) {
+ this.moveTo(oldStart);
+ }
+ }
+
+ @Override
+ public Point3Temp getPlaneExtent() {
+ return Point3Temp.make(1.0F, 0.0F, 1.0F);
+ }
+
+ @Override
+ public BumpCalc getBumpCalc(BumpEventTemp b) {
+ return this.bumpCalc == null ? standardPlaneBumpCalc : this.bumpCalc;
+ }
+
+ public Point2 getTileSize() {
+ return new Point2(this.u != 1.0F ? this.getScaleX() / this.u : 0.0F, this.v != 1.0F ? this.getScaleZ() / this.v : 0.0F);
+ }
+
+ void setUV(float u, float v) {
+ this.setTileSize(this.getScaleX() / u, this.getScaleZ() / v);
+ }
+
+ public Rect setTileSize(float tx, float ty) {
+ this.u = tx == 0.0F ? 1.0F : this.getScaleX() / tx;
+ this.v = ty == 0.0F ? 1.0F : this.getScaleZ() / ty;
+ this.reclump();
+ return this;
+ }
+
+ public void setTileOffset(Point2 p) {
+ this.uOff = this.getScaleX() == 0.0F ? 0.0F : p.x / this.getScaleX();
+ this.vOff = this.getScaleZ() == 0.0F ? 0.0F : p.y / this.getScaleZ();
+ this.reclump();
+ }
+
+ public Point2 getTileOffset() {
+ return new Point2(this.uOff * this.getScaleX(), this.vOff * this.getScaleZ());
+ }
+
+ public static Rect floor(float x, float y, Material m) {
+ return (Rect)new Rect(x, y, m).setBumpable(false).postspin(1.0F, 0.0F, 0.0F, -90.0F);
+ }
+
+ public static Rect floor(float llx, float lly, float z, float urx, float ury, Material m) {
+ return (Rect)floor(urx - llx, ury - lly, m).moveBy(llx, lly, z);
+ }
+
+ public static Rect ceiling(float x, float y, Material m) {
+ return (Rect)new Rect(x, y, m).setBumpable(false).postspin(1.0F, 0.0F, 0.0F, 90.0F).moveBy(0.0F, y, 0.0F);
+ }
+
+ public static Rect ceiling(float llx, float lly, float z, float urx, float ury, Material m) {
+ return (Rect)ceiling(urx - llx, ury - lly, m).moveBy(llx, lly, z);
+ }
+
+ public Rect hang(float pllx, float pllz, float purx, float purz, Material pic) {
+ Rect r = (Rect)new Rect((purx - pllx) / this.getScaleX(), (purz - pllz) / this.getScaleZ(), pic)
+ .moveBy(pllx / this.getScaleX(), 0.0F, pllz / this.getScaleZ())
+ .post(this);
+ return (Rect)r.premoveBy(0.0F, -1.0F / r.getScale().length(), 0.0F);
+ }
+
+ public VideoTexture getVideoAttribute() {
+ return this._videoAttribute;
+ }
+
+ public Billboard getBillboardAttribute() {
+ return this._billboardAttribute;
+ }
+
+ @Override
+ public boolean handle(MouseDownEvent event) {
+ if (this._billboardAttribute != null && (event.key & 1) == 1) {
+ Point2 pt = this.deproject();
+ this._billboardAttribute.billboardClicked(pt);
+ }
+
+ return false;
+ }
+
+ @Override
+ public boolean handle(FrameEvent f) {
+ if (this._billboardAttribute != null && this.getVisible() && this.visible) {
+ this._billboardAttribute.billboardFrame(f);
+ }
+
+ if (this._videoAttribute != null && this.getVisible() && this.visible) {
+ this._videoAttribute.videoFrame(f);
+ }
+
+ this.visible = false;
+ return false;
+ }
+
+ @Override
+ public void prerender(Camera cam) {
+ if (this._billboardAttribute != null || this._videoAttribute != null) {
+ Point3Temp p = this.inCamSpace(cam);
+ boolean v = p != null && p.z > 1.0F && p.x < p.z && -p.x < p.z;
+ if (v) {
+ this.visible = true;
+ }
+ }
+ }
+
+ protected Point2 deproject() {
+ Console c = Console.getActive();
+ if (c instanceof DefaultConsole) {
+ DefaultConsole dc = (DefaultConsole)c;
+ Point3Temp worldClick = dc.getRender().getCamera().lastPickSpot();
+ Point3Temp vWorld = Point3Temp.make(worldClick);
+ vWorld.minus(this.getObjectToWorldMatrix().getPosition());
+ Transform inv = this.getObjectToWorldMatrix().invert();
+ Point3Temp vObj = Point3Temp.make(vWorld).vectorTimes(inv);
+ inv.recycle();
+ Point2 rectPt = new Point2();
+ rectPt.set(vObj.x, vObj.z);
+ return rectPt;
+ } else {
+ return new Point2(-1.0F, -1.0F);
+ }
+ }
+
+ @Override
+ protected void addRwChildren(WObject container) {
+ this.addNewRwChild(container);
+ float uo = this.uOff;
+ if (uo != 0.0F) {
+ uo *= this.u;
+ uo = (float)(uo - 2.0 * Math.floor(uo / 2.0F));
+ }
+
+ float vo = this.vOff;
+ if (vo != 0.0F) {
+ vo *= this.v;
+ vo = (float)(vo - 2.0 * Math.floor(vo / 2.0F));
+ }
+
+ this.addVertex(0.0F, 0.0F, 0.0F, uo, this.v + vo);
+ this.addVertex(1.0F, 0.0F, 0.0F, this.u + uo, this.v + vo);
+ this.addVertex(1.0F, 0.0F, 1.0F, this.u + uo, vo);
+ this.addVertex(0.0F, 0.0F, 1.0F, uo, vo);
+ this.doneWithEditing();
+ if (!(this instanceof Portal)) {
+ this.getRoom().addPrerenderHandler(this);
+ }
+ }
+
+ @Override
+ protected void markVoid() {
+ if (!(this instanceof Portal)) {
+ this.getRoom().removePrerenderHandler(this);
+ }
+
+ super.markVoid();
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = Point2PropertyEditor.make(new Property(this, index, "Tile Size"));
+ } else if (mode == 1) {
+ ret = this.getTileSize();
+ } else if (mode == 2) {
+ Point2 p = (Point2)value;
+ if (!(p.x < 0.0F) && !(p.y < 0.0F)) {
+ this.setTileSize(p.x, p.y);
+ } else {
+ Console.println(Console.message("Tile-size"));
+ }
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = Point2PropertyEditor.make(new Property(this, index, "Tile Origin"));
+ } else if (mode == 1) {
+ ret = this.getTileOffset();
+ } else if (mode == 2) {
+ this.setTileOffset((Point2)value);
+ }
+ break;
+ case 2:
+ if (mode == 0) {
+ ret = Point3PropertyEditor.make(new Property(this, index, "From"));
+ } else if (mode == 1) {
+ ret = new Point3(this.getPosition());
+ } else if (mode == 2) {
+ this.setNearCorner((Point3)value);
+ }
+ break;
+ case 3:
+ if (mode == 0) {
+ ret = Point3PropertyEditor.make(new Property(this, index, "To"));
+ } else if (mode == 1) {
+ ret = new Point3(this.getFarCornerLocal());
+ } else if (mode == 2) {
+ this.setFarCorner((Point3)value);
+ }
+ break;
+ case 4:
+ if (mode == 0) {
+ ret = Point2PropertyEditor.make(new Property(this, index, "Extent"));
+ } else if (mode == 1) {
+ ret = new Point2(this.getScaleX(), this.getScaleZ());
+ } else if (mode == 2) {
+ float zScale = ((Point2)value).y / this.getScaleZ();
+ this.scale(((Point2)value).x / this.getScaleX(), zScale, zScale);
+ }
+ break;
+ case 5:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Flip Alternate U"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(this.getUFlip());
+ } else if (mode == 2) {
+ this.setUFlip((Boolean)value);
+ this.reclump();
+ }
+ break;
+ case 6:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Flip Alternate V"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(this.getVFlip());
+ } else if (mode == 2) {
+ this.setVFlip((Boolean)value);
+ this.reclump();
+ }
+ break;
+ case 7:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Unused"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(this.getMouseOver());
+ } else if (mode == 2) {
+ this.setMouseOver((Boolean)value);
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 8, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(4, classCookie);
+ super.saveState(s);
+ s.saveFloat(this.u);
+ s.saveFloat(this.v);
+ s.saveFloat(this.uOff);
+ s.saveFloat(this.vOff);
+ s.saveBoolean(false);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ int vers = r.restoreVersion(classCookie);
+ switch (vers) {
+ case 0:
+ case 1:
+ super.restoreState(r);
+ float x = r.restoreFloat();
+ float y = r.restoreFloat();
+ float z = r.restoreFloat();
+ r.restoreFloat();
+ r.restoreFloat();
+ r.restoreFloat();
+ this.u = r.restoreFloat();
+ this.v = r.restoreFloat();
+ this.spin(0.0F, 0.0F, 1.0F, (float)(Math.atan2(y, x) * 180.0 / Math.PI));
+ this.scale((float)Math.sqrt(x * x + y * y), z, z);
+ break;
+ case 2:
+ super.restoreState(r);
+ this.u = r.restoreFloat();
+ this.v = r.restoreFloat();
+ break;
+ case 3:
+ super.restoreState(r);
+ this.u = r.restoreFloat();
+ this.v = r.restoreFloat();
+ this.uOff = r.restoreFloat();
+ this.vOff = r.restoreFloat();
+ break;
+ case 4:
+ super.restoreState(r);
+ this.u = r.restoreFloat();
+ this.v = r.restoreFloat();
+ this.uOff = r.restoreFloat();
+ this.vOff = r.restoreFloat();
+ r.restoreBoolean();
+ break;
+ default:
+ throw new TooNewException();
+ }
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + "[" + this.getPosition() + "->" + this.getFarCornerLocal() + "]";
+ }
+
+ @Override
+ public boolean acceptsLeftClicks() {
+ return this._billboardAttribute != null && this._billboardAttribute.getIsAdBanner() ? true : this.getMouseOver();
+ }
+}
diff --git a/NET/worlds/scape/RectPatch.java b/NET/worlds/scape/RectPatch.java
new file mode 100644
index 0000000..6ce3473
--- /dev/null
+++ b/NET/worlds/scape/RectPatch.java
@@ -0,0 +1,401 @@
+package NET.worlds.scape;
+
+import java.awt.Color;
+import java.io.IOException;
+
+public class RectPatch extends WObject implements FloorPatch {
+ public float xDim;
+ public float yDim;
+ public float[] z = new float[]{0.0F, 0.0F, 0.0F, 0.0F};
+ public Material mat;
+ public float xTile = 1.0F;
+ public float xTileOffset = 0.0F;
+ public float yTile = 1.0F;
+ public float yTileOffset = 0.0F;
+ public Polygon[] t = new Polygon[4];
+ private static Object classCookie = new Object();
+
+ public RectPatch(float x, float y) {
+ this.setVisible(true);
+ this.setBumpable(false);
+ this.xDim = x;
+ this.yDim = y;
+ this.setMaterial(new Material(Color.gray));
+ }
+
+ public RectPatch() {
+ this.xDim = 1.0F;
+ this.yDim = 1.0F;
+ this.setMaterial(new Material(Color.gray));
+ }
+
+ @Override
+ protected void addRwChildren(WObject parent) {
+ if (this.t[0] == null) {
+ this.createAppearance();
+ }
+
+ super.addRwChildren(parent);
+ }
+
+ @Override
+ public void setVisible(boolean v) {
+ super.setVisible(v);
+ this.createAppearance();
+ }
+
+ public void setMaterial(Material m) {
+ if (this.mat != null) {
+ this.mat.detach();
+ }
+
+ this.add(m);
+ this.mat = m;
+ this.createAppearance();
+ }
+
+ public Material getMaterial() {
+ return this.mat;
+ }
+
+ @Override
+ public boolean inPatch(float x, float y) {
+ Transform inverse = this.getObjectToWorldMatrix().invert();
+ Point3Temp p = Point3Temp.make(x, y, 0.0F).times(inverse);
+ inverse.recycle();
+ x = p.x;
+ y = p.y;
+ return !(x < 0.0F) && !(x > this.xDim) && !(y < 0.0F) && !(y > this.yDim);
+ }
+
+ @Override
+ public float floorHeight(float x, float y) {
+ Transform inverse = this.getObjectToWorldMatrix().invert();
+ Point3Temp p = Point3Temp.make(x, y, 0.0F).times(inverse);
+ inverse.recycle();
+ x = p.x;
+ y = p.y;
+ float nx = x / this.xDim;
+ float ny = y / this.yDim;
+ float fx = 1.0F - nx;
+ float fy = 1.0F - ny;
+ return this.z[0] * fy * fx + this.z[1] * ny * fx + this.z[2] * ny * nx + this.z[3] * fy * nx;
+ }
+
+ @Override
+ public Point3 surfaceNormal(float x, float y) {
+ Point3 A = new Point3(this.xDim, 0.0F, this.z[1] - this.z[0]);
+ Point3Temp B = Point3Temp.make(0.0F, this.yDim, this.z[3] - this.z[0]);
+ A.cross(B);
+ A.normalize();
+ A.times(this.getObjectToWorldMatrix());
+ return A;
+ }
+
+ private void removeAppearance() {
+ for (int i = 0; i < 4; i++) {
+ if (this.t[i] != null) {
+ this.t[i].detach();
+ this.t[i] = null;
+ }
+ }
+ }
+
+ public void createAppearance() {
+ this.removeAppearance();
+ if (this.getVisible()) {
+ if (!(this.xDim <= 0.0F) && !(this.yDim <= 0.0F)) {
+ if (this.xTile <= 0.0F) {
+ this.xTile = 1.0F;
+ }
+
+ if (this.xTile > 31.0F) {
+ this.xTile = 31.0F;
+ }
+
+ if (this.yTile <= 0.0F) {
+ this.yTile = 1.0F;
+ }
+
+ if (this.yTile > 31.0F) {
+ this.yTile = 31.0F;
+ }
+
+ if (this.xTileOffset < 0.0F) {
+ this.xTileOffset = 1.0F - (float)Math.floor(this.xTileOffset) + this.xTileOffset;
+ }
+
+ if (this.yTileOffset < 0.0F) {
+ this.yTileOffset = 1.0F - (float)Math.floor(this.yTileOffset) + this.yTileOffset;
+ }
+
+ float cx = this.xDim / 2.0F;
+ float cy = this.yDim / 2.0F;
+ float cz = (this.z[0] + this.z[1] + this.z[2] + this.z[3]) / 4.0F;
+ float cU = this.xTileOffset + this.xTile / 2.0F;
+ float cV = this.yTileOffset + this.yTile / 2.0F;
+ this.t[0] = new Polygon(3, this.mat);
+ this.t[0].setVertex(0, 0.0F, 0.0F, this.z[0], this.xTileOffset, this.yTileOffset);
+ this.t[0].setVertex(1, cx, cy, cz, cU, cV);
+ this.t[0].setVertex(2, 0.0F, this.yDim, this.z[1], this.xTileOffset, this.yTileOffset + this.yTile);
+ this.add(this.t[0]);
+ this.t[1] = new Polygon(3, this.mat);
+ this.t[1].setVertex(0, 0.0F, this.yDim, this.z[1], this.xTileOffset, this.yTileOffset + this.yTile);
+ this.t[1].setVertex(1, cx, cy, cz, cU, cV);
+ this.t[1].setVertex(2, this.xDim, this.yDim, this.z[2], this.xTileOffset + this.xTile, this.yTileOffset + this.yTile);
+ this.add(this.t[1]);
+ this.t[2] = new Polygon(3, this.mat);
+ this.t[2].setVertex(0, this.xDim, this.yDim, this.z[2], this.xTileOffset + this.xTile, this.yTileOffset + this.yTile);
+ this.t[2].setVertex(1, cx, cy, cz, cU, cV);
+ this.t[2].setVertex(2, this.xDim, 0.0F, this.z[3], this.xTileOffset + this.xTile, this.yTileOffset);
+ this.add(this.t[2]);
+ this.t[3] = new Polygon(3, this.mat);
+ this.t[3].setVertex(0, this.xDim, 0.0F, this.z[3], this.xTileOffset + this.xTile, this.yTileOffset);
+ this.t[3].setVertex(1, cx, cy, cz, cU, cV);
+ this.t[3].setVertex(2, 0.0F, 0.0F, this.z[0], this.xTileOffset, this.yTileOffset);
+ this.add(this.t[3]);
+ }
+ }
+ }
+
+ public void setCornerHeight(int corner, float height) {
+ this.z[corner] = height;
+ this.createAppearance();
+ }
+
+ public void setWidth(float v) {
+ this.xDim = v;
+ this.createAppearance();
+ }
+
+ public void setLength(float v) {
+ this.yDim = v;
+ this.createAppearance();
+ }
+
+ @Override
+ public Transform spin(float x, float y, float z, float a) {
+ if (x == 0.0F && y == 0.0F) {
+ return super.spin(x, y, z, a);
+ } else {
+ System.out.println("ERROR: cannot spin floor patch out of horizontal!");
+ return this;
+ }
+ }
+
+ @Override
+ public Transform postspin(float x, float y, float z, float a) {
+ if (x == 0.0F && y == 0.0F) {
+ return super.spin(x, y, z, a);
+ } else {
+ System.out.println("ERROR: cannot spin floor patch out of horizontal!");
+ return this;
+ }
+ }
+
+ @Override
+ public Transform worldSpin(float x, float y, float z, float a) {
+ if (x == 0.0F && y == 0.0F) {
+ return super.spin(x, y, z, a);
+ } else {
+ System.out.println("ERROR: cannot spin floor patch out of horizontal!");
+ return this;
+ }
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Length (y)"));
+ } else if (mode == 1) {
+ ret = new Float(this.yDim);
+ } else if (mode == 2) {
+ this.setLength((Float)value);
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Width (x)"));
+ } else if (mode == 1) {
+ ret = new Float(this.xDim);
+ } else if (mode == 2) {
+ this.setWidth((Float)value);
+ }
+ break;
+ case 2:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "0,0 corner"));
+ } else if (mode == 1) {
+ ret = new Float(this.z[0]);
+ } else if (mode == 2) {
+ this.setCornerHeight(0, (Float)value);
+ }
+ break;
+ case 3:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "0,y corner"));
+ } else if (mode == 1) {
+ ret = new Float(this.z[1]);
+ } else if (mode == 2) {
+ this.setCornerHeight(1, (Float)value);
+ }
+ break;
+ case 4:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "x,y corner"));
+ } else if (mode == 1) {
+ ret = new Float(this.z[2]);
+ } else if (mode == 2) {
+ this.setCornerHeight(2, (Float)value);
+ }
+ break;
+ case 5:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "x,0 corner"));
+ } else if (mode == 1) {
+ ret = new Float(this.z[3]);
+ } else if (mode == 2) {
+ this.setCornerHeight(3, (Float)value);
+ }
+ break;
+ case 6:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "# Tiles (x)"));
+ } else if (mode == 1) {
+ ret = new Float(this.xTile);
+ } else if (mode == 2) {
+ this.xTile = (Float)value;
+ this.createAppearance();
+ }
+ break;
+ case 7:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "# Tiles (y)"));
+ } else if (mode == 1) {
+ ret = new Float(this.yTile);
+ } else if (mode == 2) {
+ this.yTile = (Float)value;
+ this.createAppearance();
+ }
+ break;
+ case 8:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Tile Offset (x)"));
+ } else if (mode == 1) {
+ ret = new Float(this.xTileOffset);
+ } else if (mode == 2) {
+ this.xTileOffset = (Float)value;
+ this.createAppearance();
+ }
+ break;
+ case 9:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Tile Offset (y)"));
+ } else if (mode == 1) {
+ ret = new Float(this.yTileOffset);
+ } else if (mode == 2) {
+ this.yTileOffset = (Float)value;
+ this.createAppearance();
+ }
+ break;
+ case 10:
+ if (mode == 0) {
+ ret = new Property(this, index, "Material");
+ } else if (mode == 1) {
+ ret = this.mat;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 11, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(2, classCookie);
+ this.removeAppearance();
+ super.saveState(s);
+ s.saveFloat(this.xDim);
+ s.saveFloat(this.yDim);
+
+ for (int i = 0; i < 4; i++) {
+ s.saveFloat(this.z[i]);
+ }
+
+ s.saveFloat(this.xTile);
+ s.saveFloat(this.xTileOffset);
+ s.saveFloat(this.yTile);
+ s.saveFloat(this.yTileOffset);
+ s.saveMaybeNull(this.mat);
+ this.createAppearance();
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ this.restoreStateRectPatchHelper(r, classCookie);
+ }
+
+ public void restoreStateRectPatchHelper(Restorer r, Object cookie) throws IOException, TooNewException {
+ switch (r.restoreVersion(cookie)) {
+ case 0:
+ r.setOldFlag();
+ super.restoreState(r);
+ this.xDim = r.restoreFloat();
+ this.yDim = r.restoreFloat();
+
+ for (int i = 0; i < 4; i++) {
+ this.z[i] = r.restoreFloat();
+ }
+
+ this.setVisible(false);
+ break;
+ case 1:
+ r.setOldFlag();
+ super.restoreState(r);
+ this.xDim = r.restoreFloat();
+ this.yDim = r.restoreFloat();
+
+ for (int i = 0; i < 4; i++) {
+ this.z[i] = r.restoreFloat();
+ }
+
+ this.xTile = r.restoreFloat();
+ this.xTileOffset = r.restoreFloat();
+ this.yTile = r.restoreFloat();
+ this.yTileOffset = r.restoreFloat();
+ this.setMaterial(Material.restore(r));
+ r.restoreMaybeNull();
+ r.restoreMaybeNull();
+ r.restoreMaybeNull();
+ r.restoreMaybeNull();
+ break;
+ case 2:
+ super.restoreState(r);
+ this.xDim = r.restoreFloat();
+ this.yDim = r.restoreFloat();
+
+ for (int i = 0; i < 4; i++) {
+ this.z[i] = r.restoreFloat();
+ }
+
+ this.xTile = r.restoreFloat();
+ this.xTileOffset = r.restoreFloat();
+ this.yTile = r.restoreFloat();
+ this.yTileOffset = r.restoreFloat();
+ this.setMaterial(Material.restore(r));
+ break;
+ default:
+ throw new TooNewException();
+ }
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + "[" + this.xDim + "," + this.yDim + "]";
+ }
+}
diff --git a/NET/worlds/scape/Recycler.java b/NET/worlds/scape/Recycler.java
new file mode 100644
index 0000000..cab50e4
--- /dev/null
+++ b/NET/worlds/scape/Recycler.java
@@ -0,0 +1,75 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Main;
+import NET.worlds.console.MainCallback;
+
+public class Recycler implements MainCallback {
+ private static int minCapacity = 50;
+ private Object[] list = new Object[minCapacity];
+ private int numFilled = 0;
+ private int numAllocked = 0;
+ private int maxAllockedRecently = 0;
+ private int howRecently = 0;
+
+ Recycler() {
+ Main.register(this);
+ }
+
+ private void resizeTo(int newCapacity) {
+ assert newCapacity > this.numAllocked;
+
+ if (newCapacity < minCapacity) {
+ newCapacity = minCapacity;
+ }
+
+ if (newCapacity < this.list.length && this.list.length < 2 * newCapacity) {
+ while (this.numFilled > newCapacity) {
+ this.list[--this.numFilled] = null;
+ }
+ } else {
+ Object[] newList = new Object[newCapacity];
+
+ try {
+ System.arraycopy(this.list, 0, newList, 0, this.numAllocked);
+ } catch (Exception var4) {
+ throw new Error(var4.toString());
+ }
+
+ this.list = newList;
+ this.numFilled = this.numAllocked;
+ }
+ }
+
+ @Override
+ public void mainCallback() {
+ if (this.numAllocked > this.maxAllockedRecently) {
+ this.maxAllockedRecently = this.numAllocked;
+ }
+
+ if (++this.howRecently == 1000) {
+ int newCapacity = this.maxAllockedRecently + minCapacity;
+ if (newCapacity < this.list.length) {
+ this.resizeTo(newCapacity);
+ }
+
+ this.howRecently = 0;
+ this.maxAllockedRecently = this.numAllocked;
+ }
+
+ this.numAllocked = 0;
+ }
+
+ public Object alloc() {
+ assert Main.isMainThread();
+
+ return this.numAllocked == this.numFilled ? null : this.list[this.numAllocked++];
+ }
+
+ public void recycle(Object o) {
+ if (this.numFilled == this.list.length) {
+ this.resizeTo(this.list.length * 2);
+ }
+
+ this.list[this.numFilled++] = o;
+ }
+}
diff --git a/NET/worlds/scape/RelativeMoveAction.java b/NET/worlds/scape/RelativeMoveAction.java
new file mode 100644
index 0000000..8d59804
--- /dev/null
+++ b/NET/worlds/scape/RelativeMoveAction.java
@@ -0,0 +1,196 @@
+package NET.worlds.scape;
+
+import NET.worlds.core.Std;
+import java.io.IOException;
+
+public class RelativeMoveAction extends Action {
+ int startTime;
+ public int cycleTime = 1000;
+ public int cycles = 1;
+ public boolean loopInfinite = false;
+ public Point3 extentPoint = new Point3();
+ public Point3 extentScale = new Point3(1.0F, 1.0F, 1.0F);
+ public Point3 extentSpin = new Point3(0.0F, 0.0F, -1.0F);
+ public float extentRotation = 0.0F;
+ public float accumulatedRotation;
+ public Point3 accumulatedScale;
+ public Point3 accumulatedPoint;
+ protected Persister activeID;
+ private static Object classCookie = new Object();
+
+ @Override
+ public Persister trigger(Event e, Persister seqID) {
+ Object owner = this.getOwner();
+ if (owner != null && owner instanceof WObject) {
+ WObject o = (WObject)owner;
+ if (seqID == null) {
+ if (this.activeID != null) {
+ return this.activeID;
+ }
+
+ this.startTime = Std.getRealTime();
+ this.activeID = new SuperRoot();
+ seqID = this.activeID;
+ this.accumulatedRotation = 0.0F;
+ this.accumulatedPoint = new Point3(0.0F, 0.0F, 0.0F);
+ this.accumulatedScale = new Point3(1.0F, 1.0F, 1.0F);
+ }
+
+ if (seqID != this.activeID) {
+ return null;
+ } else {
+ int currentTime = Std.getRealTime();
+ int cycleNo = (currentTime - this.startTime) / this.cycleTime;
+ float frameLoc = 1.0F;
+ if (cycleNo >= this.cycles && !this.loopInfinite) {
+ this.activeID = null;
+ } else {
+ frameLoc = (float)((currentTime - this.startTime) % this.cycleTime) / this.cycleTime;
+ }
+
+ float tmpSpin = this.extentRotation * frameLoc;
+ o.spin(this.extentSpin, tmpSpin - this.accumulatedRotation);
+ this.accumulatedRotation = tmpSpin;
+ Point3 tmpScale = new Point3(
+ (float)Math.pow(this.extentScale.x, frameLoc), (float)Math.pow(this.extentScale.y, frameLoc), (float)Math.pow(this.extentScale.z, frameLoc)
+ );
+ o.scale(Point3Temp.make(tmpScale).dividedBy(this.accumulatedScale));
+ this.accumulatedScale = tmpScale;
+ Point3 tmpPoint = new Point3(Point3Temp.make(this.extentPoint).times(frameLoc));
+ o.moveBy(Point3Temp.make(tmpPoint).minus(this.accumulatedPoint));
+ this.accumulatedPoint = tmpPoint;
+ return this.activeID;
+ }
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Cycle Time (in seconds)"));
+ } else if (mode == 1) {
+ ret = new Float(this.cycleTime / 1000.0F);
+ } else if (mode == 2) {
+ this.cycleTime = (int)(1000.0F * (Float)value);
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = IntegerPropertyEditor.make(new Property(this, index, "Cycles"));
+ } else if (mode == 1) {
+ ret = new Integer(this.cycles);
+ } else if (mode == 2) {
+ this.cycles = (Integer)value;
+ }
+ break;
+ case 2:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Loop Infinite"), "False", "True");
+ } else if (mode == 1) {
+ ret = new Boolean(this.loopInfinite);
+ } else if (mode == 2) {
+ this.loopInfinite = (Boolean)value;
+ }
+ break;
+ case 3:
+ if (mode == 0) {
+ ret = Point3PropertyEditor.make(new Property(this, index, "Translation Extent"));
+ } else if (mode == 1) {
+ ret = new Point3(this.extentPoint);
+ } else if (mode == 2) {
+ this.extentPoint.copy((Point3)value);
+ }
+ break;
+ case 4:
+ if (mode == 0) {
+ ret = Point3PropertyEditor.make(new Property(this, index, "Scale Extent"));
+ } else if (mode == 1) {
+ ret = new Point3(this.extentScale);
+ } else if (mode == 2) {
+ this.extentScale.copy((Point3)value);
+ }
+ break;
+ case 5:
+ if (mode == 0) {
+ ret = Point3PropertyEditor.make(new Property(this, index, "Spin Axis For Extent"));
+ } else if (mode == 1) {
+ Point3 p = new Point3(this.extentSpin);
+ p.x = Math.round(p.x * 10000.0F) / 10000.0F;
+ p.y = Math.round(p.y * 10000.0F) / 10000.0F;
+ p.z = Math.round(p.z * 10000.0F) / 10000.0F;
+ ret = p;
+ } else if (mode == 2) {
+ this.extentSpin.copy((Point3)value);
+ }
+ break;
+ case 6:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Extent Rotation Amount"));
+ } else if (mode == 1) {
+ ret = new Float(this.extentRotation);
+ } else if (mode == 2) {
+ this.extentRotation = (Float)value;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 7, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public String toString() {
+ String retVal = super.toString() + "[cycleTime " + this.cycleTime / 1000.0F + ", cycles " + this.cycles + ", ";
+ if (!this.loopInfinite) {
+ retVal = retVal + " NOT";
+ }
+
+ return retVal + " Infinite]";
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(5, classCookie);
+ super.saveState(s);
+ s.saveBoolean(this.loopInfinite);
+ s.saveInt(this.cycleTime);
+ s.saveInt(this.cycles);
+ s.save(this.extentPoint);
+ s.save(this.extentScale);
+ s.save(this.extentSpin);
+ s.saveFloat(this.extentRotation);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 4:
+ super.restoreState(r);
+ this.cycleTime = r.restoreInt();
+ this.cycles = r.restoreInt();
+ this.extentPoint = (Point3)r.restore();
+ this.extentScale = (Point3)r.restore();
+ this.extentSpin = (Point3)r.restore();
+ this.extentRotation = r.restoreFloat();
+ break;
+ case 5:
+ super.restoreState(r);
+ this.loopInfinite = r.restoreBoolean();
+ this.cycleTime = r.restoreInt();
+ this.cycles = r.restoreInt();
+ this.extentPoint = (Point3)r.restore();
+ this.extentScale = (Point3)r.restore();
+ this.extentSpin = (Point3)r.restore();
+ this.extentRotation = r.restoreFloat();
+ break;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/RemotePortal.java b/NET/worlds/scape/RemotePortal.java
new file mode 100644
index 0000000..aa3621e
--- /dev/null
+++ b/NET/worlds/scape/RemotePortal.java
@@ -0,0 +1,73 @@
+package NET.worlds.scape;
+
+import NET.worlds.network.URL;
+import java.io.IOException;
+import java.util.Enumeration;
+
+public class RemotePortal extends WObject {
+ private static Object classCookie = new Object();
+
+ RemotePortal() {
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ assert false;
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ Portal p = new Portal();
+ r.replace(this, p);
+ int vers = r.restoreVersion(classCookie);
+ WObject dlRepresentation = null;
+ WObject initialRepresentation = null;
+ p.superRestoreState(r);
+ Point3 p1 = (Point3)r.restore();
+ Point3 p2 = (Point3)r.restore();
+ p.moveTo(p1);
+ p.setFarCorner(p2);
+ Point3 p3 = (Point3)r.restore();
+ Point3 p4 = (Point3)r.restore();
+ URL wname = URL.restore(r);
+ String rname = r.restoreString();
+ p.connectTo(wname, rname, p3, p4);
+ switch (vers) {
+ case 0:
+ r.setOldFlag();
+ r.restoreBoolean();
+ dlRepresentation = (WObject)r.restoreMaybeNull();
+ initialRepresentation = (WObject)r.restoreMaybeNull();
+ r.restoreMaybeNull();
+ break;
+ case 1:
+ dlRepresentation = (WObject)r.restoreMaybeNull();
+ initialRepresentation = (WObject)r.restoreMaybeNull();
+ break;
+ default:
+ throw new TooNewException();
+ }
+
+ if (initialRepresentation instanceof Surface) {
+ Surface s = (Surface)initialRepresentation;
+ Material m = s.getMaterial();
+ s.setMaterial(null);
+ p.setMaterial(m);
+ }
+
+ if (dlRepresentation instanceof Surface) {
+ Surface s = (Surface)dlRepresentation;
+ Material m = s.getMaterial();
+ s.setMaterial(null);
+ p.setMaterial(m);
+ }
+
+ if (initialRepresentation != null) {
+ for (Enumeration en = initialRepresentation.getHandlers(); en.hasMoreElements(); en = initialRepresentation.getHandlers()) {
+ SuperRoot h = (SuperRoot)en.nextElement();
+ initialRepresentation.removeHandler(h);
+ p.addHandler(h);
+ }
+ }
+ }
+}
diff --git a/NET/worlds/scape/RemoveObjectAction.java b/NET/worlds/scape/RemoveObjectAction.java
new file mode 100644
index 0000000..73526a6
--- /dev/null
+++ b/NET/worlds/scape/RemoveObjectAction.java
@@ -0,0 +1,72 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+import java.util.Vector;
+
+public class RemoveObjectAction extends SetPropertyAction {
+ private SuperRoot _value;
+ private static Object classCookie = new Object();
+
+ @Override
+ public Persister trigger(Event e, Persister seqID) {
+ assert !this.useParam();
+
+ this.remove(this._value);
+ return null;
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ VectorProperty vp = new VectorProperty(this, index, "Object to Remove");
+ SuperRoot target = this.getTarget();
+ if (this._value == null && target != null) {
+ ret = ObjectPropertyAdder.make(vp, target, "NET.worlds.scape.SuperRoot");
+ } else {
+ vp.allowSetNull();
+ ret = vp;
+ }
+ } else if (mode == 1) {
+ ret = new Vector(1);
+ if (this._value != null) {
+ ((Vector)ret).addElement(this._value);
+ }
+ } else if (mode == 4) {
+ assert value == this._value;
+
+ this._value = null;
+ } else if (mode == 3) {
+ assert this._value == null;
+
+ this._value = (SuperRoot)value;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 1, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(1, classCookie);
+ super.saveState(s);
+ s.saveMaybeNull(this._value);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 1:
+ super.restoreState(r);
+ this._value = (SuperRoot)r.restoreMaybeNull();
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/RenderWare.java b/NET/worlds/scape/RenderWare.java
new file mode 100644
index 0000000..8c811f3
--- /dev/null
+++ b/NET/worlds/scape/RenderWare.java
@@ -0,0 +1,7 @@
+package NET.worlds.scape;
+
+public class RenderWare {
+ public static native boolean get3DHardwareInUse();
+
+ public static native boolean get3DHardwareAvailable();
+}
diff --git a/NET/worlds/scape/Restorer.java b/NET/worlds/scape/Restorer.java
new file mode 100644
index 0000000..fa1e774
--- /dev/null
+++ b/NET/worlds/scape/Restorer.java
@@ -0,0 +1,430 @@
+package NET.worlds.scape;
+
+import NET.worlds.core.IniFile;
+import NET.worlds.network.URL;
+import java.io.DataInput;
+import java.io.DataInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+public class Restorer {
+ private DataInput is;
+ private boolean myFile;
+ private Hashtable<Integer, Class<?>> classTable;
+ private Hashtable<Object, Persister> objectTable;
+ private Hashtable<Object, Integer> cookieTable;
+ private URL reference;
+ private int _version;
+ private boolean _oldFlag;
+ private int _dblevel = 0;
+ private Integer _firstRead = null;
+
+ public URL getReferenceURL() {
+ return this.reference;
+ }
+
+ public final int version() {
+ return this._version;
+ }
+
+ private Restorer(String fileName) throws IOException, BadFormatException, TooNewException {
+ this(new DataInputStream(new FileInputStream(new File(fileName))));
+ if (this._dblevel > 0) {
+ System.out.println("Restoring from " + fileName);
+ }
+
+ this.myFile = true;
+ }
+
+ public Restorer(String fileName, URL url) throws IOException, BadFormatException, TooNewException {
+ this(fileName);
+ this.reference = url;
+ }
+
+ public Restorer(URL url) throws IOException, BadFormatException, TooNewException {
+ this(url.unalias(), url);
+ }
+
+ public Restorer(DataInput is) throws IOException, BadFormatException, TooNewException {
+ this.is = is;
+ this._dblevel = IniFile.gamma().getIniInt("RESTORE_DEBUG", 0);
+ String header = this.restoreString();
+ if (header != null && header.equals("PERSISTER Worlds, Inc.")) {
+ this._version = this.restoreInt();
+ if (this._dblevel > 0) {
+ System.out.println("Persister version " + this._version + " {");
+ }
+
+ if (this._version < 1) {
+ throw new BadFormatException();
+ } else if (this._version > Saver.version()) {
+ throw new TooNewException();
+ } else {
+ this.classTable = new Hashtable<Integer, Class<?>>();
+ this.objectTable = new Hashtable<Object, Persister>();
+ this.cookieTable = new Hashtable<Object, Integer>();
+ }
+ } else {
+ throw new BadFormatException();
+ }
+ }
+
+ public Restorer(DataInput is, URL url) throws IOException, BadFormatException, TooNewException {
+ this(is);
+ this.reference = url;
+ }
+
+ public int restoreVersion(Object cookie) throws IOException {
+ if (this._version == 1) {
+ return 0;
+ } else {
+ Integer oldv = this.cookieTable.get(cookie);
+ int v;
+ if (oldv == null) {
+ v = this.restoreInt();
+ this.cookieTable.put(cookie, new Integer(v));
+ } else {
+ v = oldv;
+ }
+
+ return v;
+ }
+ }
+
+ public Persister restore() throws IOException, TooNewException {
+ return this.restore(true);
+ }
+
+ public Persister restore(boolean restoreContents) throws IOException, TooNewException {
+ boolean firstCall = this._firstRead == null;
+ Integer hc = new Integer(this.restoreInt());
+ if (this._dblevel > 0) {
+ System.out.print("Object:" + Integer.toString(hc, 16));
+ }
+
+ if (this.objectTable.containsKey(hc)) {
+ Persister obj = this.objectTable.get(hc);
+ if (this._dblevel > 0) {
+ System.out.println(" - old: " + obj.getClass().getName() + " (" + Integer.toString(hc, 16) + ")");
+ }
+
+ return obj;
+ } else {
+ Persister p = null;
+
+ try {
+ Class<?> c = this.restoreClass(true);
+ if (this._dblevel > 0) {
+ System.out.println(" {");
+ }
+
+ try {
+ p = (Persister)c.newInstance();
+ } catch (NoSuchMethodError var7) {
+ System.out.println(c);
+ var7.printStackTrace(System.out);
+ throw var7;
+ }
+ } catch (InstantiationException var8) {
+ var8.printStackTrace(System.out);
+
+ assert false;
+ } catch (IllegalAccessException var9) {
+ var9.printStackTrace(System.out);
+
+ assert false;
+ }
+
+ this.objectTable.put(hc, p);
+ if (restoreContents) {
+ p.restoreState(this);
+ }
+
+ if (this._dblevel > 0) {
+ System.out.println((restoreContents ? "} Done with: " : "} Created: ") + Integer.toString(hc, 16));
+ }
+
+ Persister obj = this.objectTable.get(hc);
+ if (firstCall) {
+ this._firstRead = hc;
+ }
+
+ return obj;
+ }
+ }
+
+ public Vector<Object> restoreVectorMaybeNull() throws IOException, TooNewException {
+ return this.restoreBoolean() ? this.restoreVector() : null;
+ }
+
+ public Persister restoreMaybeNull() throws IOException, TooNewException {
+ if (this.restoreBoolean()) {
+ if (this._dblevel > 0) {
+ System.out.println("null");
+ }
+
+ return null;
+ } else {
+ return this.restore();
+ }
+ }
+
+ public Class<?> restoreClass() throws IOException {
+ return this.restoreClass(true);
+ }
+
+ public Class<?> restoreClass(boolean printdebug) throws IOException {
+ Class<?> c = null;
+ Integer classhc = new Integer(this.restoreInt());
+ if (this.classTable.containsKey(classhc)) {
+ c = this.classTable.get(classhc);
+ if (this._dblevel > 0 && printdebug) {
+ System.out.print("..." + c.getName() + " [" + Integer.toString(classhc, 16) + "]");
+ }
+ } else {
+ String s = this.restoreString();
+ if (this._dblevel > 0 && printdebug) {
+ System.out.print("---" + s + " [" + Integer.toString(classhc, 16) + "]");
+ }
+
+ try {
+ c = Class.forName(s);
+ } catch (ClassNotFoundException var8) {
+ try {
+ if (s.equals("NET.worlds.network.World")) {
+ if (this._dblevel > 0) {
+ System.out.print(" (Converting NET.worlds.network.World to NET.worlds.scape.World)");
+ }
+
+ c = Class.forName("NET.worlds.scape.World");
+ } else {
+ if (this._dblevel > 0) {
+ System.out.print(" (Converting " + s + " to NET.worlds.scape." + s + ")");
+ }
+
+ c = Class.forName("NET.worlds.scape." + s);
+ }
+ } catch (ClassNotFoundException var7) {
+ throw new Error("Can't find class " + s);
+ }
+ }
+
+ this.classTable.put(classhc, c);
+ }
+
+ return c;
+ }
+
+ private native Object makeArray(Class<?> var1, int var2);
+
+ public Persister[] restoreArray() throws IOException, TooNewException {
+ Class<?> arrayclass = null;
+ if (this._version > 4) {
+ arrayclass = this.restoreClass(false);
+ }
+
+ int length = this.restoreInt();
+ Persister[] pa = (Persister[])null;
+ if (arrayclass == null) {
+ if (this._dblevel > 0) {
+ System.out.println("Array of " + Integer.toString(length, 16) + " items {");
+ }
+
+ pa = new Persister[length];
+ } else {
+ String classname = arrayclass.getName();
+
+ assert classname.startsWith("[L");
+
+ assert classname.endsWith(";");
+
+ classname = classname.substring(2);
+ classname = classname.substring(0, classname.length() - 1);
+ if (this._dblevel > 0) {
+ System.out.println("Array of " + Integer.toString(length, 16) + " " + classname + " {");
+ }
+
+ try {
+ arrayclass = Class.forName(classname);
+ } catch (ClassNotFoundException var6) {
+ throw new Error("Can't find class " + classname.substring(1));
+ }
+
+ Object ob = this.makeArray(arrayclass, length);
+ pa = (Persister[])ob;
+ }
+
+ for (int i = 0; i < length; i++) {
+ pa[i] = this.restoreMaybeNull();
+ }
+
+ if (this._dblevel > 0) {
+ System.out.println("} Done with array");
+ }
+
+ return pa;
+ }
+
+ public Vector<Object> restoreVector() throws IOException, TooNewException {
+ int length = this.restoreInt();
+ if (this._dblevel > 0) {
+ System.out.println("Vector of " + Integer.toString(length, 16) + " items {");
+ }
+
+ Vector<Object> v = new Vector<Object>(length);
+
+ for (int i = 0; i < length; i++) {
+ v.addElement(this.restore());
+ }
+
+ if (this._dblevel > 0) {
+ System.out.println("} Done with vector");
+ }
+
+ return v;
+ }
+
+ public Vector<SuperRoot> restoreVectorSuperRoot() throws IOException, TooNewException {
+ int length = this.restoreInt();
+ if (this._dblevel > 0) {
+ System.out.println("Vector of " + Integer.toString(length, 16) + " items {");
+ }
+
+ Vector<SuperRoot> v = new Vector<SuperRoot>(length);
+
+ for (int i = 0; i < length; i++) {
+ v.addElement((SuperRoot)this.restore());
+ }
+
+ if (this._dblevel > 0) {
+ System.out.println("} Done with vector");
+ }
+
+ return v;
+ }
+
+ public Vector<Action> restoreVectorActions() throws IOException, TooNewException {
+ int length = this.restoreInt();
+ if (this._dblevel > 0) {
+ System.out.println("Vector of " + Integer.toString(length, 16) + " items {");
+ }
+
+ Vector<Action> v = new Vector<Action>(length);
+
+ for (int i = 0; i < length; i++) {
+ v.addElement((Action)this.restore());
+ }
+
+ if (this._dblevel > 0) {
+ System.out.println("} Done with vector");
+ }
+
+ return v;
+ }
+
+ public String restoreString() throws IOException {
+ return this.restoreBoolean() ? null : this.is.readUTF();
+ }
+
+ public boolean restoreBoolean() throws IOException {
+ return this.is.readBoolean();
+ }
+
+ public byte restoreByte() throws IOException {
+ return this.is.readByte();
+ }
+
+ public short restoreShort() throws IOException {
+ return this.is.readShort();
+ }
+
+ public int restoreInt() throws IOException {
+ return this.is.readInt();
+ }
+
+ public long restoreLong() throws IOException {
+ return this.is.readLong();
+ }
+
+ public float restoreFloat() throws IOException {
+ return this.is.readFloat();
+ }
+
+ public double restoreDouble() throws IOException {
+ return this.is.readDouble();
+ }
+
+ public void done() throws IOException, Error {
+ if (this._dblevel > 0) {
+ System.out.println("Calling all postRestores");
+ }
+
+ Enumeration<Persister> e = this.objectTable.elements();
+
+ while (e.hasMoreElements()) {
+ Persister p = e.nextElement();
+ p.postRestore(this._version);
+ }
+
+ e = this.objectTable.elements();
+
+ while (e.hasMoreElements()) {
+ Object obj = e.nextElement();
+ if (obj != this.objectTable.get(this._firstRead) && obj instanceof SuperRoot) {
+ SuperRoot s = (SuperRoot)obj;
+ if (s.getOwner() == null) {
+ System.out.println("Warning: " + s.getName() + " was not owned by any object.");
+ s.finalize();
+ }
+ }
+ }
+
+ String trailer = this.restoreString();
+ if (!trailer.equals("END PERSISTER")) {
+ throw new Error("Format error in save file");
+ } else {
+ if (this.myFile) {
+ ((DataInputStream)this.is).close();
+ }
+
+ this.classTable = null;
+ this.objectTable = null;
+ this.cookieTable = null;
+ if (this._dblevel > 0) {
+ System.out.println("} Done with persister");
+ }
+ }
+ }
+
+ public void setOldFlag() {
+ this._oldFlag = true;
+ if (this._dblevel > 0) {
+ System.out.println("----OLD!----");
+ }
+ }
+
+ public boolean oldFlag() {
+ return this._oldFlag;
+ }
+
+ public void replace(Persister old, Persister replacement) {
+ System.out.println("Converting a " + old.getClass().getName() + " to a " + replacement.getClass().getName());
+ boolean found = false;
+ Enumeration<Object> oe = this.objectTable.keys();
+
+ while (oe.hasMoreElements()) {
+ Object k = oe.nextElement();
+ if (this.objectTable.get(k) == old) {
+ this.objectTable.put(k, replacement);
+ found = true;
+ break;
+ }
+ }
+
+ assert found;
+ }
+}
diff --git a/NET/worlds/scape/RollBehavior.java b/NET/worlds/scape/RollBehavior.java
new file mode 100644
index 0000000..19f5865
--- /dev/null
+++ b/NET/worlds/scape/RollBehavior.java
@@ -0,0 +1,79 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+public class RollBehavior extends VelocityBehavior {
+ public float rollFactor;
+ private long lastTime;
+ private float bumpFraction;
+ private static Object classCookie = new Object();
+
+ public RollBehavior(Point3Temp vel, float diameter) {
+ super(vel, 0.0F, Point3Temp.make(0.0F, 0.0F, 1.0F), 0.0F, 0.0F);
+ this.rollFactor = 360.0F / (3.1416F * diameter);
+ }
+
+ public RollBehavior() {
+ }
+
+ @Override
+ public boolean handle(FrameEvent e) {
+ float vel = this.linearVel;
+ float dT = (float)(e.time - this.lastTime) / 1000.0F;
+ this.bumpFraction = 1.0F;
+ super.handle(e);
+ if (vel != 0.0F && this.lastTime != 0L) {
+ e.receiver.worldSpin(-this.dir.y, this.dir.x, this.dir.z, this.dir.length() * dT * vel * this.rollFactor * this.bumpFraction);
+ }
+
+ this.lastTime = e.time;
+ return true;
+ }
+
+ @Override
+ public boolean handle(BumpEventTemp b) {
+ this.bumpFraction = b.fraction;
+ return super.handle(b);
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Roll Factor"));
+ } else if (mode == 1) {
+ ret = new Float(this.rollFactor);
+ } else if (mode == 2) {
+ this.rollFactor = (Float)value;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 1, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(0, classCookie);
+ super.saveState(s);
+ s.saveFloat(this.rollFactor);
+ s.saveFloat(this.bumpFraction);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ this.rollFactor = r.restoreFloat();
+ this.bumpFraction = r.restoreFloat();
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/RollWidget.java b/NET/worlds/scape/RollWidget.java
new file mode 100644
index 0000000..e9e71b4
--- /dev/null
+++ b/NET/worlds/scape/RollWidget.java
@@ -0,0 +1,21 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+
+class RollWidget extends WidgetButton {
+ public RollWidget(ToolBar toolbar) {
+ super(toolbar, "roll.gif", Console.message("Roll"));
+ }
+
+ @Override
+ public String drag(boolean initialDrag, float deltax, float deltay) {
+ if (Math.abs(deltay) > Math.abs(deltax)) {
+ deltax = 0.0F;
+ }
+
+ Transform t = Transform.make();
+ this.applyWorldTransform(initialDrag, t.spin(this.getWorldAxis(0, 1, 0), deltax));
+ t.recycle();
+ return "Roll";
+ }
+}
diff --git a/NET/worlds/scape/RollingAttribute.java b/NET/worlds/scape/RollingAttribute.java
new file mode 100644
index 0000000..5293818
--- /dev/null
+++ b/NET/worlds/scape/RollingAttribute.java
@@ -0,0 +1,188 @@
+package NET.worlds.scape;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class RollingAttribute extends Attribute {
+ RollBehavior rb = new RollBehavior();
+ public float initialKickVel = 200.0F;
+ private Point3 kp = new Point3();
+ private float kv = 0.0F;
+ private Point3 kd = new Point3();
+ private static Object classCookie = new Object();
+
+ public RollingAttribute(int attrID) {
+ super(attrID);
+ this.rb.linearDamp = 0.95F;
+ this.rb.rollFactor = 1.0F;
+ this.rb.setNotifyAttribute(this);
+ }
+
+ public RollingAttribute() {
+ this.rb.linearDamp = 0.8F;
+ this.rb.setNotifyAttribute(this);
+ }
+
+ public void set(Point3Temp p, float v, Point3Temp d) {
+ if (this.kp.x != p.x || this.kp.y != p.y || this.kp.x != p.z) {
+ this.kp.x = p.x;
+ this.kp.y = p.y;
+ this.kp.z = p.z;
+ this.kv = v;
+ this.kd.x = d.x;
+ this.kd.y = d.y;
+ this.kd.z = d.z;
+ ((WObject)this.getOwner().getOwner()).moveTo(this.kp);
+ this.rb.linearVel = this.kv;
+ this.rb.setDir(this.kd);
+ this.noteChange();
+ }
+ }
+
+ public void notifyStopped() {
+ WObject ball = (WObject)((Sharer)this.getOwner()).getOwner();
+ Point3Temp pos = ball.getPosition();
+ this.set(pos, 0.0F, Point3Temp.make(0.0F, 0.0F, 0.0F));
+ }
+
+ public void get(Point3Temp p, float v, Point3Temp d) {
+ p.x = this.kp.x;
+ p.y = this.kp.y;
+ p.z = this.kp.z;
+ v = this.kv;
+ d.x = this.kd.x;
+ d.y = this.kd.y;
+ d.z = this.kd.z;
+ }
+
+ @Override
+ protected void noteAddingTo(SuperRoot owner) {
+ WObject parent = (WObject)owner.getOwner();
+ parent.addHandler(this.rb);
+ }
+
+ public boolean handle(BumpEventTemp b) {
+ if (b.target == b.receiver && !(this.rb.linearVel > 0.0F)) {
+ if (this.rb.linearVel == 0.0F) {
+ Point3Temp pos = b.target.getWorldPosition();
+ WObject kicker = (WObject)b.source;
+ float alpha = kicker.getYaw();
+ Point3Temp kpos = kicker.getWorldPosition();
+ double dx = kpos.x - pos.x;
+ double dy = kpos.y - pos.y;
+ Math.atan2(dx, dy);
+ float kickang = (float)((360.0F - alpha + 90.0F) * Math.PI / 180.0);
+ Point3Temp kickdir = Point3Temp.make((float)Math.cos(kickang), (float)Math.sin(kickang), 0.0F);
+ pos.x = pos.x + kickdir.x;
+ pos.y = pos.y + kickdir.y;
+ this.set(pos, this.initialKickVel, kickdir);
+ }
+ } else {
+ if (b.target instanceof Camera) {
+ double dx = this.rb.dir.x;
+ double dy = this.rb.dir.y;
+ Math.atan2(dx, dy);
+ double theta = dy + 60.0 * Math.random() - 30.0;
+ double var12 = dx * Math.cos(theta * Math.PI / 180.0);
+ dy = dx * Math.sin(theta * Math.PI / 180.0);
+ this.rb.dir.x = (float)var12;
+ this.rb.dir.y = (float)dy;
+ }
+
+ this.rb.processBumpEvent(b);
+ if (b.target instanceof Camera || b.source instanceof Camera) {
+ Point3Temp pos = ((WObject)((Sharer)this.getOwner()).getOwner()).getWorldPosition();
+ this.set(pos, this.rb.linearVel, this.rb.dir);
+ }
+ }
+
+ return true;
+ }
+
+ @Override
+ public void generateNetData(DataOutputStream s) throws IOException {
+ s.writeFloat(this.kp.x);
+ s.writeFloat(this.kp.y);
+ s.writeFloat(this.kp.z);
+ s.writeFloat(this.kv);
+ s.writeFloat(this.kd.x);
+ s.writeFloat(this.kd.y);
+ s.writeFloat(this.kd.z);
+ }
+
+ @Override
+ public void setFromNetData(DataInputStream ds, int len) throws IOException {
+ Point3Temp pos = Point3Temp.make();
+ float vel = 0.0F;
+ Point3Temp dir = Point3Temp.make();
+ pos.x = ds.readFloat();
+ pos.y = ds.readFloat();
+ pos.z = ds.readFloat();
+ vel = ds.readFloat();
+ dir.x = ds.readFloat();
+ dir.y = ds.readFloat();
+ dir.z = ds.readFloat();
+ this.set(pos, vel, dir);
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Roll Factor"));
+ } else if (mode == 1) {
+ ret = new Float(this.rb.rollFactor);
+ } else if (mode == 2) {
+ this.rb.rollFactor = (Float)value;
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Initial Kick Velocity"));
+ } else if (mode == 1) {
+ ret = new Float(this.initialKickVel);
+ } else if (mode == 2) {
+ this.initialKickVel = (Float)value;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 2, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(1, classCookie);
+ super.saveState(s);
+ s.saveFloat(this.initialKickVel);
+ s.saveFloat(this.rb.rollFactor);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ this.initialKickVel = r.restoreFloat();
+ float threshold = r.restoreFloat();
+ break;
+ case 1:
+ super.restoreState(r);
+ this.initialKickVel = r.restoreFloat();
+ this.rb.rollFactor = r.restoreFloat();
+ break;
+ default:
+ throw new TooNewException();
+ }
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + " [From " + this.kp + " with velocity " + this.kv + " toward " + this.kd + "] ";
+ }
+}
diff --git a/NET/worlds/scape/Room.java b/NET/worlds/scape/Room.java
new file mode 100644
index 0000000..a10305c
--- /dev/null
+++ b/NET/worlds/scape/Room.java
@@ -0,0 +1,996 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Main;
+import NET.worlds.core.Std;
+import NET.worlds.network.Galaxy;
+import NET.worlds.network.NetworkRoom;
+import java.awt.Color;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Vector;
+
+public class Room extends WObject implements TeleportStatus {
+ public WObject highlightTarget;
+ private int sceneID;
+ public Point3 defaultPosition = new Point3(100.0F, 100.0F, 120.0F);
+ public Point3 defaultOrientationAxis = new Point3(0.0F, 0.0F, -1.0F);
+ public float defaultOrientation = 0.0F;
+ String teleportChain = "home:avatargallery/avatar.world#[email protected],145.0,150.0,89.0";
+ int roomLoadTime = 0;
+ int teleportInterval = -1;
+ boolean teleported = false;
+ private RoomEnvironment environment;
+ private Vector<Portal> outgoingPortals = new Vector<Portal>();
+ private Vector<AudibilityFilter> aFilters = new Vector<AudibilityFilter>();
+ private Point3 lightPosition = new Point3(-1.0F, 1.0F, -1.0F);
+ private Color lightColor = new Color(255, 255, 255);
+ private int lightid = 0;
+ private int lightid2 = 0;
+ private int renderStamp;
+ private static int timeoutAge = 15000;
+ private Vector<FrameHandler> frameHandlers = new Vector<FrameHandler>();
+ private Vector<WObject> frameHandlerWObjects = new Vector<WObject>();
+ private Color skyColor;
+ private Color groundColor;
+ private Vector<Prerenderable> prerenderHandlers = new Vector<Prerenderable>();
+ private Vector<Postrenderable> postrenderHandlers = new Vector<Postrenderable>();
+ private static int isRendering = 4;
+ private static int isVIPOnly = 262144;
+ private static int isVIPViewOnly = 524288;
+ private NetworkRoom _netRoom;
+ private static String[] skyOptions = new String[]{"Blue Sky"};
+ private static String[] groundOptions = new String[]{"Green Ground"};
+ private boolean allowTeleport = true;
+ private static Object classCookie = new Object();
+ private RoomEnvironment infiniteBackground;
+
+ static {
+ nativeInit();
+ }
+
+ public Room(World world, String name) {
+ this.setName(name);
+ this.environment = new RoomEnvironment();
+ this.infiniteBackground = new RoomEnvironment();
+ super.add(this.environment);
+ super.add(this.infiniteBackground);
+ if (world != null) {
+ world.addRoom(this);
+ }
+ }
+
+ public Room() {
+ }
+
+ public static native void nativeInit();
+
+ @Override
+ public void getChildren(DeepEnumeration d) {
+ if (this.infiniteBackground != null) {
+ d.addChildElement(this.infiniteBackground);
+ }
+
+ if (this.environment != null) {
+ d.addChildElement(this.environment);
+ }
+
+ super.getChildren(d);
+ }
+
+ @Override
+ public void setName(String newName) {
+ String oldName = this.getName();
+ super.setName(newName);
+ World world = this.getWorld();
+ if (world != null) {
+ world.renameRoom(oldName, this.getName(), this);
+ }
+
+ if (!oldName.equals(newName)) {
+ synchronized (this) {
+ if (this._netRoom != null) {
+ this._netRoom.setName(newName);
+ }
+ }
+ }
+ }
+
+ synchronized void register() {
+ assert this._netRoom == null;
+
+ this._netRoom = new NetworkRoom(this);
+ }
+
+ @Override
+ public void detach() {
+ if (this.hasClump()) {
+ System.out.println("Detaching clumped room " + this.getName());
+ this.markVoid();
+ }
+
+ assert this._netRoom != null;
+
+ boolean subscribed = Pilot.getActive().removeSubscribedRoom(this);
+ if (subscribed) {
+ this._netRoom.unsubscribe();
+ }
+
+ synchronized (this) {
+ this._netRoom.detach();
+ this._netRoom = null;
+ }
+
+ this.getWorld().removeRoom(this);
+ super.detach();
+ }
+
+ @Override
+ public void discard() {
+ this.environment.discard();
+ this.infiniteBackground.discard();
+ super.discard();
+ this.frameHandlers.removeAllElements();
+ this.frameHandlerWObjects.removeAllElements();
+ this.outgoingPortals.removeAllElements();
+ this.aFilters.removeAllElements();
+ this.prerenderHandlers.removeAllElements();
+ this.postrenderHandlers.removeAllElements();
+ }
+
+ int getSceneID() {
+ return this.sceneID;
+ }
+
+ public Point3Temp getDefaultPosition() {
+ return Point3Temp.make(this.defaultPosition);
+ }
+
+ public Point3Temp getDefaultOrientationAxis() {
+ return Point3Temp.make(this.defaultOrientationAxis);
+ }
+
+ public float getDefaultOrientation() {
+ return this.defaultOrientation;
+ }
+
+ @Override
+ protected final void noteAddingTo(SuperRoot s) {
+ World w = (World)s;
+ }
+
+ public RoomEnvironment getEnvironment() {
+ return this.environment;
+ }
+
+ public Vector<Portal> getOutgoingPortals() {
+ return this.outgoingPortals;
+ }
+
+ public void addOutgoingPortal(Portal p) {
+ if (!this.outgoingPortals.contains(p)) {
+ this.outgoingPortals.addElement(p);
+
+ for (int index = 0; index < this.aFilters.size(); index++) {
+ this.aFilters.elementAt(index).moveEmitter();
+ }
+ }
+ }
+
+ public void removeOutgoingPortal(Portal p) {
+ this.outgoingPortals.removeElement(p);
+ Vector<AudibilityFilter> v = this.getAFilters();
+
+ for (int v_index = 0; v_index < v.size(); v_index++) {
+ v.elementAt(v_index).moveEmitter();
+ }
+ }
+
+ public Vector<AudibilityFilter> getAFilters() {
+ return this.aFilters;
+ }
+
+ public void addAFilter(AudibilityFilter p) {
+ this.aFilters.addElement(p);
+ }
+
+ public void removeAFilter(AudibilityFilter a) {
+ this.aFilters.removeElement(a);
+ }
+
+ public void move(Room from, Room to) {
+ Vector<AudibilityFilter> v = from.getAFilters();
+
+ for (int index = 0; index < v.size(); index++) {
+ v.elementAt(index).updateListenerState();
+ }
+
+ v = to.getAFilters();
+
+ for (int index = 0; index < v.size(); index++) {
+ v.elementAt(index).updateListenerState();
+ }
+ }
+
+ static native int addLight(int var0, float var1, float var2, float var3, float var4, float var5, float var6);
+
+ static native void setLightPosition(int var0, float var1, float var2, float var3);
+
+ static native void setLightColor(int var0, float var1, float var2, float var3);
+
+ private void setLightPosition(float x, float y, float z) {
+ if (this.lightid != 0) {
+ setLightPosition(this.lightid, x, y, z);
+ }
+
+ if (this.lightid2 != 0) {
+ setLightPosition(this.lightid2, -x, -y, -z);
+ }
+ }
+
+ private void setLightColor(float red, float green, float blue) {
+ if (this.lightid != 0) {
+ setLightColor(this.lightid, red, green, blue);
+ }
+
+ if (this.lightid2 != 0) {
+ setLightColor(this.lightid2, red / 2.0F, green / 2.0F, blue / 2.0F);
+ }
+ }
+
+ public void setLightPosition(Point3Temp p) {
+ this.lightPosition.set(p.x, p.y, p.z);
+ this.setLightPosition(p.x, p.y, p.z);
+ RoomEnvironment re = this.getEnvironment();
+ if (re != null) {
+ re.setLightPosition(p.x, p.y, p.z);
+ }
+
+ re = this.getInfiniteBackground();
+ if (re != null) {
+ re.setLightPosition(p.x, p.y, p.z);
+ }
+ }
+
+ public void setLightColor(Color c) {
+ this.lightColor = new Color(c.getRGB());
+ float r = c.getRed() / 256.0F;
+ float g = c.getGreen() / 256.0F;
+ float b = c.getBlue() / 256.0F;
+ this.setLightColor(r, g, b);
+ RoomEnvironment re = this.getEnvironment();
+ if (re != null) {
+ re.setLightColor(r, g, b);
+ }
+
+ re = this.getInfiniteBackground();
+ if (re != null) {
+ re.setLightColor(r, g, b);
+ }
+ }
+
+ public Point3Temp getLightPosition() {
+ return Point3Temp.make(this.lightPosition);
+ }
+
+ public Color getLightColor() {
+ return new Color(this.lightColor.getRGB());
+ }
+
+ public void noteRef() {
+ this.renderStamp = Std.getRealTime();
+ World w = this.getWorld();
+ if (w != null) {
+ w.incRef();
+ }
+ }
+
+ public void discardIfOld() {
+ if (this.hasClump()) {
+ int age = Std.getFastTime() - this.renderStamp;
+ if (age > timeoutAge) {
+ this.markVoid();
+ }
+ }
+ }
+
+ public void generateFrameEvents(FrameEvent f) {
+ this.noteRef();
+ if (Main.profile != 0) {
+ for (int i = 0; i < this.frameHandlers.size(); i++) {
+ FrameHandler fh = this.frameHandlers.elementAt(i);
+ WObject fhw = this.frameHandlerWObjects.elementAt(i);
+ int start = Std.getRealTime();
+ long startBytes = Runtime.getRuntime().freeMemory();
+ f.retargetAndDeliver(fh, fhw);
+ int dur = Std.getRealTime() - start;
+ long used = startBytes - Runtime.getRuntime().freeMemory();
+ if (dur > Main.profile) {
+ if (fh instanceof SuperRoot) {
+ System.out.println("Took " + dur + "ms and " + used + " bytes to call frameHandler " + ((SuperRoot)fh).getName() + " of " + fhw.getName());
+ } else {
+ System.out.println("Took " + dur + "ms and " + used + " bytes to call frameHandler " + fh + " of " + fhw.getName());
+ }
+ }
+ }
+ } else {
+ for (int ix = 0; ix < this.frameHandlers.size(); ix++) {
+ f.retargetAndDeliver(this.frameHandlers.elementAt(ix), this.frameHandlerWObjects.elementAt(ix));
+ }
+ }
+
+ if (this.teleportChain != null && this.teleportInterval != -1 && !this.teleported && Std.getSynchronizedTime() % this.teleportInterval == 0) {
+ this.teleported = true;
+ TeleportAction.teleport(this.teleportChain, this);
+ }
+ }
+
+ @Override
+ public void teleportStatus(String err, String dest) {
+ if (err != null) {
+ this.teleported = false;
+ }
+ }
+
+ private int findFrameHandler(FrameHandler h, WObject o) {
+ int next = 0;
+
+ while (true) {
+ next = this.frameHandlers.indexOf(h, next);
+ if (next == -1) {
+ return -1;
+ }
+
+ if (this.frameHandlerWObjects.elementAt(next) == o) {
+ return next;
+ }
+
+ next++;
+ }
+ }
+
+ void addFrameHandler(FrameHandler h, WObject o) {
+ int i = this.findFrameHandler(h, o);
+ if (i < 0) {
+ this.frameHandlers.addElement(h);
+ this.frameHandlerWObjects.addElement(o);
+ }
+ }
+
+ void removeFrameHandler(FrameHandler h, WObject o) {
+ int i = this.findFrameHandler(h, o);
+ if (i >= 0) {
+ this.frameHandlers.removeElementAt(i);
+ this.frameHandlerWObjects.removeElementAt(i);
+ }
+ }
+
+ native void createScene();
+
+ native void destroyScene();
+
+ @Override
+ protected void markVoid() {
+ this.infiniteBackground.markVoid();
+ this.environment.markVoid();
+ super.markVoid();
+ this.destroyScene();
+ this.lightid = 0;
+ this.lightid2 = 0;
+ }
+
+ @Override
+ protected void noteTransformChange() {
+ super.noteTransformChange();
+ this.getInfiniteBackground().setTransform(this);
+ this.getEnvironment().setTransform(this);
+ int i = this.outgoingPortals.size();
+
+ while (--i >= 0) {
+ this.outgoingPortals.elementAt(i).discardTransform();
+ }
+ }
+
+ public void setSkyColor(Color c) {
+ this.skyColor = c;
+ }
+
+ public Color getSkyColor() {
+ return this.skyColor;
+ }
+
+ public void setGroundColor(Color c) {
+ this.groundColor = c;
+ }
+
+ public Color getGroundColor() {
+ return this.groundColor;
+ }
+
+ public boolean getVIPOnly() {
+ return (this.flags & isVIPOnly) != 0;
+ }
+
+ public void prerender(Camera cam, float x, float y, float z, float d) {
+ this.flags = this.flags | isRendering;
+ this.infiniteBackground.prerender();
+ this.environment.prerender();
+ Pilot.addVisibleRoom(this, x, y, z, d);
+ int end = this.prerenderHandlers.size();
+
+ for (int i = 0; i < end; i++) {
+ Prerenderable p = this.prerenderHandlers.elementAt(i);
+ p.prerender(cam);
+ }
+ }
+
+ public void addPrerenderHandler(Prerenderable o) {
+ assert (this.flags & isRendering) == 0;
+
+ if (!this.prerenderHandlers.contains(o)) {
+ this.prerenderHandlers.addElement(o);
+ }
+ }
+
+ public void prependPrerenderHandler(Prerenderable o) {
+ assert (this.flags & isRendering) == 0;
+
+ if (!this.prerenderHandlers.contains(o)) {
+ this.prerenderHandlers.insertElementAt(o, 0);
+ }
+ }
+
+ public void removePrerenderHandler(Prerenderable o) {
+ assert (this.flags & isRendering) == 0;
+
+ this.prerenderHandlers.removeElement(o);
+ }
+
+ public void postrender(Camera cam, float x, float y, float z, float d) {
+ Pilot.addVisibleRoom(this, x, y, z, d);
+ int i = this.postrenderHandlers.size();
+
+ while (--i >= 0) {
+ Postrenderable p = this.postrenderHandlers.elementAt(i);
+ p.postrender(cam);
+ }
+
+ this.flags = this.flags & ~isRendering;
+ }
+
+ public void addPostrenderHandler(Postrenderable o) {
+ assert (this.flags & isRendering) == 0;
+
+ if (!this.postrenderHandlers.contains(o)) {
+ this.postrenderHandlers.addElement(o);
+ }
+ }
+
+ public void prependPostrenderHandler(Postrenderable o) {
+ assert (this.flags & isRendering) == 0;
+
+ if (!this.postrenderHandlers.contains(o)) {
+ this.postrenderHandlers.insertElementAt(o, 0);
+ }
+ }
+
+ public void removePostrenderHandler(Postrenderable o) {
+ assert (this.flags & isRendering) == 0;
+
+ this.postrenderHandlers.removeElement(o);
+ }
+
+ @Override
+ public void detectBump(BumpEventTemp b) {
+ if (this.environment.getBumpable()) {
+ this.environment.detectBump(b);
+ }
+
+ super.detectBump(b);
+ }
+
+ @Override
+ public BoundBoxTemp getBoundBox() {
+ return BoundBoxTemp.make(Point3Temp.make(), Point3Temp.make());
+ }
+
+ @Override
+ public World getWorld() {
+ return (World)this.getOwner();
+ }
+
+ @Override
+ public Room getRoom() {
+ return this;
+ }
+
+ @Override
+ public Room getRoomFromClump() {
+ return this;
+ }
+
+ @Override
+ public Room getRoomNotFromClump() {
+ return this;
+ }
+
+ public Galaxy getGalaxy() {
+ World w = this.getWorld();
+ return w == null ? null : w.getConsole().getGalaxy();
+ }
+
+ public String getURL() {
+ return this.getWorld().getSourceURL().getAbsolute() + "#" + this.getName();
+ }
+
+ public boolean registerShare(WObject w) {
+ w.notifyRegister(1);
+ return true;
+ }
+
+ private void processPendingRegistrations() {
+ this.notifyRegister(1);
+ }
+
+ public NetworkRoom getNetworkRoom() {
+ return this._netRoom;
+ }
+
+ void subscribe(RoomSubscribeInfo info) {
+ assert this._netRoom != null;
+
+ this._netRoom.subscribe(info);
+ }
+
+ void subscribeDist(RoomSubscribeInfo info) {
+ assert this._netRoom != null;
+
+ this._netRoom.subscribeDist(info);
+ }
+
+ void unsubscribe() {
+ if (this._netRoom != null) {
+ this._netRoom.unsubscribe();
+ } else {
+ System.out.println(this + ": unsubscribing from bad room?");
+ new Exception().printStackTrace(System.out);
+ }
+ }
+
+ public boolean getAllowTeleport() {
+ return this.allowTeleport;
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = new Property(this, index, "Environment");
+ } else if (mode == 1) {
+ ret = this.environment;
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = new Property(this, index, "Infinite Background");
+ } else if (mode == 1) {
+ ret = this.infiniteBackground;
+ }
+ break;
+ case 2:
+ if (mode == 0) {
+ ret = ColorPropertyEditor.make(new Property(this, index, "Sky Color").allowSetNull());
+ if (this.getSkyColor() == null) {
+ ret = MaybeNullPropertyEditor.make((Property)ret, Color.blue);
+ }
+ } else if (mode == 1) {
+ ret = this.getSkyColor();
+ } else if (mode == 2) {
+ this.setSkyColor((Color)value);
+ }
+ break;
+ case 3:
+ if (mode == 0) {
+ ret = ColorPropertyEditor.make(new Property(this, index, "Ground Color").allowSetNull());
+ if (this.getGroundColor() == null) {
+ ret = MaybeNullPropertyEditor.make((Property)ret, Color.green);
+ }
+ } else if (mode == 1) {
+ ret = this.getGroundColor();
+ } else if (mode == 2) {
+ this.setGroundColor((Color)value);
+ }
+ break;
+ case 4:
+ if (mode == 0) {
+ ret = Point3PropertyEditor.make(new Property(this, index, "Default Position"));
+ } else if (mode == 1) {
+ ret = new Point3(this.getDefaultPosition());
+ } else if (mode == 2) {
+ this.defaultPosition = (Point3)value;
+ }
+ break;
+ case 5:
+ if (mode == 0) {
+ ret = Point3PropertyEditor.make(new Property(this, index, "Default Orientation Axis"));
+ } else if (mode == 1) {
+ ret = new Point3(this.getDefaultOrientationAxis());
+ } else if (mode == 2) {
+ this.defaultOrientationAxis = (Point3)value;
+ }
+ break;
+ case 6:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Default Orientation Angle"));
+ } else if (mode == 1) {
+ ret = new Float(this.getDefaultOrientation());
+ } else if (mode == 2) {
+ this.defaultOrientation = (Float)value;
+ }
+ break;
+ case 7:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "VIP only"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean((this.flags & isVIPOnly) != 0);
+ } else if (mode == 2) {
+ if ((Boolean)value) {
+ this.flags = this.flags | isVIPOnly;
+ } else {
+ this.flags = this.flags & ~isVIPOnly;
+ }
+ }
+ break;
+ case 8:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Visible to VIP only"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean((this.flags & isVIPViewOnly) != 0);
+ } else if (mode == 2) {
+ if ((Boolean)value) {
+ this.flags = this.flags | isVIPViewOnly;
+ } else {
+ this.flags = this.flags & ~isVIPViewOnly;
+ }
+ }
+ break;
+ case 9:
+ if (mode == 0) {
+ ret = Point3PropertyEditor.make(new Property(this, index, "Light Source Direction"));
+ } else if (mode == 1) {
+ ret = this.lightPosition;
+ } else if (mode == 2) {
+ this.setLightPosition((Point3)value);
+ }
+ break;
+ case 10:
+ if (mode == 0) {
+ ret = ColorPropertyEditor.make(new Property(this, index, "Light Color"));
+ } else if (mode == 1) {
+ ret = this.lightColor;
+ } else if (mode == 2) {
+ this.setLightColor((Color)value);
+ }
+ break;
+ case 11:
+ if (mode == 0) {
+ ret = IntegerPropertyEditor.make(new Property(this, index, "Time To Auto-Teleport (seconds, -1 = never)"));
+ } else if (mode == 1) {
+ ret = new Integer(this.teleportInterval);
+ } else if (mode == 2) {
+ this.teleportInterval = (Integer)value;
+ }
+ break;
+ case 12:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Auto-Teleport destination"));
+ } else if (mode == 1) {
+ ret = this.teleportChain;
+ } else if (mode == 2) {
+ this.teleportChain = new String((String)value);
+ }
+ break;
+ case 13:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Allow Teleporting"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(this.allowTeleport);
+ } else if (mode == 2) {
+ this.allowTeleport = (Boolean)value;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 14, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(7, classCookie);
+ super.saveState(s);
+ if (this.skyColor != null) {
+ s.saveBoolean(true);
+ s.saveInt(this.skyColor.getRGB());
+ } else {
+ s.saveBoolean(false);
+ }
+
+ if (this.groundColor != null) {
+ s.saveBoolean(true);
+ s.saveInt(this.groundColor.getRGB());
+ } else {
+ s.saveBoolean(false);
+ }
+
+ s.save(this.defaultPosition);
+ s.save(this.defaultOrientationAxis);
+ s.saveFloat(this.defaultOrientation);
+ s.save(this.lightPosition);
+ s.saveInt(this.lightColor.getRGB());
+ s.save(this.environment);
+ s.save(this.infiniteBackground);
+ s.saveString(this.teleportChain);
+ s.saveInt(this.teleportInterval);
+ s.saveBoolean(this.allowTeleport);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ r.setOldFlag();
+ super.restoreState(r);
+ this.setName(r.restoreString());
+ r.restore();
+ if (r.restoreBoolean()) {
+ this.skyColor = new Color(r.restoreInt());
+ }
+
+ if (r.restoreBoolean()) {
+ this.groundColor = new Color(r.restoreInt());
+ }
+
+ r.restoreMaybeNull();
+ this.defaultPosition = (Point3)r.restore();
+ this.defaultOrientationAxis = (Point3)r.restore();
+ this.defaultOrientation = r.restoreFloat();
+ r.restoreVector();
+ this.environment = (RoomEnvironment)r.restore();
+ this.infiniteBackground = new RoomEnvironment();
+ break;
+ case 1:
+ r.setOldFlag();
+ super.restoreState(r);
+ r.restore();
+ if (r.restoreBoolean()) {
+ this.skyColor = new Color(r.restoreInt());
+ }
+
+ if (r.restoreBoolean()) {
+ this.groundColor = new Color(r.restoreInt());
+ }
+
+ r.restoreMaybeNull();
+ this.defaultPosition = (Point3)r.restore();
+ this.defaultOrientationAxis = (Point3)r.restore();
+ this.defaultOrientation = r.restoreFloat();
+ this.environment = (RoomEnvironment)r.restore();
+ this.infiniteBackground = new RoomEnvironment();
+ break;
+ case 2:
+ r.setOldFlag();
+ super.restoreState(r);
+ if (r.restoreBoolean()) {
+ this.skyColor = new Color(r.restoreInt());
+ }
+
+ if (r.restoreBoolean()) {
+ this.groundColor = new Color(r.restoreInt());
+ }
+
+ r.restoreMaybeNull();
+ this.defaultPosition = (Point3)r.restore();
+ this.defaultOrientationAxis = (Point3)r.restore();
+ this.defaultOrientation = r.restoreFloat();
+ this.environment = (RoomEnvironment)r.restore();
+ this.infiniteBackground = new RoomEnvironment();
+ break;
+ case 3:
+ r.setOldFlag();
+ super.restoreState(r);
+ if (r.restoreBoolean()) {
+ this.skyColor = new Color(r.restoreInt());
+ }
+
+ if (r.restoreBoolean()) {
+ this.groundColor = new Color(r.restoreInt());
+ }
+
+ r.restoreMaybeNull();
+ this.defaultPosition = (Point3)r.restore();
+ this.defaultOrientationAxis = (Point3)r.restore();
+ this.defaultOrientation = r.restoreFloat();
+ this.environment = (RoomEnvironment)r.restore();
+ this.infiniteBackground = (RoomEnvironment)r.restore();
+ break;
+ case 4:
+ r.setOldFlag();
+ super.restoreState(r);
+ if (r.restoreBoolean()) {
+ this.skyColor = new Color(r.restoreInt());
+ }
+
+ if (r.restoreBoolean()) {
+ this.groundColor = new Color(r.restoreInt());
+ }
+
+ this.defaultPosition = (Point3)r.restore();
+ this.defaultOrientationAxis = (Point3)r.restore();
+ this.defaultOrientation = r.restoreFloat();
+ this.environment = (RoomEnvironment)r.restore();
+ this.infiniteBackground = (RoomEnvironment)r.restore();
+ break;
+ case 5:
+ super.restoreState(r);
+ if (r.restoreBoolean()) {
+ this.skyColor = new Color(r.restoreInt());
+ }
+
+ if (r.restoreBoolean()) {
+ this.groundColor = new Color(r.restoreInt());
+ }
+
+ this.defaultPosition = (Point3)r.restore();
+ this.defaultOrientationAxis = (Point3)r.restore();
+ this.defaultOrientation = r.restoreFloat();
+ this.setLightPosition((Point3)r.restore());
+ this.setLightColor(new Color(r.restoreInt()));
+ this.environment = (RoomEnvironment)r.restore();
+ this.infiniteBackground = (RoomEnvironment)r.restore();
+ break;
+ case 6:
+ super.restoreState(r);
+ if (r.restoreBoolean()) {
+ this.skyColor = new Color(r.restoreInt());
+ }
+
+ if (r.restoreBoolean()) {
+ this.groundColor = new Color(r.restoreInt());
+ }
+
+ this.defaultPosition = (Point3)r.restore();
+ this.defaultOrientationAxis = (Point3)r.restore();
+ this.defaultOrientation = r.restoreFloat();
+ this.setLightPosition((Point3)r.restore());
+ this.setLightColor(new Color(r.restoreInt()));
+ this.environment = (RoomEnvironment)r.restore();
+ this.infiniteBackground = (RoomEnvironment)r.restore();
+ this.teleportChain = r.restoreString();
+ this.teleportInterval = r.restoreInt();
+ this.roomLoadTime = Std.getFastTime() / 1000;
+ break;
+ case 7:
+ super.restoreState(r);
+ if (r.restoreBoolean()) {
+ this.skyColor = new Color(r.restoreInt());
+ }
+
+ if (r.restoreBoolean()) {
+ this.groundColor = new Color(r.restoreInt());
+ }
+
+ this.defaultPosition = (Point3)r.restore();
+ this.defaultOrientationAxis = (Point3)r.restore();
+ this.defaultOrientation = r.restoreFloat();
+ this.setLightPosition((Point3)r.restore());
+ this.setLightColor(new Color(r.restoreInt()));
+ this.environment = (RoomEnvironment)r.restore();
+ this.infiniteBackground = (RoomEnvironment)r.restore();
+ this.teleportChain = r.restoreString();
+ this.teleportInterval = r.restoreInt();
+ this.roomLoadTime = Std.getFastTime() / 1000;
+ this.allowTeleport = r.restoreBoolean();
+ break;
+ default:
+ throw new TooNewException();
+ }
+
+ super.add(this.environment);
+ super.add(this.infiniteBackground);
+ }
+
+ public void aboutToDraw() {
+ if (!this.hasClump() && this.getOwner() instanceof World) {
+ this.recursiveAddRwChildren(null);
+ }
+ }
+
+ @Override
+ protected void addRwChildren(WObject parent) {
+ assert parent == null;
+
+ this.createClump();
+ this.createScene();
+ this.newRwChildHelper();
+ float red = this.lightColor.getRed() / 256.0F;
+ float green = this.lightColor.getGreen() / 256.0F;
+ float blue = this.lightColor.getBlue() / 256.0F;
+ this.lightid = addLight(this.sceneID, this.lightPosition.x, this.lightPosition.y, this.lightPosition.z, red, green, blue);
+ this.lightid2 = addLight(this.sceneID, -this.lightPosition.x, -this.lightPosition.y, -this.lightPosition.z, red * 0.5F, green * 0.5F, blue * 0.5F);
+ }
+
+ @Override
+ public void recursiveAddRwChildren(WObject parent) {
+ super.recursiveAddRwChildren(parent);
+ this.environment.recursiveAddRwChildren(this);
+ this.infiniteBackground.recursiveAddRwChildren(this);
+ }
+
+ public final float floorHeight(float x, float y) {
+ return this.floorHeight(x, y, 120.0F);
+ }
+
+ public float floorHeight(float x, float y, float z) {
+ Transform inverse = this.getObjectToWorldMatrix().invert();
+ Point3Temp p = Point3Temp.make(x, y, z).times(inverse);
+ inverse.recycle();
+ x = p.x;
+ y = p.y;
+ z = p.z;
+ float height = 0.0F;
+ boolean patchFound = false;
+ Enumeration<Object> e = (Enumeration<Object>)this.getContents();
+
+ while (e.hasMoreElements()) {
+ Object o = e.nextElement();
+ if (o instanceof FloorPatch && ((FloorPatch)o).inPatch(x, y)) {
+ float patchHeight = ((FloorPatch)o).floorHeight(x, y);
+ if (patchHeight <= z && (patchHeight > height || !patchFound)) {
+ patchFound = true;
+ height = ((FloorPatch)o).floorHeight(x, y);
+ }
+ }
+ }
+
+ return height;
+ }
+
+ public Point3 surfaceNormal(float x, float y, float z) {
+ Point3 normal = new Point3(0.0F, 0.0F, 1.0F);
+ FloorPatch patch = null;
+ float height = 0.0F;
+ boolean patchFound = false;
+ Enumeration<Object> e = (Enumeration<Object>)this.getContents();
+
+ while (e.hasMoreElements()) {
+ Object o = e.nextElement();
+ if (o instanceof FloorPatch && ((FloorPatch)o).inPatch(x, y)) {
+ float patchHeight = ((FloorPatch)o).floorHeight(x, y);
+ if (patchHeight <= z && (patchHeight > height || !patchFound)) {
+ patchFound = true;
+ height = ((FloorPatch)o).floorHeight(x, y);
+ patch = (FloorPatch)o;
+ }
+ }
+ }
+
+ if (patch != null) {
+ normal = patch.surfaceNormal(x, y);
+ }
+
+ normal.vectorTimes(this.getObjectToWorldMatrix());
+ return normal;
+ }
+
+ public RoomEnvironment getInfiniteBackground() {
+ return this.infiniteBackground;
+ }
+
+ @Override
+ public String toString() {
+ return this.getWorld() + "#" + this.getName();
+ }
+}
diff --git a/NET/worlds/scape/RoomEnvironment.java b/NET/worlds/scape/RoomEnvironment.java
new file mode 100644
index 0000000..18b1d1f
--- /dev/null
+++ b/NET/worlds/scape/RoomEnvironment.java
@@ -0,0 +1,116 @@
+package NET.worlds.scape;
+
+import java.awt.Color;
+import java.io.IOException;
+
+public class RoomEnvironment extends WObject {
+ private int lightid = 0;
+ private int lightid2 = 0;
+ int nextVertex = 1;
+ boolean wasEdited = false;
+ private static Object classCookie = new Object();
+ private int sceneID;
+
+ static {
+ nativeInit();
+ }
+
+ RoomEnvironment() {
+ }
+
+ public static native void nativeInit();
+
+ @Override
+ protected void addRwChildren(WObject parent) {
+ this.createClump();
+ Room r = (Room)this.getOwner();
+ this.createScene(r);
+ this.newRwChildHelper();
+ this.addLight(r.getLightPosition(), r.getLightColor());
+ }
+
+ @Override
+ protected void noteAddingTo(SuperRoot owner) {
+ Room r = (Room)owner;
+ }
+
+ private void addLight(Point3Temp pos, Color c) {
+ assert this.lightid == 0;
+
+ float red = c.getRed() / 256.0F;
+ float green = c.getGreen() / 256.0F;
+ float blue = c.getBlue() / 256.0F;
+ this.lightid = Room.addLight(this.sceneID, pos.x, pos.y, pos.z, red, green, blue);
+ this.lightid2 = Room.addLight(this.sceneID, -pos.x, -pos.y, -pos.z, red * 0.5F, green * 0.5F, blue * 0.5F);
+ }
+
+ void setLightPosition(float x, float y, float z) {
+ if (this.lightid != 0) {
+ Room.setLightPosition(this.lightid, x, y, z);
+ }
+
+ if (this.lightid2 != 0) {
+ Room.setLightPosition(this.lightid2, -x, -y, -z);
+ }
+ }
+
+ void setLightColor(float red, float green, float blue) {
+ if (this.lightid != 0) {
+ Room.setLightColor(this.lightid, red, green, blue);
+ }
+
+ if (this.lightid2 != 0) {
+ Room.setLightColor(this.lightid2, red * 0.5F, green * 0.5F, blue * 0.5F);
+ }
+ }
+
+ @Override
+ public BoundBoxTemp getBoundBox() {
+ return BoundBoxTemp.make(Point3Temp.make(), Point3Temp.make());
+ }
+
+ @Override
+ protected void markVoid() {
+ super.markVoid();
+ this.destroyScene();
+ this.lightid = 0;
+ this.lightid2 = 0;
+ }
+
+ public void markClumpEdited() {
+ this.wasEdited = true;
+ }
+
+ public void prerender() {
+ if (this.wasEdited) {
+ this.wasEdited = false;
+ this.doneWithEditing();
+ }
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(1, classCookie);
+ super.saveState(s);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ r.setOldFlag();
+ super.restoreState(r);
+ r.restore();
+ break;
+ case 1:
+ super.restoreState(r);
+ break;
+ default:
+ throw new TooNewException();
+ }
+ }
+
+ native void createScene(Room var1);
+
+ native void destroyScene();
+}
diff --git a/NET/worlds/scape/RoomSubscribeInfo.java b/NET/worlds/scape/RoomSubscribeInfo.java
new file mode 100644
index 0000000..0d98959
--- /dev/null
+++ b/NET/worlds/scape/RoomSubscribeInfo.java
@@ -0,0 +1,15 @@
+package NET.worlds.scape;
+
+public class RoomSubscribeInfo {
+ public float x;
+ public float y;
+ public float z;
+ public float d;
+
+ public RoomSubscribeInfo(float x, float y, float z, float d) {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ this.d = d;
+ }
+}
diff --git a/NET/worlds/scape/RunningActionCallback.java b/NET/worlds/scape/RunningActionCallback.java
new file mode 100644
index 0000000..ca58f5b
--- /dev/null
+++ b/NET/worlds/scape/RunningActionCallback.java
@@ -0,0 +1,5 @@
+package NET.worlds.scape;
+
+public interface RunningActionCallback {
+ void actionDone(Action var1, Event var2, Object var3);
+}
diff --git a/NET/worlds/scape/RunningActionHandler.java b/NET/worlds/scape/RunningActionHandler.java
new file mode 100644
index 0000000..a821458
--- /dev/null
+++ b/NET/worlds/scape/RunningActionHandler.java
@@ -0,0 +1,153 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import java.io.IOException;
+import java.text.MessageFormat;
+import java.util.Vector;
+
+public class RunningActionHandler extends SuperRoot implements FrameHandler, NonPersister {
+ private Action action;
+ private Persister seqID;
+ private RunningActionCallback callback;
+ private Object callbackCookie;
+ private static Object classCookie = new Object();
+
+ public static void trigger(Action act, World w, Event event) {
+ trigger(act, w, event, null, null);
+ }
+
+ public static void trigger(Action act, World w, Event event, RunningActionCallback callb, Object o) {
+ if (act.isActive()) {
+ Persister seqID = null;
+ if ((seqID = act.trigger(event, seqID)) != null) {
+ new RunningActionHandler(w, act, seqID, callb, o);
+ }
+ }
+ }
+
+ public static void trigger(Vector v, World w, Event event) {
+ trigger(v, w, event, null, null);
+ }
+
+ public static void trigger(Vector v, World w, Event event, RunningActionCallback callb, Object o) {
+ Vector acts = (Vector)v.clone();
+ int sz = acts.size();
+
+ for (int i = 0; i < sz; i++) {
+ Action act = (Action)acts.elementAt(i);
+ if (v.contains(act)) {
+ trigger(act, w, event, callb, o);
+ }
+ }
+ }
+
+ RunningActionHandler() {
+ }
+
+ private RunningActionHandler(World world, Action a, Persister seqID, RunningActionCallback callb, Object o) {
+ this.action = a;
+ this.seqID = seqID;
+ this.callback = callb;
+ this.callbackCookie = o;
+ world.addHandler(this);
+ }
+
+ @Override
+ public boolean handle(FrameEvent e) {
+ if (!this.action.isActive() || (this.seqID = this.action.trigger(e, this.seqID)) == null) {
+ if (this.callback != null) {
+ this.callback.actionDone(this.action, e, this.callbackCookie);
+ }
+
+ this.getWorld().removeHandler(this);
+ }
+
+ return true;
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = new Property(this, index, "Action");
+ } else if (mode == 1) {
+ ret = this.action;
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = new Property(this, index, "Sequence ID Object");
+ } else if (mode == 1) {
+ ret = this.seqID;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 2, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ Console.println(Console.message("Save-running"));
+ s.saveVersion(3, classCookie);
+ super.saveState(s);
+ s.save(this.action);
+ s.saveMaybeNull(this.seqID);
+ s.saveMaybeNull((Persister)this.callback);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ r.restore();
+ this.action = (Action)r.restoreMaybeNull();
+ this.callback = null;
+ break;
+ case 1:
+ super.restoreState(r);
+ this.action = (Action)r.restore();
+ this.callback = null;
+ break;
+ case 2:
+ super.restoreState(r);
+ this.action = (Action)r.restore();
+ this.seqID = r.restoreMaybeNull();
+ this.callback = null;
+ break;
+ case 3:
+ super.restoreState(r);
+ this.action = (Action)r.restore();
+ this.seqID = r.restoreMaybeNull();
+ this.callback = (RunningActionCallback)r.restoreMaybeNull();
+ break;
+ default:
+ throw new TooNewException();
+ }
+ }
+
+ @Override
+ public void postRestore(int version) {
+ super.postRestore(version);
+ Object[] arguments = new Object[]{new String(this.getName())};
+ Console.println(MessageFormat.format(Console.message("Discarding-old"), arguments));
+ SuperRoot owner = this.getOwner();
+ if (owner instanceof WObject) {
+ ((WObject)owner).removeHandler(this);
+ } else if (owner instanceof World) {
+ ((World)owner).removeHandler(this);
+ } else {
+ Console.println(MessageFormat.format(Console.message("Unable-discard"), arguments));
+ }
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + ":" + this.action.getName() + "[" + this.seqID + "]";
+ }
+}
diff --git a/NET/worlds/scape/SameRoomSensor.java b/NET/worlds/scape/SameRoomSensor.java
new file mode 100644
index 0000000..268573c
--- /dev/null
+++ b/NET/worlds/scape/SameRoomSensor.java
@@ -0,0 +1,60 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+public class SameRoomSensor extends Sensor implements FrameHandler {
+ private Room lastCamRoom;
+ private static Object classCookie = new Object();
+
+ public SameRoomSensor(Action a) {
+ if (a != null) {
+ this.addAction(a);
+ }
+ }
+
+ public SameRoomSensor() {
+ }
+
+ @Override
+ public void detach() {
+ this.lastCamRoom = null;
+ super.detach();
+ }
+
+ @Override
+ public boolean handle(FrameEvent e) {
+ Object owner = this.getOwner();
+ if (owner != null && owner instanceof WObject) {
+ WObject o = (WObject)owner;
+ Room thisRoom = o.getRoom();
+ Room thisCamRoom = Pilot.getActiveRoom();
+ if (thisCamRoom == thisRoom && this.lastCamRoom != thisCamRoom) {
+ this.trigger(e);
+ }
+
+ this.lastCamRoom = thisCamRoom;
+ return true;
+ } else {
+ return true;
+ }
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ super.saveState(s);
+ s.saveVersion(0, classCookie);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ int vers = super.restoreStateVers(r);
+ if (vers > 1) {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+ }
+}
diff --git a/NET/worlds/scape/SaveWidget.java b/NET/worlds/scape/SaveWidget.java
new file mode 100644
index 0000000..d50c040
--- /dev/null
+++ b/NET/worlds/scape/SaveWidget.java
@@ -0,0 +1,31 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.DialogReceiver;
+import NET.worlds.console.FileSysDialog;
+
+class SaveWidget extends ClickWidget implements DialogReceiver {
+ public SaveWidget(ToolBar toolbar) {
+ super(toolbar, "save.gif", Console.message("Save-to-file"));
+ }
+
+ @Override
+ public void perform() {
+ new FileSysDialog(
+ Console.getFrame(),
+ this,
+ Console.message("Save-Object-As"),
+ 1,
+ " wobject |*.wob| world |*.world;*.wor| console |*.console| pilot |*.pilot| drone |*.drone| other ||",
+ "",
+ false
+ );
+ }
+
+ @Override
+ public void dialogDone(Object who, boolean confirmed) {
+ if (confirmed) {
+ Console.getFrame().getEditTile().save(((FileSysDialog)who).fileName());
+ }
+ }
+}
diff --git a/NET/worlds/scape/Saver.java b/NET/worlds/scape/Saver.java
new file mode 100644
index 0000000..7b202e0
--- /dev/null
+++ b/NET/worlds/scape/Saver.java
@@ -0,0 +1,174 @@
+package NET.worlds.scape;
+
+import NET.worlds.network.URL;
+import java.io.DataOutput;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+public class Saver {
+ static final String headerString = "PERSISTER Worlds, Inc.";
+ static final String trailerString = "END PERSISTER";
+ private static int _version = 7;
+ private DataOutput os;
+ private boolean myFile;
+ private Hashtable classTable;
+ private Hashtable objectTable;
+ private Hashtable cookieTable;
+ private URL reference;
+
+ public static int version() {
+ return _version;
+ }
+
+ public URL getReferenceURL() {
+ return this.reference;
+ }
+
+ public Saver(URL url) throws IOException {
+ this(new DataOutputStream(new FileOutputStream(new File(url.unalias()))));
+ this.reference = url;
+ this.myFile = true;
+ }
+
+ public Saver(DataOutput os) throws IOException {
+ this.os = os;
+ this.saveString("PERSISTER Worlds, Inc.");
+ this.saveInt(_version);
+ this.classTable = new Hashtable();
+ this.objectTable = new Hashtable();
+ this.cookieTable = new Hashtable();
+ }
+
+ public void saveVersion(int v, Object cookie) throws IOException {
+ Integer oldv = (Integer)this.cookieTable.get(cookie);
+ if (oldv == null) {
+ this.saveInt(v);
+ this.cookieTable.put(cookie, new Integer(v));
+ } else {
+ assert oldv == v;
+ }
+ }
+
+ public void save(Persister p) throws IOException {
+ assert !(p instanceof NonPersister);
+
+ int hashed = UniqueHasher.uh().hash(p);
+ this.saveInt(hashed);
+ if (!this.objectTable.containsKey(p)) {
+ this.objectTable.put(p, p);
+ this.saveClass(p.getClass());
+ p.saveState(this);
+ }
+ }
+
+ public void saveVectorMaybeNull(Vector v) throws IOException {
+ if (v == null) {
+ this.saveBoolean(false);
+ } else {
+ this.saveBoolean(true);
+ this.saveVector(v);
+ }
+ }
+
+ public void saveMaybeNull(Persister p) throws IOException {
+ if (p != null && !(p instanceof NonPersister)) {
+ this.saveBoolean(false);
+ this.save(p);
+ } else {
+ this.saveBoolean(true);
+ }
+ }
+
+ public void saveClass(Class c) throws IOException {
+ UniqueHasher uh = UniqueHasher.uh();
+ this.saveInt(uh.hash(c.toString()));
+ if (!this.classTable.containsKey(c)) {
+ this.saveString(c.getName());
+ this.classTable.put(c, c);
+ }
+ }
+
+ public void saveArray(Persister[] pa) throws IOException {
+ this.saveClass(pa.getClass());
+ this.saveInt(pa.length);
+
+ for (int i = 0; i < pa.length; i++) {
+ this.saveMaybeNull(pa[i]);
+ }
+ }
+
+ public void saveVector(Vector v) throws IOException {
+ synchronized (v) {
+ Enumeration en = v.elements();
+ int length = 0;
+
+ while (en.hasMoreElements()) {
+ Object obj = en.nextElement();
+ if (obj instanceof Persister && !(obj instanceof NonPersister)) {
+ length++;
+ }
+ }
+
+ this.saveInt(length);
+ en = v.elements();
+
+ while (en.hasMoreElements()) {
+ Object obj = en.nextElement();
+ if (obj instanceof Persister && !(obj instanceof NonPersister)) {
+ this.save((Persister)obj);
+ }
+ }
+ }
+ }
+
+ public void saveString(String str) throws IOException {
+ this.saveBoolean(str == null);
+ if (str != null) {
+ this.os.writeUTF(str);
+ }
+ }
+
+ public void saveBoolean(boolean b) throws IOException {
+ this.os.writeBoolean(b);
+ }
+
+ public void saveByte(byte b) throws IOException {
+ this.os.writeByte(b);
+ }
+
+ public void saveShort(short s) throws IOException {
+ this.os.writeShort(s);
+ }
+
+ public void saveInt(int i) throws IOException {
+ this.os.writeInt(i);
+ }
+
+ public void saveLong(long g) throws IOException {
+ this.os.writeLong(g);
+ }
+
+ public void saveFloat(float f) throws IOException {
+ this.os.writeFloat(f);
+ }
+
+ public void saveDouble(double d) throws IOException {
+ this.os.writeDouble(d);
+ }
+
+ public void done() throws IOException {
+ this.saveString("END PERSISTER");
+ if (this.myFile) {
+ ((DataOutputStream)this.os).close();
+ }
+
+ this.classTable = null;
+ this.objectTable = null;
+ this.cookieTable = null;
+ }
+}
diff --git a/NET/worlds/scape/ScaleWidget.java b/NET/worlds/scape/ScaleWidget.java
new file mode 100644
index 0000000..4ee1084
--- /dev/null
+++ b/NET/worlds/scape/ScaleWidget.java
@@ -0,0 +1,23 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+
+class ScaleWidget extends WidgetButton {
+ public ScaleWidget(ToolBar toolbar) {
+ super(toolbar, "scale.gif", Console.message("Scale"));
+ }
+
+ @Override
+ public String drag(boolean initialDrag, float deltax, float deltay) {
+ WObject wobj = this.getWObject();
+ float delta = Math.abs(deltax) > Math.abs(deltay) ? deltax : deltay;
+ delta = (float)Math.pow(1.01, delta);
+ if (initialDrag) {
+ Console.getFrame().getEditTile().addUndoable(new UndoablTransform(wobj));
+ }
+
+ wobj.scale(delta);
+ wobj.markEdited();
+ return "Scale: " + wobj.getScale();
+ }
+}
diff --git a/NET/worlds/scape/ScapePicMovie.java b/NET/worlds/scape/ScapePicMovie.java
new file mode 100644
index 0000000..773e72d
--- /dev/null
+++ b/NET/worlds/scape/ScapePicMovie.java
@@ -0,0 +1,140 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.network.URL;
+import java.io.IOException;
+import java.util.Hashtable;
+
+public class ScapePicMovie implements Persister {
+ private static Hashtable movieDict = new Hashtable();
+ private ScapePicTexture[] movie;
+ private String localName;
+ private URL url;
+ private int frameCount;
+ private int width;
+ private int height;
+ private static Object classCookie = new Object();
+
+ static {
+ nativeInit();
+ }
+
+ public ScapePicMovie() {
+ }
+
+ public ScapePicMovie(String localName, URL url) {
+ this.localName = localName;
+ this.url = url;
+ this.movie = this.getAll();
+ }
+
+ public static native void nativeInit();
+
+ public int getW() {
+ return this.width;
+ }
+
+ public int getH() {
+ return this.height;
+ }
+
+ public int length() {
+ return this.frameCount;
+ }
+
+ public URL getURL() {
+ return this.url;
+ }
+
+ public ScapePicTexture getTexture(int frameNumber) {
+ ScapePicTexture ret = null;
+ if (this.movie != null) {
+ ret = this.movie[frameNumber];
+ this.movie[frameNumber] = null;
+ int i = 0;
+
+ while (i < this.frameCount && this.movie[i] == null) {
+ i++;
+ }
+
+ if (i == this.frameCount) {
+ this.movie = null;
+ }
+ }
+
+ return ret;
+ }
+
+ public ScapePicTexture[] getTextures() {
+ ScapePicTexture[] ret = this.movie;
+ this.movie = null;
+ return ret;
+ }
+
+ private synchronized ScapePicTexture[] getAll() {
+ String name = this.url.getAbsolute();
+ ScapePicMovie proto = (ScapePicMovie)movieDict.get(name);
+ ScapePicTexture[] a = (ScapePicTexture[])null;
+ if (proto != null) {
+ this.frameCount = proto.length();
+ this.width = proto.getW();
+ this.height = proto.getH();
+ a = this.lookupTextures(name, this.frameCount, this.width, this.height);
+ }
+
+ if (a == null) {
+ a = this.makeTextures(this.localName, name);
+ if (a != null && proto == null) {
+ this.frameCount = a.length;
+ this.width = a[0].getW();
+ this.height = a[0].getH();
+ movieDict.put(name, this);
+ }
+ }
+
+ return a;
+ }
+
+ private native ScapePicTexture[] lookupTextures(String var1, int var2, int var3, int var4);
+
+ private native ScapePicTexture[] makeTextures(String var1, String var2);
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ Console.println(Console.message("Obs-ScapePicMov") + this.url);
+ s.saveVersion(2, classCookie);
+ this.url.save(s);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ this.localName = r.restoreString();
+ this.url = URL.make(this.localName);
+ r.restoreBoolean();
+ break;
+ case 1:
+ this.localName = r.restoreString();
+ this.url = URL.make(this.localName);
+ break;
+ case 2:
+ this.url = URL.restore(r);
+ this.localName = this.url.unalias();
+ break;
+ default:
+ throw new TooNewException();
+ }
+
+ this.movie = this.getAll();
+ }
+
+ @Override
+ public void postRestore(int version) {
+ }
+
+ @Override
+ public String toString() {
+ return this.url.getAbsolute();
+ }
+}
diff --git a/NET/worlds/scape/ScapePicTexture.java b/NET/worlds/scape/ScapePicTexture.java
new file mode 100644
index 0000000..b2dd1ed
--- /dev/null
+++ b/NET/worlds/scape/ScapePicTexture.java
@@ -0,0 +1,94 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import java.io.IOException;
+import java.text.MessageFormat;
+
+public class ScapePicTexture extends Texture implements Persister {
+ private int w;
+ private int h;
+ private String _urlName;
+ private ScapePicMovie _movie;
+ private int _movieFrame;
+ private static Object classCookie = new Object();
+
+ static {
+ nativeInit();
+ }
+
+ public ScapePicTexture(String urlName, String filename) {
+ this._urlName = urlName;
+ this.makeTexture(urlName, filename);
+ }
+
+ public ScapePicTexture() {
+ }
+
+ public static native void nativeInit();
+
+ @Override
+ public int getW() {
+ return this.w;
+ }
+
+ @Override
+ public int getH() {
+ return this.h;
+ }
+
+ private native void makeTexture(String var1, String var2);
+
+ @Override
+ public String getName() {
+ return this._urlName;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(1, classCookie);
+ super.saveState(s);
+ if (this._movie != null) {
+ s.saveBoolean(true);
+ s.save(this._movie);
+ s.saveInt(this._movieFrame);
+ } else {
+ s.saveBoolean(false);
+ s.saveString(this._urlName);
+ }
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ r.restoreBoolean();
+ break;
+ case 1:
+ super.restoreState(r);
+ break;
+ default:
+ throw new TooNewException();
+ }
+
+ if (r.restoreBoolean()) {
+ this._movie = (ScapePicMovie)r.restore();
+ this._movieFrame = r.restoreInt();
+ ScapePicTexture t = this._movie.getTexture(this._movieFrame);
+ if (t == null) {
+ Object[] arguments = new Object[]{new String("" + this._movieFrame), new String("" + this._movie)};
+ Console.println(MessageFormat.format(Console.message("Error-frame"), arguments));
+ } else {
+ this.textureID = t.textureID;
+ }
+ } else {
+ this._urlName = r.restoreString();
+ this.makeTexture(this._urlName, this._urlName);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return this._movie == null ? this._urlName : this._movie.toString();
+ }
+}
diff --git a/NET/worlds/scape/ScapePicTextureDecoder.java b/NET/worlds/scape/ScapePicTextureDecoder.java
new file mode 100644
index 0000000..ca0a2d0
--- /dev/null
+++ b/NET/worlds/scape/ScapePicTextureDecoder.java
@@ -0,0 +1,15 @@
+package NET.worlds.scape;
+
+class ScapePicTextureDecoder extends TextureDecoder {
+ private String exts = "cmp;mov";
+
+ @Override
+ protected String getExts() {
+ return this.exts;
+ }
+
+ @Override
+ protected Texture read(String urlName, String filename) {
+ return new ScapePicTexture(urlName, filename);
+ }
+}
diff --git a/NET/worlds/scape/ScrollingImagePanel.java b/NET/worlds/scape/ScrollingImagePanel.java
new file mode 100644
index 0000000..31bb498
--- /dev/null
+++ b/NET/worlds/scape/ScrollingImagePanel.java
@@ -0,0 +1,398 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.DialogDisabled;
+import NET.worlds.console.ExposedPanel;
+import NET.worlds.console.WiderScrollbar;
+import NET.worlds.network.URL;
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Frame;
+import java.awt.Graphics;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Image;
+import java.awt.MediaTracker;
+import java.awt.Point;
+import java.awt.Scrollbar;
+import java.awt.Toolkit;
+import java.util.Enumeration;
+import java.util.Vector;
+
+public class ScrollingImagePanel extends ExposedPanel implements LibraryDropTarget, DialogDisabled {
+ private Scrollbar scrollbar = new WiderScrollbar();
+ private Vector items;
+ private int cellWidth;
+ private int cellHeight;
+ private Font font = new Font(Console.message("ScImageFont"), 1, 12);
+ private FontMetrics metrics = this.getFontMetrics(this.font);
+ private int ascent = this.metrics.getAscent();
+ private int descent = this.metrics.getDescent();
+ private int textHeight = this.ascent + this.descent;
+ private int scrollPos = 0;
+ private ClickEventHandler handler;
+ private ScrollingListElement downClicked;
+ private boolean isDownClicked;
+ private int maxScrollPos;
+ private boolean useIcons = false;
+ private boolean isDialogDisabled;
+
+ public ScrollingImagePanel(ClickEventHandler handler, Vector icons, boolean showIcons) {
+ this.handler = handler;
+ this.setFont(this.font);
+ this.setForeground(Color.black);
+ this.setBackground(Color.lightGray);
+ this.items = new Vector();
+ this.setContents(icons, false);
+ this.setLayout(new BorderLayout());
+ this.add("East", this.scrollbar);
+ this.useIcons = showIcons;
+ }
+
+ public void resetContents(Vector icons) {
+ this.setContents(icons);
+ }
+
+ protected void add(GridBagLayout gbag, Component comp, GridBagConstraints c) {
+ gbag.setConstraints(comp, c);
+ this.add(comp);
+ }
+
+ @Override
+ public boolean handleEvent(java.awt.Event e) {
+ if (this.isDialogDisabled) {
+ return false;
+ } else {
+ switch (e.id) {
+ case 601:
+ return this.scrollLineUp();
+ case 602:
+ return this.scrollLineDown();
+ case 603:
+ return this.scrollPageUp();
+ case 604:
+ return this.scrollPageDown();
+ case 605:
+ return this.scrollAbsolute();
+ default:
+ return super.handleEvent(e);
+ }
+ }
+ }
+
+ @Override
+ public void dialogDisable(boolean disable) {
+ this.isDialogDisabled = disable;
+ }
+
+ private void setContents(Vector icons) {
+ this.setContents(icons, true);
+ }
+
+ private void setContents(Vector icons, boolean showIt) {
+ this.items.removeAllElements();
+ int count = icons.size();
+
+ for (int i = 0; i < count; i++) {
+ this.addIcon((Iconic)icons.elementAt(i), false);
+ }
+
+ if (showIt) {
+ this.recalc(this.size().width, this.size().height);
+ this.repaint();
+ }
+ }
+
+ private void addIcon(Iconic icon, boolean showIt) {
+ String title = icon.getIconCaption();
+ int titleWidth = title != null ? this.metrics.stringWidth(title) : 0;
+ URL name = icon.getIconURL();
+ Image image = null;
+ if (name != null) {
+ MediaTracker tracker = new MediaTracker(this);
+ image = Toolkit.getDefaultToolkit().getImage(name.unalias());
+ tracker.addImage(image, 0);
+
+ try {
+ tracker.waitForID(0);
+ } catch (InterruptedException var9) {
+ }
+
+ if (tracker.isErrorID(0)) {
+ image = null;
+ System.out.println("Error loading " + name);
+ }
+ }
+
+ this.items.addElement(new ScrollingListElement(image, title, titleWidth));
+ }
+
+ private void findCellSize() {
+ this.cellWidth = 30;
+ this.cellHeight = 0;
+ if (this.useIcons) {
+ this.cellHeight = 30;
+ }
+
+ Enumeration e = this.items.elements();
+
+ while (e.hasMoreElements()) {
+ ScrollingListElement item = (ScrollingListElement)e.nextElement();
+ this.cellWidth = Math.max(this.cellWidth, item.titleWidth);
+ if (this.useIcons && item.image != null) {
+ this.cellWidth = Math.max(this.cellWidth, item.image.getWidth(this));
+ this.cellHeight = Math.max(this.cellHeight, item.image.getHeight(this));
+ }
+ }
+
+ this.cellWidth += 2;
+ this.cellHeight = this.cellHeight + this.textHeight + 2;
+ }
+
+ @Override
+ public void reshape(int x, int y, int w, int h) {
+ super.reshape(x, y, w, h);
+ this.recalc(w, h);
+ this.repaint();
+ }
+
+ private void recalc(int w, int h) {
+ this.findCellSize();
+ this.scrollPos = 0;
+ this.scrollbar.setValue(this.scrollPos);
+ int pass = 0;
+
+ while (pass < 2) {
+ int scrollbarWidth = 0;
+ if (pass == 1) {
+ scrollbarWidth = this.scrollbar.size().width;
+ }
+
+ int lines = 0;
+ if (this.cellWidth != 0) {
+ int imagesPerLine = Math.max(1, (w - scrollbarWidth) / this.cellWidth);
+ lines = (this.items.size() + imagesPerLine - 1) / imagesPerLine * this.cellHeight;
+ }
+
+ if (lines > h) {
+ if (pass == 0) {
+ if (!this.scrollbar.isVisible()) {
+ this.scrollbar.show();
+ this.validate();
+ }
+
+ pass++;
+ continue;
+ }
+
+ this.maxScrollPos = lines;
+ this.scrollbar.setValues(this.scrollPos, h, 0, lines);
+ this.scrollbar.setPageIncrement(h);
+ this.scrollbar.setLineIncrement(this.cellHeight);
+ break;
+ }
+
+ if (this.scrollbar.isVisible()) {
+ this.scrollbar.hide();
+ this.validate();
+ }
+ break;
+ }
+
+ this.clearHitTest();
+ }
+
+ private void clearHitTest() {
+ int count = this.items.size();
+
+ for (int i = 0; i < count; i++) {
+ ScrollingListElement e = (ScrollingListElement)this.items.elementAt(i);
+ e.x = e.y = -1;
+ }
+ }
+
+ private ScrollingListElement findCell(int x, int y) {
+ int count = this.items.size();
+
+ for (int i = 0; i < count; i++) {
+ ScrollingListElement e = (ScrollingListElement)this.items.elementAt(i);
+ if (x >= 0 && y >= 0 && x < e.x && y < e.y) {
+ return e;
+ }
+ }
+
+ return null;
+ }
+
+ private void buttonAction(boolean down) {
+ if (this.isDownClicked != down) {
+ this.isDownClicked = down;
+ Graphics g = this.getGraphics();
+ this.drawCell(g, this.downClicked, this.isDownClicked);
+ g.dispose();
+ }
+ }
+
+ private Component findComponent(Point p) {
+ Point screenLoc = this.getLocationOnScreen();
+ Container cur = null;
+
+ for (Container tmp = this.getParent(); !(tmp instanceof Frame); tmp = tmp.getParent()) {
+ cur = tmp;
+ }
+
+ Point parentCoords = cur.getLocationOnScreen();
+ p.x = p.x + screenLoc.x - parentCoords.x;
+ p.y = p.y + screenLoc.y - parentCoords.y;
+ Component found = cur;
+
+ while (true) {
+ Component c = found.locate(p.x, p.y);
+ if (c == found || c == null) {
+ return found;
+ }
+
+ Point tmp = c.location();
+ p.x = p.x - tmp.x;
+ p.y = p.y - tmp.y;
+ found = c;
+ }
+ }
+
+ @Override
+ public boolean mouseUp(java.awt.Event event, int x, int y) {
+ if (this.downClicked != null) {
+ Point p = new Point(x, y);
+ this.buttonAction(false);
+ this.handler.clickEvent(this.findComponent(p), p, 2);
+ this.downClicked = null;
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public int itemAt(Point p) {
+ ScrollingListElement cell = this.findCell(p.x, p.y);
+ return cell != null ? this.items.indexOf(cell) : -1;
+ }
+
+ @Override
+ public boolean mouseDown(java.awt.Event event, int x, int y) {
+ if (this.downClicked == null && (this.downClicked = this.findCell(x, y)) != null) {
+ this.buttonAction(true);
+ int flags = 1;
+ if (event.metaDown()) {
+ flags |= 4;
+ }
+
+ this.handler.clickEvent(this, new Point(x, y), flags);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public boolean mouseDrag(java.awt.Event event, int x, int y) {
+ if (this.downClicked != null) {
+ Point p = new Point(x, y);
+ this.handler.clickEvent(this.findComponent(p), p, 8);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ private void drawCell(Graphics g, ScrollingListElement e, boolean depressed) {
+ int x = e.x - this.cellWidth;
+ int y = e.y - this.cellHeight;
+ int imageBoxHeight = this.cellHeight - this.textHeight;
+ int yTextOffset = imageBoxHeight + this.ascent;
+ Color normColor = g.getColor();
+ g.setColor(this.getBackground());
+ g.draw3DRect(x, y, this.cellWidth - 1, this.cellHeight - 1, !depressed);
+ g.setColor(normColor);
+ if (this.useIcons && e.image != null) {
+ int imageWidth = e.image.getWidth(this);
+ int imageHeight = e.image.getHeight(this);
+ g.drawImage(e.image, x + (this.cellWidth - imageWidth) / 2, y + (imageBoxHeight - imageHeight) / 2, null);
+ }
+
+ if (e.title != null) {
+ g.drawString(e.title, x + (this.cellWidth - e.titleWidth) / 2, y + yTextOffset);
+ }
+ }
+
+ @Override
+ public void paint(Graphics g) {
+ Color normColor = g.getColor();
+ super.paint(g);
+ g.setColor(normColor);
+ this.clearHitTest();
+ int width = this.size().width;
+ int height = this.size().height;
+ int x = 0;
+ int y = -this.scrollbar.getValue();
+ int count = this.items.size();
+
+ for (int i = 0; i < count; i++) {
+ if (y + this.cellHeight > 0) {
+ ScrollingListElement e = (ScrollingListElement)this.items.elementAt(i);
+ e.x = x + this.cellWidth;
+ e.y = y + this.cellHeight;
+ this.drawCell(g, e, false);
+ }
+
+ x += this.cellWidth;
+ if (x + this.cellWidth > width) {
+ x = 0;
+ if ((y += this.cellHeight) >= height) {
+ break;
+ }
+ }
+ }
+ }
+
+ public boolean isIconsVisible() {
+ return this.useIcons;
+ }
+
+ public void setIconsVisible(boolean showIcons) {
+ this.useIcons = showIcons;
+ this.recalc(this.size().width, this.size().height);
+ this.repaint();
+ }
+
+ private boolean setScrollValue(int value) {
+ this.scrollPos = Math.max(this.scrollbar.getMinimum(), value);
+ this.scrollPos = Math.min(this.maxScrollPos, this.scrollPos);
+ this.scrollbar.setValue(this.scrollPos);
+ this.repaint();
+ return true;
+ }
+
+ private boolean scrollLineUp() {
+ return this.setScrollValue(this.scrollPos - this.scrollbar.getLineIncrement());
+ }
+
+ private boolean scrollLineDown() {
+ return this.setScrollValue(this.scrollPos + this.scrollbar.getLineIncrement());
+ }
+
+ private boolean scrollPageUp() {
+ return this.setScrollValue(this.scrollPos - this.scrollbar.getPageIncrement());
+ }
+
+ private boolean scrollPageDown() {
+ return this.setScrollValue(this.scrollPos + this.scrollbar.getPageIncrement());
+ }
+
+ private boolean scrollAbsolute() {
+ return this.setScrollValue(this.scrollbar.getValue());
+ }
+}
diff --git a/NET/worlds/scape/ScrollingListElement.java b/NET/worlds/scape/ScrollingListElement.java
new file mode 100644
index 0000000..318dbba
--- /dev/null
+++ b/NET/worlds/scape/ScrollingListElement.java
@@ -0,0 +1,17 @@
+package NET.worlds.scape;
+
+import java.awt.Image;
+
+class ScrollingListElement {
+ Image image;
+ String title;
+ int titleWidth;
+ int x;
+ int y;
+
+ ScrollingListElement(Image image, String title, int titleWidth) {
+ this.image = image;
+ this.title = title;
+ this.titleWidth = titleWidth;
+ }
+}
diff --git a/NET/worlds/scape/SelectAvatarAction.java b/NET/worlds/scape/SelectAvatarAction.java
new file mode 100644
index 0000000..fef58eb
--- /dev/null
+++ b/NET/worlds/scape/SelectAvatarAction.java
@@ -0,0 +1,152 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.OkCancelDialog;
+import NET.worlds.console.PolledDialog;
+import NET.worlds.core.ServerTableManager;
+import NET.worlds.network.URL;
+import java.io.IOException;
+
+public class SelectAvatarAction extends DialogAction {
+ URL url = null;
+ String description;
+ static String[] avatarAliases = ServerTableManager.instance().getTable("avatarAliases");
+ private static Object classCookie = new Object();
+
+ private URL getURLVal() {
+ URL val = this.url;
+ if (val == null) {
+ SuperRoot o = this.getOwner();
+ if (o instanceof Drone) {
+ val = ((Drone)o).getSourceURL();
+ } else if (o instanceof PosableShape) {
+ val = ((Shape)o).getURL();
+ } else if (o instanceof Hologram) {
+ val = ((Hologram)o).getMovieName();
+ }
+ }
+
+ return val;
+ }
+
+ @Override
+ public void doIt() {
+ Console console = Console.getActive();
+ URL val = this.getURLVal();
+ if (console != null && val != null) {
+ console.setAvatar(val);
+ }
+ }
+
+ @Override
+ public PolledDialog getDialog() {
+ URL val = this.getURLVal();
+ if (!Console.getActive().getVIP() && val.getInternal().toLowerCase().endsWith(".rwg")) {
+ return new OkCancelDialog(
+ Console.getFrame(), this, Console.message("Cant-change-AV"), Console.message("OK"), null, Console.message("Only-VIPs-change"), false
+ );
+ } else {
+ String desc = this.description;
+ if (desc == null || desc.length() == 0) {
+ desc = getPrettyAvatarName(val.getBase());
+ }
+
+ return new ChangeAvatarDialog(Console.getFrame(), this, desc);
+ }
+ }
+
+ public static String getPrettyAvatarName(String name) {
+ int extIndex = name.indexOf(46);
+ if (extIndex >= 0) {
+ name = name.substring(0, extIndex).toLowerCase();
+ } else {
+ name = name.toLowerCase();
+ }
+
+ for (int i = 0; i < avatarAliases.length; i += 2) {
+ if (avatarAliases[i].equals(name)) {
+ return avatarAliases[i + 1];
+ }
+ }
+
+ String properName = name.substring(0, 1).toUpperCase();
+ if (name.length() > 1) {
+ properName = properName + name.substring(1);
+ }
+
+ return properName;
+ }
+
+ @Override
+ public Persister trigger(Event e, Persister seqID) {
+ URL val = this.getURLVal();
+ return val == null ? null : super.trigger(e, seqID);
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = URLPropertyEditor.make(new Property(this, index, "Avatar URL").allowSetNull(), "pilot;drone;rwx;rwg;mov");
+ } else if (mode == 1) {
+ ret = this.url;
+ } else if (mode == 2) {
+ this.url = (URL)value;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 1, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + "[url " + (this.url == null ? "null" : this.url.getRelativeTo(this) + "]");
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(4, classCookie);
+ super.saveState(s);
+ URL.save(s, this.url);
+ s.saveString(this.description);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ int ver = r.restoreVersion(classCookie);
+ switch (ver) {
+ case 0:
+ r.setOldFlag();
+ this.dialogActionSkipRestore(r);
+ this.url = URL.restore(r, ".world");
+ break;
+ case 1:
+ r.setOldFlag();
+ this.dialogActionSkipRestore(r);
+ this.url = URL.restore(r, ".world");
+ this.showDialog = r.restoreBoolean();
+ break;
+ case 2:
+ this.dialogActionSkipRestore(r);
+ this.url = URL.restore(r, ".world");
+ this.showDialog = r.restoreBoolean();
+ this.cancelOnly = r.restoreBoolean();
+ break;
+ case 3:
+ case 4:
+ super.restoreState(r);
+ this.url = URL.restore(r, ".world");
+ if (ver >= 4) {
+ this.description = r.restoreString();
+ }
+ break;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/SendURLAction.java b/NET/worlds/scape/SendURLAction.java
new file mode 100644
index 0000000..83da5e1
--- /dev/null
+++ b/NET/worlds/scape/SendURLAction.java
@@ -0,0 +1,442 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.InternetExplorer;
+import NET.worlds.console.Main;
+import NET.worlds.console.MainCallback;
+import NET.worlds.console.OkCancelDialog;
+import NET.worlds.console.PolledDialog;
+import NET.worlds.console.WebBrowser;
+import NET.worlds.console.WebControlImp;
+import NET.worlds.core.IniFile;
+import NET.worlds.network.RemoteFileConst;
+import NET.worlds.network.URL;
+import java.io.IOException;
+import java.text.MessageFormat;
+import java.util.Hashtable;
+
+public class SendURLAction extends DialogAction implements MainCallback, RemoteFileConst {
+ URL destination;
+ URL destinationOverride;
+ String worldOverride;
+ String description;
+ String postData = null;
+ protected boolean getUser;
+ InternetExplorer bogusBrowser;
+ private static String notAvailablePrefix = "http://www.worldsstore.com/superstore/en/product/";
+ private static Hashtable notAvailable = new Hashtable();
+ private String trigger;
+ private int tries = 0;
+ private Persister curSeq = null;
+ private static Object classCookie = new Object();
+
+ static {
+ Object o = new Object();
+ notAvailable.put("pa101", o);
+ notAvailable.put("pa102", o);
+ notAvailable.put("pg102", o);
+ notAvailable.put("pg105", o);
+ notAvailable.put("ph108", o);
+ notAvailable.put("ph502", o);
+ }
+
+ public SendURLAction() {
+ this("http://www.worlds.net");
+ }
+
+ public SendURLAction(URL dest) {
+ this.destination = dest;
+ this.getUser = false;
+ }
+
+ public SendURLAction(String dest) {
+ this(dest == null ? null : URL.make(dest));
+ }
+
+ public SendURLAction(String dest, boolean get) {
+ this(dest == null ? null : URL.make(dest), get);
+ }
+
+ public SendURLAction(URL dest, boolean get) {
+ this.destination = dest;
+ this.getUser = get;
+ }
+
+ public void setDestination(URL d) {
+ this.destination = d;
+ }
+
+ public void setTrigger(String t) {
+ this.trigger = t;
+ }
+
+ public void startBrowser() {
+ if (Main.isMainThread()) {
+ this.tryLaunch();
+ } else {
+ Main.register(this);
+ }
+ }
+
+ @Override
+ public void mainCallback() {
+ Main.unregister(this);
+ this.tryLaunch();
+ }
+
+ private URL getDestination() {
+ if (this.worldOverride != null) {
+ IniFile ini = new IniFile("InstalledWorlds");
+ String first = ini.getIniString("InstalledWorld0", "");
+ if (this.worldOverride.equalsIgnoreCase(first)) {
+ return this.destinationOverride;
+ }
+ }
+
+ return this.destination;
+ }
+
+ private void tryLaunch() {
+ URL destURL = this.getDestination();
+ if (destURL != null) {
+ String dest = destURL.unalias();
+ String newDest = WebControlImp.processURL(dest);
+ if (newDest != null) {
+ dest = newDest;
+ }
+
+ if (this.postData != null) {
+ this.postData = WebControlImp.processURL(this.postData);
+ }
+
+ String info = null;
+ Console console = Console.getActive();
+ if (console != null && console.getGalaxy().getChatname() != null && !console.getGalaxy().getChatname().equals("")) {
+ info = "Username=" + console.getGalaxy().getUsernameU();
+ }
+
+ if (this.getUser && info != null) {
+ dest = dest + "?" + info;
+ }
+
+ String midDest = dest.substring(dest.indexOf(":") + 1);
+ if (dest.startsWith("sound:")) {
+ dest = URL.make(midDest).unalias();
+ WavSoundPlayer.pauseSystem();
+ CDAudio.get().setEnabled(false);
+
+ try {
+ WebBrowser.forceMinimized(true);
+ WebBrowser.reuseOrMake(dest, this.postData, WebBrowser.getAdPartPlacement(), "sound:");
+ WebBrowser.forceMinimized(false);
+ return;
+ } catch (IOException var14) {
+ }
+ } else if (dest.startsWith("videoMap:") || dest.startsWith("overmap:")) {
+ dest = URL.make(midDest).unalias();
+ WavSoundPlayer.pauseSystem();
+ CDAudio.get().setEnabled(false);
+
+ try {
+ WebBrowser.dontUseToolbar();
+ WebBrowser.dontUseWindowFrame();
+ WebBrowser.reuseOrMake(dest, this.postData, WebBrowser.getMapPartPlacement(), "videoMap:");
+ WebBrowser.useToolbar();
+ return;
+ } catch (IOException var15) {
+ }
+ } else if (dest.startsWith("videoAd:")) {
+ dest = URL.make(midDest).unalias();
+ WavSoundPlayer.pauseSystem();
+ CDAudio.get().setEnabled(false);
+
+ try {
+ WebBrowser.dontUseToolbar();
+ WebBrowser.dontUseWindowFrame();
+ WebBrowser.reuseOrMake(dest, this.postData, WebBrowser.getAdPartPlacement(), "videoAd:");
+ WebBrowser.useToolbar();
+ return;
+ } catch (IOException var13) {
+ }
+ } else if (dest.startsWith("zoom:")) {
+ dest = URL.make(midDest).unalias();
+ WavSoundPlayer.pauseSystem();
+ CDAudio.get().setEnabled(false);
+
+ try {
+ WebBrowser.dontUseToolbar();
+ WebBrowser.dontUseWindowFrame();
+ WebBrowser.reuseOrMake(dest, this.postData, WebBrowser.getRenderPartPlacement(), "zoom:");
+ WebBrowser.useToolbar();
+ return;
+ } catch (IOException var12) {
+ }
+ } else if (dest.startsWith("zoomLeft:")) {
+ dest = URL.make(midDest).unalias();
+ WavSoundPlayer.pauseSystem();
+ CDAudio.get().setEnabled(false);
+
+ try {
+ WebBrowser.dontUseToolbar();
+ WebBrowser.dontUseWindowFrame();
+ WebBrowser.reuseOrMake(dest, this.postData, WebBrowser.getLeftRenderPartPlacement(), "zoomLeft:");
+ WebBrowser.useToolbar();
+ return;
+ } catch (IOException var11) {
+ }
+ } else if (dest.startsWith("outside:")) {
+ dest = URL.make(midDest).unalias();
+ WavSoundPlayer.pauseSystem();
+ CDAudio.get().setEnabled(false);
+
+ try {
+ WebBrowser.dontUseToolbar();
+ WebBrowser.reuseOrMake(dest, this.postData, WebBrowser.getOutsidePlacement(), "outside:");
+ WebBrowser.useToolbar();
+ return;
+ } catch (IOException var10) {
+ }
+ } else if (dest.startsWith("http:")) {
+ try {
+ WebBrowser.reuseOrMake(dest, this.postData);
+ return;
+ } catch (IOException var9) {
+ }
+ }
+
+ if (this.bogusBrowser == null) {
+ try {
+ this.bogusBrowser = new InternetExplorer(null);
+ } catch (IOException var8) {
+ }
+ }
+
+ if (!launchViaRegistry(dest)) {
+ Console.println(dest + Console.message("Unable-to-launch"));
+ }
+ }
+ }
+
+ @Override
+ public void doIt() {
+ this.startBrowser();
+ }
+
+ @Override
+ public PolledDialog getDialog() {
+ URL tmpURL = this.getDestination();
+ if (tmpURL == null) {
+ return new ItemNotAvailableDialog(Console.getFrame(), this);
+ } else {
+ String tmp = tmpURL.unalias().toLowerCase();
+ if (tmp.startsWith(notAvailablePrefix) && notAvailable.containsKey(tmp.substring(notAvailablePrefix.length()))) {
+ return new ItemNotAvailableDialog(Console.getFrame(), this);
+ } else {
+ return (PolledDialog)(this.description != null && !this.description.equals("Would you like more information?")
+ ? new OkCancelDialog(
+ Console.getFrame(), this, Console.message("BrowseQ"), Console.message("Cancel"), Console.message("OK"), this.description, false, 1
+ )
+ : new MoreInfoDialog(Console.getFrame(), this));
+ }
+ }
+ }
+
+ private static native boolean launchViaRegistry(String var0);
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = URLPropertyEditor.make(new Property(this, index, "Destination").allowSetNull(), null);
+ } else if (mode == 1) {
+ ret = this.destination;
+ } else if (mode == 2) {
+ this.destination = (URL)value;
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Description"));
+ } else if (mode == 1) {
+ ret = this.description;
+ } else if (mode == 2) {
+ this.description = ((String)value).trim();
+ }
+ break;
+ case 2:
+ if (mode == 0) {
+ ret = URLPropertyEditor.make(new Property(this, index, "Destination Override").allowSetNull(), null);
+ } else if (mode == 1) {
+ ret = this.destinationOverride;
+ } else if (mode == 2) {
+ this.destinationOverride = (URL)value;
+ }
+ break;
+ case 3:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Override World").allowSetNull());
+ } else if (mode == 1) {
+ ret = this.worldOverride;
+ } else if (mode == 2) {
+ if (value == null) {
+ this.worldOverride = null;
+ } else {
+ this.worldOverride = ((String)value).trim();
+ if (this.worldOverride.length() == 0) {
+ this.worldOverride = null;
+ }
+ }
+ }
+ break;
+ case 4:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Send User Info (auto-login)"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(this.getUser);
+ } else if (mode == 2) {
+ if ((Boolean)value) {
+ this.getUser = true;
+ } else {
+ this.getUser = false;
+ }
+ }
+ break;
+ case 5:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "POST data"));
+ } else if (mode == 1) {
+ ret = this.postData;
+ } else if (mode == 2) {
+ this.postData = ((String)value).trim();
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 6, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(9, classCookie);
+ super.saveState(s);
+ s.saveString(this.description);
+ URL.save(s, this.destination);
+ URL.save(s, this.destinationOverride);
+ s.saveString(this.worldOverride);
+ s.saveBoolean(this.getUser);
+ s.saveString(this.postData);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ String destStr = null;
+ switch (r.restoreVersion(classCookie)) {
+ case 1:
+ r.setOldFlag();
+ r.restoreBoolean();
+ destStr = r.restoreString();
+ r.restoreString();
+ break;
+ case 2:
+ r.setOldFlag();
+ r.restoreBoolean();
+ destStr = r.restoreString();
+ break;
+ case 3:
+ this.dialogActionSkipRestore(r);
+ r.restoreBoolean();
+ destStr = r.restoreString();
+ break;
+ case 4:
+ this.dialogActionSkipRestore(r);
+ destStr = r.restoreString();
+ break;
+ case 5:
+ this.dialogActionSkipRestore(r);
+ destStr = r.restoreString();
+ this.getUser = r.restoreBoolean();
+ r.restoreBoolean();
+ break;
+ case 6:
+ super.restoreState(r);
+ this.description = r.restoreString();
+ destStr = r.restoreString();
+ this.getUser = r.restoreBoolean();
+ r.restoreBoolean();
+ break;
+ case 7:
+ super.restoreState(r);
+ this.description = r.restoreString();
+ destStr = r.restoreString();
+ String destOverrideStr = r.restoreString();
+ if (destOverrideStr != null) {
+ this.destinationOverride = URL.make(destOverrideStr);
+ }
+
+ this.worldOverride = r.restoreString();
+ this.getUser = r.restoreBoolean();
+ r.restoreBoolean();
+ break;
+ case 8:
+ super.restoreState(r);
+ this.description = r.restoreString();
+ this.destination = URL.restore(r, null);
+ this.destinationOverride = URL.restore(r, null);
+ this.worldOverride = r.restoreString();
+ this.getUser = r.restoreBoolean();
+ r.restoreBoolean();
+ break;
+ case 9:
+ super.restoreState(r);
+ this.description = r.restoreString();
+ this.destination = URL.restore(r, null);
+ this.destinationOverride = URL.restore(r, null);
+ this.worldOverride = r.restoreString();
+ this.getUser = r.restoreBoolean();
+ this.postData = r.restoreString();
+ break;
+ default:
+ throw new TooNewException();
+ }
+
+ if (destStr != null) {
+ this.destination = URL.make(destStr);
+ }
+ }
+
+ @Override
+ public void postRestore(int version) {
+ super.postRestore(version);
+ if (this.trigger != null) {
+ SuperRoot owner = this.getOwner();
+
+ while (owner != null && !(owner instanceof WObject)) {
+ owner = owner.getOwner();
+ }
+
+ if (owner == null) {
+ Object[] arguments = new Object[]{new String(this.getName())};
+ Console.println(MessageFormat.format(Console.message("Cannot-sensor"), arguments));
+ } else if (this.trigger.equals("click")) {
+ ((WObject)owner).addHandler(new ClickSensor(this));
+ } else if (this.trigger.equals("bump")) {
+ ((WObject)owner).addHandler(new BumpSensor(this));
+ } else {
+ Room r = ((WObject)owner).getRoom();
+ if (r != null) {
+ Object[] arguments = new Object[]{new String(this.trigger), new String(this.getName()), new String(r.getName())};
+ Console.println(MessageFormat.format(Console.message("Trigger-value-in"), arguments));
+ } else {
+ Object[] arguments = new Object[]{new String(this.trigger), new String(this.getName())};
+ Console.println(MessageFormat.format(Console.message("Trigger-value"), arguments));
+ }
+ }
+
+ this.trigger = null;
+ }
+ }
+}
diff --git a/NET/worlds/scape/Sensor.java b/NET/worlds/scape/Sensor.java
new file mode 100644
index 0000000..8fb989d
--- /dev/null
+++ b/NET/worlds/scape/Sensor.java
@@ -0,0 +1,99 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Vector;
+
+public class Sensor extends SuperRoot {
+ protected Vector<Action> actions = new Vector<Action>();
+ private static Object classCookie = new Object();
+
+ public void addAction(Action o) {
+ this.actions.addElement(o);
+ }
+
+ public void deleteAction(Action o) {
+ this.actions.removeElement(o);
+ }
+
+ public void deleteActions() {
+ while (this.actions.size() > 0) {
+ this.deleteAction(this.actions.elementAt(0));
+ }
+ }
+
+ public Enumeration<Action> getActions() {
+ return this.actions.elements();
+ }
+
+ public int countActions() {
+ return this.actions.size();
+ }
+
+ public void trigger(Event event) {
+ RunningActionHandler.trigger(this.actions, this.getWorld(), event);
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = ObjectPropertyAdder.make(new VectorProperty(this, index, "Targets"), this.getRoot(), "NET.worlds.scape.Action");
+ } else if (mode == 1) {
+ ret = this.actions.clone();
+ } else if (mode == 4) {
+ this.deleteAction((Action)value);
+ } else if (mode == 3) {
+ this.addAction((Action)value);
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 1, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(2, classCookie);
+ super.saveState(s);
+ s.saveVector(this.actions);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ this.restoreStateVers(r);
+ }
+
+ protected int restoreStateVers(Restorer r) throws IOException, TooNewException {
+ int vers = r.restoreVersion(classCookie);
+ switch (vers) {
+ case 1:
+ case 2:
+ super.restoreState(r);
+ case 0:
+ this.actions = r.restoreVectorActions();
+ return vers;
+ default:
+ throw new TooNewException();
+ }
+ }
+
+ @Override
+ public void postRestore(int version) {
+ super.postRestore(version);
+ Enumeration<Action> en = this.getActions();
+
+ while (en.hasMoreElements()) {
+ Action a = en.nextElement();
+ if (this.getOwner() != null && a.getOwner() == null) {
+ System.out.println("Reparenting orphan action " + a.getName());
+ WObject w = (WObject)this.getOwner();
+ w.addAction(a);
+ }
+ }
+ }
+}
diff --git a/NET/worlds/scape/SensorFrameHandler.java b/NET/worlds/scape/SensorFrameHandler.java
new file mode 100644
index 0000000..fc3a4df
--- /dev/null
+++ b/NET/worlds/scape/SensorFrameHandler.java
@@ -0,0 +1,17 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+class SensorFrameHandler extends SuperRoot {
+ @Override
+ public void saveState(Saver s) throws IOException {
+ assert false;
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ RunningActionHandler a = new RunningActionHandler();
+ r.replace(this, a);
+ a.restoreState(r);
+ }
+}
diff --git a/NET/worlds/scape/SeqFile.java b/NET/worlds/scape/SeqFile.java
new file mode 100644
index 0000000..2d20bc9
--- /dev/null
+++ b/NET/worlds/scape/SeqFile.java
@@ -0,0 +1,29 @@
+package NET.worlds.scape;
+
+import NET.worlds.network.URL;
+
+public class SeqFile implements BGLoaded {
+ private int nativeNotifyObject;
+
+ public SeqFile(int obj, URL path) {
+ this.nativeNotifyObject = obj;
+ BackgroundLoader.get(this, path);
+ }
+
+ @Override
+ public Object asyncBackgroundLoad(String localName, URL remoteURL) {
+ PendingCacheDrone.notifySeqLoaded(this.nativeNotifyObject, localName);
+ return localName;
+ }
+
+ @Override
+ public boolean syncBackgroundLoad(Object obj, URL remoteURL) {
+ return false;
+ }
+
+ @Override
+ public Room getBackgroundLoadRoom() {
+ Pilot p = Pilot.getActive();
+ return p != null ? p.getRoom() : null;
+ }
+}
diff --git a/NET/worlds/scape/SequenceAction.java b/NET/worlds/scape/SequenceAction.java
new file mode 100644
index 0000000..e206861
--- /dev/null
+++ b/NET/worlds/scape/SequenceAction.java
@@ -0,0 +1,135 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Vector;
+
+public class SequenceAction extends Action {
+ protected int loopCount = 1;
+ protected boolean loopInfinite = false;
+ Vector actions = new Vector();
+ SequenceActionState currentSeq;
+ private static Object classCookie = new Object();
+
+ @Override
+ public Persister trigger(Event evt, Persister seqID) {
+ if (seqID != this.currentSeq) {
+ return null;
+ } else {
+ if (seqID == null) {
+ this.currentSeq = new SequenceActionState(this);
+ }
+
+ if (!this.currentSeq.run(evt)) {
+ this.currentSeq = null;
+ }
+
+ return this.currentSeq;
+ }
+ }
+
+ public void addComponent(Action act) {
+ this.actions.addElement(act);
+ }
+
+ public void insertComponent(Action act, int index) {
+ this.actions.insertElementAt(act, index);
+ }
+
+ public boolean removeComponent(Action act) {
+ return this.actions.removeElement(act);
+ }
+
+ public Enumeration getComponents() {
+ return this.actions.elements();
+ }
+
+ public int getLoopCount() {
+ return this.loopCount;
+ }
+
+ public void setLoopCount(int c) {
+ this.loopCount = c;
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ VectorProperty vp = new VectorProperty(this, index, "Components");
+ vp.allowSorting(false);
+ ret = ObjectPropertyAdder.make(vp, this.getRoot(), "NET.worlds.scape.Action");
+ } else if (mode == 1) {
+ ret = this.actions.clone();
+ } else if (mode == 4) {
+ this.actions.removeElement(value);
+ } else if (mode == 3) {
+ this.actions.addElement((Action)value);
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = IntegerPropertyEditor.make(new Property(this, index, "Loop Count"));
+ } else if (mode == 1) {
+ ret = new Integer(this.loopCount);
+ } else if (mode == 2) {
+ this.loopCount = (Integer)value;
+ }
+ break;
+ case 2:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Loop Infinite"), "False", "True");
+ } else if (mode == 1) {
+ ret = new Boolean(this.loopInfinite);
+ } else if (mode == 2) {
+ this.loopInfinite = (Boolean)value;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 3, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(2, classCookie);
+ super.saveState(s);
+ s.saveBoolean(this.loopInfinite);
+ s.saveVector(this.actions);
+ s.saveInt(this.loopCount);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ r.setOldFlag();
+ super.restoreState(r);
+ this.actions = r.restoreVector();
+ this.loopCount = r.restoreInt();
+ this.loopInfinite = this.loopCount < 0;
+ this.loopCount = Math.abs(this.loopCount);
+ r.restoreBoolean();
+ break;
+ case 1:
+ super.restoreState(r);
+ this.actions = r.restoreVector();
+ this.loopCount = r.restoreInt();
+ this.loopInfinite = this.loopCount < 0;
+ this.loopCount = Math.abs(this.loopCount);
+ break;
+ case 2:
+ super.restoreState(r);
+ this.loopInfinite = r.restoreBoolean();
+ this.actions = r.restoreVector();
+ this.loopCount = r.restoreInt();
+ break;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/SequenceActionState.java b/NET/worlds/scape/SequenceActionState.java
new file mode 100644
index 0000000..b7e17ed
--- /dev/null
+++ b/NET/worlds/scape/SequenceActionState.java
@@ -0,0 +1,91 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+import java.util.Vector;
+
+class SequenceActionState implements Persister {
+ int currentLoop;
+ boolean loopInfinite;
+ Vector actions;
+ Persister seqID;
+ int currentAct;
+ private static Object classCookie = new Object();
+
+ SequenceActionState() {
+ }
+
+ SequenceActionState(SequenceAction sa) {
+ this.currentLoop = sa.loopCount;
+ this.loopInfinite = sa.loopInfinite;
+ this.actions = (Vector)sa.actions.clone();
+ }
+
+ boolean run(Event evt) {
+ if (this.currentLoop <= 0 && !this.loopInfinite) {
+ return false;
+ } else {
+ while (this.currentAct < this.actions.size()) {
+ Action act = (Action)this.actions.elementAt(this.currentAct);
+ if ((this.seqID = act.trigger(evt, this.seqID)) != null) {
+ return true;
+ }
+
+ this.currentAct++;
+ }
+
+ this.currentAct = 0;
+ if (this.currentLoop > 0) {
+ this.currentLoop--;
+ }
+
+ return true;
+ }
+ }
+
+ @Override
+ public String toString() {
+ String stateString = "Action #" + this.currentAct + " of loop " + this.currentLoop + ", status " + this.seqID;
+ if (!this.loopInfinite) {
+ stateString = stateString + " NOT";
+ }
+
+ return stateString + " Infinite";
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(1, classCookie);
+ s.saveBoolean(this.loopInfinite);
+ s.saveInt(this.currentLoop);
+ s.saveInt(this.currentAct);
+ s.saveVector(this.actions);
+ s.saveMaybeNull(this.seqID);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ this.currentLoop = r.restoreInt();
+ this.loopInfinite = this.currentLoop < 0;
+ this.currentLoop = Math.abs(this.currentLoop);
+ this.currentAct = r.restoreInt();
+ this.actions = r.restoreVector();
+ this.seqID = r.restoreMaybeNull();
+ break;
+ case 1:
+ this.loopInfinite = r.restoreBoolean();
+ this.currentLoop = r.restoreInt();
+ this.currentAct = r.restoreInt();
+ this.actions = r.restoreVector();
+ this.seqID = r.restoreMaybeNull();
+ break;
+ default:
+ throw new TooNewException();
+ }
+ }
+
+ @Override
+ public void postRestore(int version) {
+ }
+}
diff --git a/NET/worlds/scape/SetBooleanAction.java b/NET/worlds/scape/SetBooleanAction.java
new file mode 100644
index 0000000..942553c
--- /dev/null
+++ b/NET/worlds/scape/SetBooleanAction.java
@@ -0,0 +1,57 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+public class SetBooleanAction extends SetPropertyAction {
+ private boolean _value;
+ private static Object classCookie = new Object();
+
+ @Override
+ public Persister trigger(Event e, Persister seqID) {
+ if (this.useParam()) {
+ this._value = Boolean.valueOf(this.param());
+ }
+
+ this.set(new Boolean(this._value));
+ return null;
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Set To"), "False", "True");
+ } else if (mode == 1) {
+ ret = new Boolean(this._value);
+ } else if (mode == 2) {
+ this._value = (Boolean)value;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 1, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(1, classCookie);
+ super.saveState(s);
+ s.saveBoolean(this._value);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 1:
+ super.restoreState(r);
+ this._value = r.restoreBoolean();
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/SetColorAction.java b/NET/worlds/scape/SetColorAction.java
new file mode 100644
index 0000000..655ce33
--- /dev/null
+++ b/NET/worlds/scape/SetColorAction.java
@@ -0,0 +1,108 @@
+package NET.worlds.scape;
+
+import java.awt.Color;
+import java.io.IOException;
+
+public class SetColorAction extends SlidePropertyAction {
+ private Color _value = null;
+ private Color _start;
+ private static Object classCookie = new Object();
+
+ @Override
+ public Persister trigger(Event e, Persister seqID) {
+ Persister ret = null;
+ Color val = null;
+ if (this.useParam()) {
+ try {
+ this._value = new Color(Integer.valueOf(this.param()));
+ } catch (NumberFormatException var9) {
+ System.out.println(this.getName() + " unable to parse " + this.paramName());
+ this._value = null;
+ }
+ }
+
+ if (this._value == null) {
+ assert !this.slide();
+ } else {
+ if (this.slide()) {
+ if (seqID == null) {
+ this.start();
+ this._start = (Color)this.get();
+ }
+
+ float frac = this.fraction();
+ if (frac < 1.0) {
+ int red = (int)((this._value.getRed() - this._start.getRed()) * frac) + this._start.getRed();
+ int grn = (int)((this._value.getGreen() - this._start.getGreen()) * frac) + this._start.getGreen();
+ int blu = (int)((this._value.getBlue() - this._start.getBlue()) * frac) + this._start.getBlue();
+ val = new Color(red, grn, blu);
+ ret = this;
+ }
+ }
+
+ if (val == null) {
+ val = this._value;
+ }
+ }
+
+ this.set(val);
+ return ret;
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = ColorPropertyEditor.make(new Property(this, index, "Set To").allowSetNull());
+ if (this._value == null) {
+ ret = MaybeNullPropertyEditor.make((Property)ret, Color.black);
+ }
+ } else if (mode == 1) {
+ ret = this._value;
+ } else if (mode == 2) {
+ this._value = (Color)value;
+ } else if (mode == 4) {
+ this._value = null;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 1, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(1, classCookie);
+ super.saveState(s);
+ if (this._value == null) {
+ s.saveBoolean(false);
+ } else {
+ s.saveBoolean(true);
+ s.saveInt(this._value.getRed());
+ s.saveInt(this._value.getGreen());
+ s.saveInt(this._value.getBlue());
+ }
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 1:
+ super.restoreState(r);
+ if (r.restoreBoolean()) {
+ int red = r.restoreInt();
+ int grn = r.restoreInt();
+ int blu = r.restoreInt();
+ this._value = new Color(red, grn, blu);
+ }
+
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/SetFloatAction.java b/NET/worlds/scape/SetFloatAction.java
new file mode 100644
index 0000000..9c4b354
--- /dev/null
+++ b/NET/worlds/scape/SetFloatAction.java
@@ -0,0 +1,82 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+public class SetFloatAction extends SlidePropertyAction {
+ private float _value;
+ private float _start;
+ private static Object classCookie = new Object();
+
+ @Override
+ public Persister trigger(Event e, Persister seqID) {
+ Persister ret = null;
+ if (this.useParam()) {
+ try {
+ this._value = Float.valueOf(this.param());
+ } catch (NumberFormatException var6) {
+ System.out.println(this.getName() + " unable to parse " + this.paramName());
+ this._value = 0.0F;
+ }
+ }
+
+ float val = this._value;
+ if (this.slide()) {
+ if (seqID == null) {
+ this.start();
+ this._start = (Float)this.get();
+ }
+
+ float frac = this.fraction();
+ if (frac < 1.0) {
+ val = (this._value - this._start) * frac + this._start;
+ ret = this;
+ }
+ }
+
+ this.set(new Float(val));
+ return ret;
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Set To"));
+ } else if (mode == 1) {
+ ret = new Float(this._value);
+ } else if (mode == 2) {
+ this._value = (Float)value;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 1, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(2, classCookie);
+ super.saveState(s);
+ s.saveFloat(this._value);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 1:
+ this.setPropertyActionRestoreState(r);
+ this._value = r.restoreFloat();
+ break;
+ case 2:
+ super.restoreState(r);
+ this._value = r.restoreFloat();
+ break;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/SetIntegerAction.java b/NET/worlds/scape/SetIntegerAction.java
new file mode 100644
index 0000000..888411a
--- /dev/null
+++ b/NET/worlds/scape/SetIntegerAction.java
@@ -0,0 +1,82 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+public class SetIntegerAction extends SlidePropertyAction {
+ private int _value;
+ private int _start;
+ private static Object classCookie = new Object();
+
+ @Override
+ public Persister trigger(Event e, Persister seqID) {
+ Persister ret = null;
+ if (this.useParam()) {
+ try {
+ this._value = Integer.valueOf(this.param());
+ } catch (NumberFormatException var6) {
+ System.out.println(this.getName() + " unable to parse " + this.paramName());
+ this._value = 0;
+ }
+ }
+
+ int val = this._value;
+ if (this.slide()) {
+ if (seqID == null) {
+ this.start();
+ this._start = (Integer)this.get();
+ }
+
+ float frac = this.fraction();
+ if (frac < 1.0) {
+ val = (int)((this._value - this._start) * frac + this._start);
+ ret = this;
+ }
+ }
+
+ this.set(new Integer(val));
+ return ret;
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = IntegerPropertyEditor.make(new Property(this, index, "Set To"));
+ } else if (mode == 1) {
+ ret = new Integer(this._value);
+ } else if (mode == 2) {
+ this._value = (Integer)value;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 1, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(2, classCookie);
+ super.saveState(s);
+ s.saveInt(this._value);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 1:
+ this.setPropertyActionRestoreState(r);
+ this._value = r.restoreInt();
+ break;
+ case 2:
+ super.restoreState(r);
+ this._value = r.restoreInt();
+ break;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/SetPoint2Action.java b/NET/worlds/scape/SetPoint2Action.java
new file mode 100644
index 0000000..0063719
--- /dev/null
+++ b/NET/worlds/scape/SetPoint2Action.java
@@ -0,0 +1,115 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+public class SetPoint2Action extends SlidePropertyAction {
+ private Point2 _value = null;
+ private Point2 _start;
+ private static Object classCookie = new Object();
+
+ @Override
+ public Persister trigger(Event e, Persister seqID) {
+ Persister ret = null;
+ Point2 val = null;
+ if (this.useParam()) {
+ String p = this.param();
+ if (p == null) {
+ this._value = null;
+ } else {
+ float x = 0.0F;
+ float y = 0.0F;
+ boolean ok = true;
+ int comma = p.indexOf(44);
+ if (comma == -1) {
+ ok = false;
+ } else {
+ try {
+ x = Float.valueOf(p.substring(0, comma));
+ p = p.substring(comma + 1);
+ y = Float.valueOf(p);
+ } catch (NumberFormatException var11) {
+ ok = false;
+ }
+ }
+
+ if (!ok) {
+ x = 0.0F;
+ y = 0.0F;
+ System.out.println(this.getName() + " unable to parse " + this.paramName());
+ }
+
+ this._value = new Point2(x, y);
+ }
+ }
+
+ if (this._value == null) {
+ assert !this.slide();
+ } else {
+ if (this.slide()) {
+ if (seqID == null) {
+ this.start();
+ this._start = (Point2)this.get();
+ }
+
+ float frac = this.fraction();
+ if (frac < 1.0 && this._start != null) {
+ val = new Point2(this._value);
+ val.x = (this._value.x - this._start.x) * frac + this._start.x;
+ val.y = (this._value.y - this._start.y) * frac + this._start.y;
+ ret = this;
+ }
+ }
+
+ if (val == null) {
+ val = this._value;
+ }
+ }
+
+ this.set(val);
+ return ret;
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = Point2PropertyEditor.make(new Property(this, index, "Set To").allowSetNull());
+ if (this._value == null) {
+ ret = MaybeNullPropertyEditor.make((Property)ret, new Point2());
+ }
+ } else if (mode == 1) {
+ ret = this._value;
+ } else if (mode == 2) {
+ this._value = (Point2)value;
+ } else if (mode == 4) {
+ this._value = null;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 1, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(1, classCookie);
+ super.saveState(s);
+ s.saveMaybeNull(this._value);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 1:
+ super.restoreState(r);
+ this._value = (Point2)r.restoreMaybeNull();
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/SetPoint3Action.java b/NET/worlds/scape/SetPoint3Action.java
new file mode 100644
index 0000000..e41c624
--- /dev/null
+++ b/NET/worlds/scape/SetPoint3Action.java
@@ -0,0 +1,125 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+public class SetPoint3Action extends SlidePropertyAction {
+ private Point3 _value = null;
+ private Point3 _start;
+ private static Object classCookie = new Object();
+
+ @Override
+ public Persister trigger(Event e, Persister seqID) {
+ Persister ret = null;
+ Point3 val = null;
+ if (this.useParam()) {
+ String p = this.param();
+ if (p == null) {
+ this._value = null;
+ } else {
+ float x = 0.0F;
+ float y = 0.0F;
+ float z = 0.0F;
+ boolean ok = true;
+ int comma = p.indexOf(44);
+ if (comma == -1) {
+ ok = false;
+ } else {
+ try {
+ x = Float.valueOf(p.substring(0, comma));
+ p = p.substring(comma + 1);
+ comma = p.indexOf(44);
+ if (comma == -1) {
+ ok = false;
+ } else {
+ y = Float.valueOf(p.substring(0, comma));
+ p = p.substring(comma + 1);
+ z = Float.valueOf(p);
+ }
+ } catch (NumberFormatException var12) {
+ ok = false;
+ }
+ }
+
+ if (!ok) {
+ System.out.println(this.getName() + " unable to parse " + this.paramName());
+ x = 0.0F;
+ y = 0.0F;
+ z = 0.0F;
+ }
+
+ this._value = new Point3(x, y, z);
+ }
+ }
+
+ if (this._value == null) {
+ assert !this.slide();
+ } else {
+ if (this.slide()) {
+ if (seqID == null) {
+ this.start();
+ this._start = (Point3)this.get();
+ }
+
+ float frac = this.fraction();
+ if (frac < 1.0) {
+ val = new Point3(this._value);
+ val.x = (this._value.x - this._start.x) * frac + this._start.x;
+ val.y = (this._value.y - this._start.y) * frac + this._start.y;
+ val.z = (this._value.z - this._start.z) * frac + this._start.z;
+ ret = this;
+ }
+ }
+
+ if (val == null) {
+ val = this._value;
+ }
+ }
+
+ this.set(val);
+ return ret;
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = Point3PropertyEditor.make(new Property(this, index, "Set To").allowSetNull());
+ if (this._value == null) {
+ ret = MaybeNullPropertyEditor.make((Property)ret, new Point3());
+ }
+ } else if (mode == 1) {
+ ret = this._value;
+ } else if (mode == 2) {
+ this._value = (Point3)value;
+ } else if (mode == 4) {
+ this._value = null;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 1, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(1, classCookie);
+ super.saveState(s);
+ s.saveMaybeNull(this._value);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 1:
+ super.restoreState(r);
+ this._value = (Point3)r.restoreMaybeNull();
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/SetPropertyAction.java b/NET/worlds/scape/SetPropertyAction.java
new file mode 100644
index 0000000..1bb2f45
--- /dev/null
+++ b/NET/worlds/scape/SetPropertyAction.java
@@ -0,0 +1,270 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.Gamma;
+import java.io.IOException;
+import java.text.MessageFormat;
+import java.util.Enumeration;
+
+public abstract class SetPropertyAction extends Action {
+ SuperRoot _target;
+ String _targetName;
+ String _roomName;
+ String _propName;
+ private int _propIndex = -1;
+ private String _paramName = null;
+ private static Object classCookie = new Object();
+
+ public SuperRoot getTarget() {
+ if (this._target == null && this._targetName != null) {
+ Room r = null;
+ if (this._roomName != null) {
+ World w = this.getWorld();
+ if (w != null) {
+ r = w.getRoom(this._roomName);
+ }
+ } else {
+ r = this.getRoom();
+ }
+
+ if (r != null) {
+ Enumeration list = r.getDeepOwned();
+ this._target = SuperRoot.nameSearch(list, this._targetName);
+ }
+ }
+
+ return this._target != null ? this._target : this.getOwner();
+ }
+
+ protected boolean useParam() {
+ return this._paramName != null;
+ }
+
+ protected String paramName() {
+ return this._paramName;
+ }
+
+ protected String param() {
+ return this._paramName == null ? null : Gamma.getParam(this._paramName);
+ }
+
+ static int index(int index, String name, Object target) {
+ if (index == -1 && name != null) {
+ Enumeration pe = new EnumProperties(target);
+
+ while (pe.hasMoreElements()) {
+ Property prop = (Property)pe.nextElement();
+ if (prop.getName().equals(name)) {
+ index = prop.getIndex();
+ break;
+ }
+ }
+ }
+
+ return index;
+ }
+
+ public static Object propHelper(int mode, Object value, String name, SuperRoot target) {
+ Object ret = null;
+ int i = index(-1, name, target);
+ if (i != -1) {
+ try {
+ ret = target.properties(i, 0, mode, value);
+ } catch (NoSuchPropertyException var7) {
+ }
+ }
+
+ return ret;
+ }
+
+ private Object propHelper(int mode, Object value) {
+ SuperRoot target = this.getTarget();
+ Object ret = null;
+ if ((this._propIndex = index(this._propIndex, this._propName, target)) != -1) {
+ try {
+ ret = target.properties(this._propIndex, 0, mode, value);
+ } catch (NoSuchPropertyException var6) {
+ assert false;
+ }
+ } else if (target == null) {
+ Console.println(this.getName() + Console.message("null-target"));
+ } else if (this._propName == null) {
+ Object[] arguments = new Object[]{new String(this.getName()), new String(this.getTarget().getName())};
+ Console.println(MessageFormat.format(Console.message("null-property"), arguments));
+ } else {
+ Object[] arguments = new Object[]{new String(this.getName()), new String(this._propName), new String(this.getTarget().getName())};
+ Console.println(MessageFormat.format(Console.message("non-property"), arguments));
+ }
+
+ return ret;
+ }
+
+ protected final void set(Object value) {
+ this.propHelper(2, value);
+ }
+
+ protected final Object get() {
+ return this.propHelper(1, null);
+ }
+
+ protected final void add(Object value) {
+ this.propHelper(3, value);
+ }
+
+ protected final void remove(Object value) {
+ this.propHelper(4, value);
+ }
+
+ protected final Property enumerate() {
+ return (Property)this.propHelper(0, null);
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ Property p = new Property(this, index, "Target");
+ p.allowSetNull();
+ ret = ObjPropertyEditor.make(p, this.getRoom(), "NET.worlds.scape.SuperRoot");
+ } else if (mode == 1) {
+ ret = this.getTarget();
+ } else if (mode == 2) {
+ this._target = (SuperRoot)value;
+ this._propIndex = -1;
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Target Room"));
+ } else if (mode == 1) {
+ ret = this._roomName;
+ } else if (mode == 4) {
+ this._roomName = null;
+ } else if (mode == 2) {
+ this._roomName = (String)value;
+ this._target = null;
+ }
+ break;
+ case 2:
+ if (mode == 0) {
+ Property p = new Property(this, index, "Target Name");
+ p.allowSetNull();
+ ret = StringPropertyEditor.make(p);
+ } else if (mode == 1) {
+ ret = this._targetName;
+ } else if (mode == 4) {
+ this._targetName = null;
+ } else if (mode == 2) {
+ this._targetName = (String)value;
+ this._target = null;
+ }
+ break;
+ case 3:
+ if (mode == 0) {
+ ret = new Property(this, index, "Property Name");
+ if (this.getTarget() != null) {
+ ret = PropPropEditor.make((Property)ret, this.getTarget(), true);
+ }
+ } else if (mode == 1) {
+ SuperRoot t = this.getTarget();
+ if ((this._propIndex = index(this._propIndex, this._propName, t)) != -1 && t != null) {
+ ret = this.enumerate();
+ } else {
+ ret = null;
+ }
+ } else if (mode == 2) {
+ if (value == null) {
+ this._propIndex = -1;
+ this._propName = null;
+ } else if (value instanceof String) {
+ this._propIndex = -1;
+ this._propName = (String)value;
+ } else {
+ this._propIndex = ((Property)value).getIndex();
+ this._propName = ((Property)value).getName();
+ }
+ }
+ break;
+ case 4:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Use parameter"), "Use 'Set To' value", "Use parameter");
+ } else if (mode == 1) {
+ ret = new Boolean(this._paramName != null);
+ } else if (mode == 2) {
+ if ((Boolean)value) {
+ if (this._paramName == null) {
+ this._paramName = "";
+ }
+ } else {
+ this._paramName = null;
+ }
+ }
+ break;
+ case 5:
+ if (mode == 0) {
+ ret = new Property(this, index, "Parameter Name");
+ if (this._paramName != null) {
+ ret = StringPropertyEditor.make((Property)ret);
+ }
+ } else if (mode == 1) {
+ ret = this._paramName == null ? "" : this._paramName;
+ } else if (mode == 2) {
+ this._paramName = (String)value;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 6, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(4, classCookie);
+ super.saveState(s);
+ s.saveMaybeNull(this.getTarget());
+ s.saveString(this._roomName);
+ s.saveString(this._targetName);
+ s.saveString(this._propName);
+ s.saveString(this._paramName);
+ }
+
+ protected void setPropertyActionRestoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 1:
+ super.restoreState(r);
+ this._target = (SuperRoot)r.restore();
+ this._propName = r.restoreString();
+ break;
+ case 2:
+ super.restoreState(r);
+ this._target = (SuperRoot)r.restoreMaybeNull();
+ this._propName = r.restoreString();
+ break;
+ case 3:
+ super.restoreState(r);
+ this._target = (SuperRoot)r.restoreMaybeNull();
+ this._propName = r.restoreString();
+ this._paramName = r.restoreString();
+ break;
+ case 4:
+ super.restoreState(r);
+ this._target = (SuperRoot)r.restoreMaybeNull();
+ this._roomName = r.restoreString();
+ this._targetName = r.restoreString();
+ this._propName = r.restoreString();
+ this._paramName = r.restoreString();
+ break;
+ default:
+ throw new TooNewException();
+ }
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ this.setPropertyActionRestoreState(r);
+ }
+}
diff --git a/NET/worlds/scape/SetStringAction.java b/NET/worlds/scape/SetStringAction.java
new file mode 100644
index 0000000..059d25e
--- /dev/null
+++ b/NET/worlds/scape/SetStringAction.java
@@ -0,0 +1,57 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+public class SetStringAction extends SetPropertyAction {
+ private String _value;
+ private static Object classCookie = new Object();
+
+ @Override
+ public Persister trigger(Event e, Persister seqID) {
+ if (this.useParam()) {
+ this._value = this.param();
+ }
+
+ this.set(this._value);
+ return null;
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Set To"));
+ } else if (mode == 1) {
+ ret = this._value;
+ } else if (mode == 2) {
+ this._value = (String)value;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 1, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(1, classCookie);
+ super.saveState(s);
+ s.saveString(this._value);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 1:
+ super.restoreState(r);
+ this._value = r.restoreString();
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/SetURLAction.java b/NET/worlds/scape/SetURLAction.java
new file mode 100644
index 0000000..6cbc8ff
--- /dev/null
+++ b/NET/worlds/scape/SetURLAction.java
@@ -0,0 +1,68 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Cursor;
+import NET.worlds.network.URL;
+import java.io.IOException;
+import java.net.MalformedURLException;
+
+public class SetURLAction extends SetPropertyAction {
+ URL _value;
+ private static Object classCookie = new Object();
+
+ @Override
+ public Persister trigger(Event e, Persister seqID) {
+ if (this.useParam()) {
+ try {
+ this._value = new URL(this.param());
+ } catch (MalformedURLException var4) {
+ System.out.println(this.getName() + " unable to parse " + this.paramName());
+ }
+ }
+
+ this.set(this._value);
+ return null;
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = URLPropertyEditor.make(
+ new Property(this, index, "Set To").allowSetNull(),
+ "ani;console;cur;drone;mid;mov;pilot;ra;ram;rwg;rwx;wav;wob;world;" + TextureDecoder.getAllExts(),
+ Cursor.getSysCursorURLs()
+ );
+ } else if (mode == 1) {
+ ret = this._value;
+ } else if (mode == 2) {
+ this._value = (URL)value;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 1, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(1, classCookie);
+ super.saveState(s);
+ URL.save(s, this._value);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 1:
+ super.restoreState(r);
+ this._value = URL.restore(r);
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/SetVisibleBumpableAction.java b/NET/worlds/scape/SetVisibleBumpableAction.java
new file mode 100644
index 0000000..6e05bfb
--- /dev/null
+++ b/NET/worlds/scape/SetVisibleBumpableAction.java
@@ -0,0 +1,73 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+public class SetVisibleBumpableAction extends Action {
+ public boolean targetBumpable = true;
+ public boolean targetVisible = true;
+ private static Object classCookie = new Object();
+
+ @Override
+ public Persister trigger(Event e, Persister seqID) {
+ Object owner = this.getOwner();
+ if (owner != null && owner instanceof WObject) {
+ WObject o = (WObject)owner;
+ o.setBumpable(this.targetBumpable);
+ o.setVisible(this.targetVisible);
+ return null;
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Target Bumpable"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(this.targetBumpable);
+ } else if (mode == 2) {
+ this.targetBumpable = (Boolean)value;
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Target Visible"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(this.targetVisible);
+ } else if (mode == 2) {
+ this.targetVisible = (Boolean)value;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 2, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(1, classCookie);
+ super.saveState(s);
+ s.saveBoolean(this.targetBumpable);
+ s.saveBoolean(this.targetVisible);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 1:
+ super.restoreState(r);
+ case 0:
+ this.targetBumpable = r.restoreBoolean();
+ this.targetVisible = r.restoreBoolean();
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/SetZoomMode.java b/NET/worlds/scape/SetZoomMode.java
new file mode 100644
index 0000000..739f2ac
--- /dev/null
+++ b/NET/worlds/scape/SetZoomMode.java
@@ -0,0 +1,61 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Window;
+import java.io.IOException;
+import java.util.Enumeration;
+
+public class SetZoomMode extends Action implements MomentumBehavior {
+ private boolean zoomMode;
+ private static Object classCookie = new Object();
+
+ public SetZoomMode(boolean on) {
+ this.zoomMode = on;
+ }
+
+ public SetZoomMode() {
+ }
+
+ @Override
+ public Persister trigger(Event e, Persister seqID) {
+ SuperRoot owner = this.getOwner();
+ if (owner != null && owner instanceof Pilot && ((Pilot)owner).isActive()) {
+ Window w = Window.getMainWindow();
+ if (w == null) {
+ return null;
+ } else {
+ w.setDeltaMode(this.zoomMode);
+ return null;
+ }
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(0, classCookie);
+ super.saveState(s);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+
+ @Override
+ public void transferFrom(Enumeration oldMBs) {
+ while (oldMBs.hasMoreElements()) {
+ SuperRoot sr = (SuperRoot)oldMBs.nextElement();
+ if (sr instanceof SetZoomMode) {
+ this.zoomMode = ((SetZoomMode)sr).zoomMode;
+ break;
+ }
+ }
+ }
+}
diff --git a/NET/worlds/scape/Shadow.java b/NET/worlds/scape/Shadow.java
new file mode 100644
index 0000000..7fe9cab
--- /dev/null
+++ b/NET/worlds/scape/Shadow.java
@@ -0,0 +1,5 @@
+package NET.worlds.scape;
+
+public interface Shadow {
+ void adjustShadow(WObject var1);
+}
diff --git a/NET/worlds/scape/ShallowEnumeration.java b/NET/worlds/scape/ShallowEnumeration.java
new file mode 100644
index 0000000..ac8fbc3
--- /dev/null
+++ b/NET/worlds/scape/ShallowEnumeration.java
@@ -0,0 +1,38 @@
+package NET.worlds.scape;
+
+import java.util.Vector;
+
+public class ShallowEnumeration extends DeepEnumeration {
+ public ShallowEnumeration(SuperRoot o) {
+ this.roots.addElement(o);
+ o.getChildren(this);
+ }
+
+ @Override
+ protected void getNextElement() {
+ this.valueRetrieved = false;
+ if (!this.roots.isEmpty()) {
+ this.nextValue = this.roots.elementAt(this.roots.size() - 1);
+
+ assert this.nextValue != null;
+
+ this.roots.removeElementAt(this.roots.size() - 1);
+ } else if (this.currentIndex >= 0) {
+ try {
+ this.nextValue = (SuperRoot)this.currentVector.elementAt(this.currentIndex--);
+ } catch (ArrayIndexOutOfBoundsException var2) {
+ this.currentIndex = this.currentVector.size() - 1;
+ this.getNextElement();
+ }
+
+ assert this.nextValue != null;
+ } else if (!this.vectors.isEmpty()) {
+ this.currentVector = (Vector<K>)this.vectors.elementAt(this.vectors.size() - 1);
+ this.currentIndex = this.currentVector.size() - 1;
+ this.vectors.removeElementAt(this.vectors.size() - 1);
+ this.getNextElement();
+ } else {
+ this.nextValue = null;
+ }
+ }
+}
diff --git a/NET/worlds/scape/Shape.java b/NET/worlds/scape/Shape.java
new file mode 100644
index 0000000..597b404
--- /dev/null
+++ b/NET/worlds/scape/Shape.java
@@ -0,0 +1,557 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.DefaultConsole;
+import NET.worlds.console.Main;
+import NET.worlds.console.MainCallback;
+import NET.worlds.console.StatMemNode;
+import NET.worlds.core.Archive;
+import NET.worlds.core.IniFile;
+import NET.worlds.network.URL;
+import java.awt.PopupMenu;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.util.Enumeration;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+public class Shape extends WObject implements MainCallback, Animatable, MouseDownHandler {
+ static int disableLOD = IniFile.gamma().getIniInt("DisableLOD", 1);
+ static int forceLODLevel;
+ Vector<ShapeLoaderListener> listeners = null;
+ URL url;
+ boolean mustReload;
+ boolean recomputeLODs;
+ int numDetailLevels;
+ int currentLOD;
+ int lastLOD;
+ URL[] lodURLs;
+ float[] lodDistanceTriggers;
+ float[] lodAreas;
+ protected static int NORMAL;
+ protected static int ERROR;
+ protected static int LOADING;
+ private int pendingShape;
+ boolean isDefault;
+ static URL xShape;
+ URL realFile;
+ private boolean prepareRoom;
+ private Material animatableMaterial;
+ protected int animatableClumpID;
+ Vector<Texture> textures;
+ private static Object classCookie;
+
+ static {
+ if (ProgressiveAdder.get().enabled()) {
+ disableLOD = 1;
+ }
+
+ if (disableLOD == 1) {
+ System.out.println("Avatar dynamic LOD disabled.");
+ } else {
+ System.out.println("Using avatar dynamic LOD when available.");
+ }
+
+ StatMemNode smn = StatMemNode.getNode();
+ forceLODLevel = IniFile.gamma().getIniInt("LowResAvs", -1);
+ if (forceLODLevel != -1) {
+ System.out.println("Avatar LOD's forced to level " + forceLODLevel);
+ disableLOD = 0;
+ }
+
+ int lowResThreshold = IniFile.gamma().getIniInt("ForceLowResRAMLimit", 33554432);
+ smn.updateMemoryStatus();
+ if (smn._totPhysMem <= lowResThreshold && smn._totPhysMem > 0) {
+ System.out.println("Low memory detected, using LOD 2 for all avatars.");
+ forceLODLevel = 2;
+ disableLOD = 0;
+ }
+
+ NORMAL = 0;
+ ERROR = -1;
+ LOADING = -2;
+ xShape = URL.make("home:avatar.rwg");
+ nativeInit();
+ classCookie = new Object();
+ }
+
+ public Shape() {
+ this.pendingShape = NORMAL;
+ this.isDefault = false;
+ this.numDetailLevels = 0;
+ this.recomputeLODs = true;
+ this.currentLOD = this.lastLOD = 0;
+ }
+
+ void addLoadListener(ShapeLoaderListener l) {
+ if (this.listeners == null) {
+ this.listeners = new Vector<ShapeLoaderListener>();
+ }
+
+ if (!this.listeners.contains(l)) {
+ this.listeners.addElement(l);
+ }
+ }
+
+ private void notifyLoadListeners() {
+ if (this.listeners != null) {
+ Enumeration<ShapeLoaderListener> e = this.listeners.elements();
+ if (e != null) {
+ while (e.hasMoreElements()) {
+ ShapeLoaderListener l = e.nextElement();
+ l.notifyShapeLoaded(this);
+ }
+ }
+
+ this.listeners.removeAllElements();
+ }
+ }
+
+ void removeLoadListener(ShapeLoaderListener l) {
+ if (this.listeners != null) {
+ this.listeners.removeElement(l);
+ }
+ }
+
+ public void setBaseLODURL(URL baseURL) {
+ if (disableLOD == 0 && baseURL != null && baseURL.getAbsolute().startsWith("avatar:")) {
+ int colon = baseURL.toString().indexOf(58);
+ int dot = baseURL.toString().indexOf(46);
+ String avName = baseURL.toString().substring(colon + 1, dot);
+ String avURLName = "avatar:lod/" + avName + ".lod";
+
+ URL lodURL;
+ try {
+ lodURL = new URL(avURLName);
+ } catch (MalformedURLException var16) {
+ return;
+ }
+
+ byte[] lodFile = Archive.readTextFile(lodURL.unalias());
+ if (lodFile != null) {
+ String lodText = new String(lodFile);
+ StringTokenizer tk = new StringTokenizer(lodText);
+ this.numDetailLevels = Integer.parseInt(tk.nextToken());
+ this.lodURLs = new URL[this.numDetailLevels];
+ this.lodAreas = new float[this.numDetailLevels];
+ this.lodDistanceTriggers = new float[this.numDetailLevels];
+ int x = 0;
+ this.lodURLs[x] = baseURL;
+
+ for (this.lodAreas[x++] = 0.0F; tk.hasMoreTokens(); x++) {
+ String level = tk.nextToken();
+ String value = tk.nextToken();
+ Float f = new Float(value);
+ this.lodAreas[x] = f;
+
+ try {
+ this.lodURLs[x] = new URL("avatar:lod/" + avName + level + baseURL.toString().substring(dot));
+ } catch (MalformedURLException var15) {
+ System.out.println("Error creating lod URL!\n");
+ this.numDetailLevels = 0;
+ return;
+ }
+ }
+ }
+ }
+
+ this.recomputeLODs = true;
+ }
+
+ public native float calcLODDistance(float var1);
+
+ public synchronized boolean setLOD(float dist) {
+ boolean switched = false;
+ if (this.numDetailLevels > 0) {
+ if (forceLODLevel != -1) {
+ int realLOD = forceLODLevel > this.numDetailLevels - 1 ? this.numDetailLevels - 1 : forceLODLevel;
+ if (realLOD != this.lastLOD) {
+ this.setURL(this.lodURLs[realLOD]);
+ this.currentLOD = this.lastLOD = realLOD;
+ return true;
+ }
+
+ return false;
+ }
+
+ if (this.recomputeLODs) {
+ for (int x = 0; x < this.numDetailLevels; x++) {
+ this.lodDistanceTriggers[x] = this.calcLODDistance(this.lodAreas[x]);
+ }
+
+ this.recomputeLODs = false;
+ }
+
+ for (int lod = 0; lod < this.numDetailLevels; lod++) {
+ if (this.lodDistanceTriggers[lod] > dist) {
+ if (lod != this.lastLOD) {
+ this.currentLOD = lod;
+ if (this instanceof PosableShape) {
+ ((PosableShape)this).removeSubparts();
+ }
+
+ if (this.isLoaded()) {
+ this.releasePendingShape();
+ }
+
+ this.setURL(this.lodURLs[lod]);
+ }
+ break;
+ }
+ }
+ }
+
+ if (this.lastLOD != this.currentLOD) {
+ switched = true;
+ }
+
+ this.lastLOD = this.currentLOD;
+ return switched;
+ }
+
+ public URL getURL() {
+ return this.url;
+ }
+
+ synchronized boolean isLoaded() {
+ return this.pendingShape < -2 || this.pendingShape > 0;
+ }
+
+ public boolean isFullyLoaded() {
+ return this.pendingShape == NORMAL && this.hasClump();
+ }
+
+ @Override
+ public boolean handle(MouseDownEvent e) {
+ SuperRoot ultimateOwner = this;
+
+ while (ultimateOwner.getOwner() != null) {
+ ultimateOwner = ultimateOwner.getOwner();
+ if (ultimateOwner instanceof PosableShape && ultimateOwner.getOwner() instanceof PosableDrone) {
+ return false;
+ }
+ }
+
+ PopupMenu m = new PopupMenu();
+ if (AnimatedActionManager.get().buildActionMenu(m, this)) {
+ Console c = Console.getActive();
+ if (c instanceof DefaultConsole) {
+ DefaultConsole dc = (DefaultConsole)c;
+ if (dc.getRender() != null) {
+ dc.getRender().add(m);
+ m.addActionListener(AnimatedActionManager.get());
+ m.show(dc.getRender(), e.x, e.y);
+ return true;
+ }
+ }
+ }
+
+ m = WorldScriptManager.getInstance().shapeClicked(this);
+ if (m != null) {
+ Console c = Console.getActive();
+ if (c instanceof DefaultConsole) {
+ DefaultConsole dc = (DefaultConsole)c;
+ if (dc.getRender() != null) {
+ dc.getRender().add(m);
+ m.addActionListener(WorldScriptManager.getInstance());
+ m.show(dc.getRender(), e.x, e.y);
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ void setState(int mode, Vector<Texture> texs) {
+ if (this.isLoaded()) {
+ this.releasePendingShape();
+ }
+
+ this.releaseTextures();
+ this.pendingShape = mode;
+ if (this.isLoaded()) {
+ this.shapeRedraw();
+ }
+
+ this.textures = texs;
+ }
+
+ public synchronized void setURL(URL newName) {
+ if (newName != this.url && (newName == null || !newName.equals(this.url))) {
+ this.url = newName;
+ this.realFile = null;
+ boolean mrWas = this.mustReload;
+ this.mustReload = true;
+ this.setState(NORMAL, null);
+ this.shapeRedraw();
+ this.mustReload = mrWas;
+ }
+ }
+
+ void shapeRedraw() {
+ if (this.hasClump()) {
+ this.reclump();
+ }
+
+ this.notifyLoadListeners();
+ }
+
+ boolean isAv() {
+ return this.url != null && this.url.getAbsolute().startsWith("avatar:");
+ }
+
+ static String getBodBase(URL u) {
+ String s = u.getBase();
+ int len = s.length();
+ return s.endsWith(".bod") && len >= 6 ? s.substring(0, len - 6) : null;
+ }
+
+ int getBodPartNum() {
+ String s = this.url.getInternal();
+ int len = s.length();
+ return s.endsWith(".bod") && len >= 6 ? (s.charAt(len - 6) - 48) * 10 + (s.charAt(len - 5) - 48) : 0;
+ }
+
+ @Override
+ protected synchronized void addRwChildren(WObject container) {
+ assert !this.hasClump();
+
+ if (this.pendingShape == NORMAL && this.url != null) {
+ String urlStr;
+ if ((urlStr = this.url.getAbsolute()).startsWith("system:subclump")) {
+ SuperRoot o = this.getOwner();
+ if (o instanceof Shape) {
+ int num = 0;
+
+ try {
+ num = new Integer(urlStr.substring(15));
+ } catch (NumberFormatException var6) {
+ }
+
+ this.animatableClumpID = ((Shape)o).extractSubclump(num);
+ this.clumpID = addEmptyParentClump(this.animatableClumpID);
+ this.isDefault = false;
+ this.newRwClumpChildHelper(container);
+ return;
+ }
+
+ this.pendingShape = ERROR;
+ } else {
+ this.setState(-2, null);
+ this.isDefault = false;
+ this.realFile = this.isAv() ? xShape : this.url;
+ if (this.url.endsWith(".bod")) {
+ String s = getBodBase(this.url);
+ this.realFile = URL.make(this.url, s + ".bod");
+ }
+
+ BackgroundLoader.get(new ShapeLoader(this), this.realFile);
+ }
+ }
+
+ if (!this.isLoaded()) {
+ this.clumpID = makeDefaultShape();
+ this.isDefault = true;
+ } else {
+ this.clumpID = this.pendingShape;
+ this.pendingShape = NORMAL;
+ this.isDefault = false;
+ }
+
+ this.newRwClumpChildHelper(container);
+ }
+
+ @Override
+ public void recursiveAddRwChildren(WObject parent) {
+ if (this.animatableMaterial != null && this.animatableClumpID == 0) {
+ this.animatableMaterial.addRwChildren();
+ }
+
+ super.recursiveAddRwChildren(parent);
+ if (this.animatableMaterial != null) {
+ this.nativeSetMaterial(this.animatableMaterial);
+ }
+ }
+
+ public Material getMaterial() {
+ return this.animatableMaterial;
+ }
+
+ @Override
+ protected void voidClump() {
+ if (!this.mustReload && !this.isDefault && this.pendingShape == NORMAL) {
+ this.pendingShape = this.extractClump();
+ } else {
+ if (this.isLoaded()) {
+ this.releasePendingShape();
+ }
+
+ this.releaseTextures();
+ super.voidClump();
+ this.animatableClumpID = 0;
+ if (this.animatableMaterial != null) {
+ this.animatableMaterial.markVoid();
+ }
+ }
+ }
+
+ @Override
+ public void discard() {
+ if (this.isLoaded()) {
+ this.releasePendingShape();
+ }
+
+ this.releaseTextures();
+ super.discard();
+ }
+
+ public void makeSpecials() {
+ if (!this.prepareRoom) {
+ Vector<WObject> detachList = new Vector<WObject>();
+ Enumeration<Object> e = (Enumeration<Object>)this.getRoom().getContents();
+
+ while (e.hasMoreElements()) {
+ Object p = e.nextElement();
+ if (p instanceof WObject) {
+ WObject w = (WObject)p;
+ if (w.getAutobuilt()) {
+ detachList.addElement(w);
+ }
+ }
+ }
+
+ e = detachList.elements();
+
+ while (e.hasMoreElements()) {
+ ((WObject)e.nextElement()).detach();
+ }
+
+ Main.register(this);
+ this.prepareRoom = true;
+ }
+ }
+
+ @Override
+ public void mainCallback() {
+ if (this.hasClump()) {
+ convertSpecial(this.clumpID);
+ this.prepareRoom = false;
+ Main.unregister(this);
+ }
+ }
+
+ @Override
+ public void setMaterial(Material m) {
+ if (this.animatableMaterial != null) {
+ this.animatableMaterial.detach();
+ }
+
+ this.add(m);
+ this.animatableMaterial = m;
+ this.nativeSetMaterial(m);
+ }
+
+ public native void nativeSetMaterial(Material var1);
+
+ protected native int extractSubclump(int var1);
+
+ protected static native int addEmptyParentClump(int var0);
+
+ private static native void convertSpecial(int var0);
+
+ public static native void nativeInit();
+
+ private static native int makeDefaultShape();
+
+ private native void releasePendingShape();
+
+ private void releaseTextures() {
+ if (this.textures != null) {
+ Enumeration<Texture> en = this.textures.elements();
+
+ while (en.hasMoreElements()) {
+ en.nextElement().decRef();
+ }
+
+ this.textures = null;
+ }
+ }
+
+ @Override
+ protected void finalize() {
+ if (this.isLoaded()) {
+ this.releasePendingShape();
+ }
+
+ this.releaseTextures();
+ super.finalize();
+ }
+
+ public void setReload(boolean mustReload) {
+ this.mustReload = mustReload;
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = URLPropertyEditor.make(new Property(this, index, "File"), "rwx;rwg;bod");
+ } else if (mode == 1) {
+ ret = this.url;
+ } else if (mode == 2) {
+ URL newName = (URL)value;
+ if (newName != null && newName.equals(this.url)) {
+ this.setURL(null);
+ }
+
+ this.setURL(newName);
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "PrepareRoom"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(this.prepareRoom);
+ } else if (mode == 2 && (Boolean)value) {
+ this.makeSpecials();
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 2, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(1, classCookie);
+ super.saveState(s);
+ URL.save(s, this.url);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ case 1:
+ super.restoreState(r);
+ URL url = URL.restore(r);
+ if (url != null) {
+ this.setURL(url);
+ }
+
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + "[" + this.url + "]";
+ }
+}
diff --git a/NET/worlds/scape/ShapeLoader.java b/NET/worlds/scape/ShapeLoader.java
new file mode 100644
index 0000000..abee9b8
--- /dev/null
+++ b/NET/worlds/scape/ShapeLoader.java
@@ -0,0 +1,113 @@
+package NET.worlds.scape;
+
+import NET.worlds.network.URL;
+import java.util.Enumeration;
+import java.util.Vector;
+
+public class ShapeLoader implements BGLoaded {
+ Shape shape;
+ int binaryParam;
+ private int numTexturesLoading;
+ private Vector<Texture> textures;
+ private boolean wasError;
+
+ public ShapeLoader(Shape s) {
+ this.shape = s;
+ }
+
+ @Override
+ public Room getBackgroundLoadRoom() {
+ return this.shape.getRoom();
+ }
+
+ @Override
+ public Object asyncBackgroundLoad(String localName, URL remoteName) {
+ if (localName == null) {
+ return null;
+ } else if (remoteName.endsWith(".rwg") || remoteName.endsWith(".RWG")) {
+ this.binaryParam = this.loadBinaryFile(localName, remoteName);
+ return new Object();
+ } else if (remoteName.endsWith(".rwx") || remoteName.endsWith(".RWX")) {
+ this.loadTextFile(localName, remoteName);
+ return localName;
+ } else {
+ return !remoteName.endsWith(".bod") && !remoteName.endsWith(".BOD") ? null : localName;
+ }
+ }
+
+ @Override
+ public boolean syncBackgroundLoad(Object o, URL remoteURL) {
+ if (o == null) {
+ return false;
+ } else if (this.numTexturesLoading > 0) {
+ return true;
+ } else {
+ if (!remoteURL.equals(this.shape.realFile)) {
+ this.wasError = true;
+ } else if (!this.shape.hasClump() && this.shape.isDefault) {
+ this.wasError = true;
+ if (!this.shape.isLoaded()) {
+ this.shape.setState(0, null);
+ }
+ }
+
+ int newModel;
+ if (o instanceof String) {
+ if (!this.wasError) {
+ if (remoteURL.endsWith(".bod")) {
+ newModel = this.loadBodFile((String)o, this.shape.getBodPartNum());
+ } else {
+ newModel = this.finishLoadingTextFile((String)o);
+ }
+ } else {
+ newModel = 0;
+ }
+ } else {
+ newModel = this.finishLoadingBinaryFile(this.binaryParam, this.wasError);
+ }
+
+ if (newModel != 0) {
+ this.shape.setState(newModel, this.textures);
+ }
+
+ if ((newModel == 0 || newModel == -1) && this.textures != null) {
+ Enumeration<Texture> en = this.textures.elements();
+
+ while (en.hasMoreElements()) {
+ en.nextElement().decRef();
+ }
+ }
+
+ this.textures = null;
+ return false;
+ }
+ }
+
+ private void startTextureLoad(String relName, URL remoteName) {
+ this.numTexturesLoading++;
+ BackgroundLoader.get(new ShapeTextureLoader(this), URL.make(remoteName, relName), true);
+ }
+
+ synchronized void textureLoadEnd(Texture tex) {
+ this.numTexturesLoading--;
+ if (tex != null) {
+ if (this.textures == null) {
+ this.textures = new Vector<Texture>();
+ }
+
+ this.textures.addElement(tex);
+ } else {
+ this.wasError = true;
+ }
+ }
+
+ private native void loadTextFile(String var1, URL var2);
+
+ private native int finishLoadingTextFile(String var1);
+
+ private native int loadBodFile(String var1, int var2);
+
+ private native int loadBinaryFile(String var1, URL var2);
+
+ private native int finishLoadingBinaryFile(int var1, boolean var2);
+}
diff --git a/NET/worlds/scape/ShapeLoaderListener.java b/NET/worlds/scape/ShapeLoaderListener.java
new file mode 100644
index 0000000..d91be55
--- /dev/null
+++ b/NET/worlds/scape/ShapeLoaderListener.java
@@ -0,0 +1,5 @@
+package NET.worlds.scape;
+
+public interface ShapeLoaderListener {
+ void notifyShapeLoaded(Shape var1);
+}
diff --git a/NET/worlds/scape/ShapeTextureLoader.java b/NET/worlds/scape/ShapeTextureLoader.java
new file mode 100644
index 0000000..1ba82e3
--- /dev/null
+++ b/NET/worlds/scape/ShapeTextureLoader.java
@@ -0,0 +1,27 @@
+package NET.worlds.scape;
+
+import NET.worlds.network.URL;
+
+class ShapeTextureLoader implements BGLoaded {
+ ShapeLoader shapeLoader;
+
+ public ShapeTextureLoader(ShapeLoader s) {
+ this.shapeLoader = s;
+ }
+
+ @Override
+ public Object asyncBackgroundLoad(String localName, URL remoteName) {
+ this.shapeLoader.textureLoadEnd(TextureDecoder.decode(remoteName, remoteName.getBaseWithoutExt(), localName));
+ return null;
+ }
+
+ @Override
+ public boolean syncBackgroundLoad(Object obj, URL remoteURL) {
+ return false;
+ }
+
+ @Override
+ public Room getBackgroundLoadRoom() {
+ return this.shapeLoader.getBackgroundLoadRoom();
+ }
+}
diff --git a/NET/worlds/scape/Sharer.java b/NET/worlds/scape/Sharer.java
new file mode 100644
index 0000000..aaa03eb
--- /dev/null
+++ b/NET/worlds/scape/Sharer.java
@@ -0,0 +1,590 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.Main;
+import NET.worlds.console.MainCallback;
+import NET.worlds.core.Std;
+import NET.worlds.network.InfiniteWaitException;
+import NET.worlds.network.ObjID;
+import NET.worlds.network.PacketTooLargeException;
+import NET.worlds.network.PropertyList;
+import NET.worlds.network.PropertySetCmd;
+import NET.worlds.network.WorldServer;
+import NET.worlds.network.net2Property;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.text.MessageFormat;
+import java.util.Enumeration;
+import java.util.Vector;
+
+public class Sharer extends SuperRoot implements MainCallback {
+ private Vector<Attribute> attributes;
+ private ByteArrayOutputStream bs = new ByteArrayOutputStream();
+ private boolean shared = false;
+ public static final int FIRST_TIME = 0;
+ public static final int STATIC = 2;
+ public static final int FORWARDED_STATIC = 3;
+ public static final int DYNAMIC = 4;
+ public static final int FORWARDED_DYNAMIC = 5;
+ public static final int FORWARDED = 1;
+ private boolean createdFromNet;
+ Vector<Attribute> noteQ;
+ Vector<Attribute> prepQ;
+ Vector<Attribute> sendQ;
+ private DynamicForwardAttribute dfa;
+ int lastSendTime;
+ private static Object classCookie = new Object();
+ private Vector<Object> restoredAttributes = null;
+
+ public Sharer() {
+ this.attributes = new Vector<Attribute>(256);
+ this.attributes.setSize(256);
+ }
+
+ public boolean isShared() {
+ return this.shared;
+ }
+
+ private int getMaybeDefaultMode() {
+ return ((WObject)this.getOwner()).getSharerMode();
+ }
+
+ public int getMode() {
+ int mode = this.getMaybeDefaultMode();
+ if (mode == 0) {
+ this.setMode(mode);
+ }
+
+ return mode;
+ }
+
+ public void setMode(int mode) {
+ WObject w = (WObject)this.getOwner();
+ if (w instanceof Room) {
+ mode = 2;
+ } else if (this.createdFromNet) {
+ mode = 4;
+ } else if (mode == 2 || mode == 4) {
+ mode = 0;
+ }
+
+ if (mode == 0) {
+ mode = 3;
+ }
+
+ int oldMode = this.getMaybeDefaultMode();
+ if (oldMode != mode) {
+ this.unshare();
+ w.setSharerMode(mode);
+ }
+
+ this.share();
+ }
+
+ public void createDynamicForwardedFromNet(DynamicForwardAttribute dfa) {
+ assert !((WObject)this.getOwner()).isActive();
+
+ this.dfa = dfa;
+ ((WObject)this.getOwner()).setSharerMode(5);
+ }
+
+ public void createDynamicFromNet() {
+ assert !((WObject)this.getOwner()).isActive() || this.createdFromNet;
+
+ this.createdFromNet = true;
+ ((WObject)this.getOwner()).setSharerMode(4);
+ }
+
+ public void adjustShare() {
+ this.share();
+ }
+
+ private void share() {
+ if (!this.shared) {
+ int mode = this.getMaybeDefaultMode();
+ switch (mode) {
+ case 0:
+ this.setMode(0);
+ case 1:
+ case 2:
+ default:
+ break;
+ case 3:
+ this.flushQueue();
+ Enumeration<Attribute> e = this.getAttributes();
+
+ while (e.hasMoreElements()) {
+ e.nextElement().addForwarding();
+ }
+ break;
+ case 4:
+ assert this.createdFromNet;
+ break;
+ case 5:
+ if (this.dfa == null) {
+ this.flushQueue();
+ WObject w = (WObject)this.getOwner();
+ WObject terminal = w.getServed();
+ if (w.getSourceURL() != null && terminal != null) {
+ this.dfa = new DynamicForwardAttribute(-1);
+ if (terminal.getSharer().addAttribute(this.dfa) == -1) {
+ this.dfa = null;
+ } else {
+ this.dfa.connect(w);
+ }
+ }
+ }
+ }
+
+ this.shared = true;
+ }
+ }
+
+ private void unshare() {
+ if (this.shared) {
+ int mode = this.getMaybeDefaultMode();
+ switch (mode) {
+ case 2:
+ case 4:
+ default:
+ break;
+ case 3:
+ Enumeration<Attribute> e = this.getAttributes();
+
+ while (e.hasMoreElements()) {
+ e.nextElement().unforward();
+ }
+ break;
+ case 5:
+ if (this.dfa != null) {
+ this.dfa.unconnect();
+ this.dfa = null;
+ }
+ }
+
+ this.shared = false;
+ }
+ }
+
+ public int addAttribute(Attribute a) {
+ this.setMode(this.getMaybeDefaultMode());
+ a._attrID = this.getFreeAttrIDFor(a, a._attrID);
+ if (a._attrID == -1) {
+ return a._attrID;
+ } else {
+ try {
+ this.add(a);
+ } catch (ClassCastException var3) {
+ Console.println(Console.message("Cant-attach") + var3);
+ a._attrID = -1;
+ return a._attrID;
+ }
+
+ this.attributes.setElementAt(a, a._attrID);
+ if (this.getMaybeDefaultMode() == 3) {
+ a.addForwarding();
+ }
+
+ return a._attrID;
+ }
+ }
+
+ public boolean attrIDAvailable(int id) {
+ return this.attributes.elementAt(id) == null;
+ }
+
+ private int getFreeAttrID(int id, int low, int high) {
+ if (id >= 20 && id <= 255 && this.attrIDAvailable(id)) {
+ return id;
+ } else {
+ int freeCount = this.countFree(low, high);
+ if (freeCount == 0) {
+ return -1;
+ } else {
+ int i;
+ label42:
+ while (true) {
+ int pos = (int)(Math.random() * freeCount);
+ i = low;
+
+ while (true) {
+ if (this.attributes.elementAt(i) == null) {
+ if (--pos < 0) {
+ assert i <= high;
+
+ if (i != 150 && i != 155 && i != 160) {
+ break label42;
+ }
+ break;
+ }
+ }
+
+ i++;
+ }
+ }
+
+ return i;
+ }
+ }
+ }
+
+ public int getFreeAttrIDFor(Attribute a, int id) {
+ return a instanceof DynamicForwardAttribute ? this.getFreeAttrID(id, 210, 249) : this.getFreeAttrID(id, 100, 249);
+ }
+
+ public void removeAttribute(Attribute a) {
+ a.detach();
+ if (a.getOwner() == null) {
+ this.attributes.setElementAt(null, a._attrID);
+ }
+ }
+
+ public int resetAttributeID(Attribute a, int newID) {
+ newID = this.getFreeAttrIDFor(a, newID);
+ if (newID == -1) {
+ return newID;
+ } else {
+ if (this.attributes.elementAt(newID) == null) {
+ int oldID = a._attrID;
+ this.attributes.setElementAt(a, newID);
+ this.attributes.setElementAt(null, oldID);
+ a._attrID = newID;
+ }
+
+ return newID;
+ }
+ }
+
+ public void moveToSlot(WObject child, int newID) {
+ if (child.isDynamic()) {
+ Sharer s = child.getSharer();
+ if (s.dfa != null) {
+ this.resetAttributeID(s.dfa, newID);
+ }
+ }
+ }
+
+ public Enumeration<Attribute> getAttributes() {
+ return this.getAttributesList().elements();
+ }
+
+ public Vector<Attribute> getAttributesList() {
+ Vector<Attribute> v = new Vector<Attribute>(this.attributes.size());
+ this.fillAttributesList(v);
+ return v;
+ }
+
+ public void fillAttributesList(Vector<Attribute> v) {
+ int end = this.attributes.size();
+
+ for (int i = 0; i < end; i++) {
+ Attribute a = this.attributes.elementAt(i);
+ if (a != null) {
+ v.addElement(a);
+ }
+ }
+ }
+
+ public Attribute getAttribute(int id) {
+ try {
+ return this.attributes.elementAt(id);
+ } catch (ArrayIndexOutOfBoundsException var3) {
+ return null;
+ }
+ }
+
+ public boolean isEmpty() {
+ return this.countFree(0, 255) == 256;
+ }
+
+ public int countFree(int low, int high) {
+ int count = 0;
+
+ for (int i = low; i <= high; i++) {
+ if (this.attributes.elementAt(i) == null) {
+ count++;
+ }
+ }
+
+ return count;
+ }
+
+ @Override
+ public void getChildren(DeepEnumeration d) {
+ d.addChildVectorWithNulls(this.attributes);
+ }
+
+ public void noteChange(Attribute a, boolean sendTriggers) {
+ assert Main.isMainThread();
+
+ if (this.prepQ == null) {
+ this.noteQ = new Vector<Attribute>();
+ this.prepQ = new Vector<Attribute>();
+ this.sendQ = new Vector<Attribute>();
+ }
+
+ if (sendTriggers && !this.noteQ.contains(a)) {
+ if (this.noteQ.isEmpty() && this.prepQ.isEmpty() && this.sendQ.isEmpty()) {
+ Main.register(this);
+ }
+
+ this.noteQ.addElement(a);
+ }
+
+ Attribute fa;
+ if (this.getMode() == 3 && (fa = a.getForwardAttribute()) != null) {
+ fa.noteChange();
+ } else if (this.dfa != null) {
+ this.dfa.noteChange();
+ } else if (!this.prepQ.contains(a)) {
+ if (this.noteQ.isEmpty() && this.prepQ.isEmpty() && this.sendQ.isEmpty()) {
+ Main.register(this);
+ }
+
+ this.prepQ.addElement(a);
+ }
+ }
+
+ private void prepQueue() {
+ if (!this.noteQ.isEmpty()) {
+ int end = this.noteQ.size();
+
+ for (int i = 0; i < end; i++) {
+ Attribute a = this.noteQ.elementAt(i);
+ ValueEvent e = new ValueEvent(Std.getFastTime(), this.getOwner(), (WObject)this.getOwner(), a);
+ a.trigger(e);
+ }
+
+ this.noteQ.removeAllElements();
+ }
+
+ int end = this.prepQ.size();
+
+ for (int i = 0; i < end; i++) {
+ Attribute a = this.prepQ.elementAt(i);
+ this.bs.reset();
+
+ try {
+ a.generateNetData(new DataOutputStream(this.bs));
+ } catch (IOException var5) {
+ System.err.println(var5);
+ throw new Error("Fatal in generateNetData");
+ }
+
+ a._outgoing = this.bs.toByteArray();
+ if (Std.byteArraysEqual(a._outgoing, a._serverData)) {
+ a._outgoing = null;
+ } else if (!this.sendQ.contains(a)) {
+ this.sendQ.addElement(a);
+ }
+ }
+
+ this.prepQ.removeAllElements();
+ }
+
+ @Override
+ public void mainCallback() {
+ if (this.noteQ.isEmpty() && this.prepQ.isEmpty() && this.sendQ.isEmpty()) {
+ Main.unregister(this);
+ } else {
+ int frameTime = Std.getFastTime();
+ if (frameTime > this.lastSendTime + 250) {
+ this.sendQueue();
+ Main.unregister(this);
+ this.lastSendTime = frameTime;
+ }
+ }
+ }
+
+ private void flushQueue() {
+ if (this.prepQ != null) {
+ this.prepQueue();
+ if (!this.sendQ.isEmpty()) {
+ int i = this.sendQ.size();
+
+ while (--i >= 0) {
+ Attribute a = this.sendQ.elementAt(i);
+ a._waitingForFeedback = false;
+ a._serverData = null;
+ a._outgoing = null;
+ }
+
+ this.sendQ.removeAllElements();
+ }
+ }
+ }
+
+ private void sendQueue() {
+ this.prepQueue();
+ WorldServer rs = ((WObject)this.getOwner()).getServer();
+ if (rs != null) {
+ int end = this.sendQ.size();
+
+ for (int i = 0; i < end; i++) {
+ Attribute a = this.sendQ.elementAt(i);
+ if (a._outgoing != null) {
+ this.share(rs, a);
+ a._serverData = a._outgoing;
+ a._outgoing = null;
+ a._waitingForFeedback = true;
+ }
+ }
+ }
+
+ this.sendQ.removeAllElements();
+ }
+
+ private void share(WorldServer ws, Attribute a) {
+ SuperRoot w = this.getOwner();
+ ObjID objID = null;
+ if (w instanceof Room) {
+ Pilot pilot = Pilot.getActive();
+ if (pilot != null && pilot.getLastServedRoom() != w) {
+ objID = new ObjID(((Room)w).getNetworkRoom().getLongID());
+ } else {
+ objID = new ObjID(253);
+ }
+ } else if (w instanceof Pilot) {
+ objID = new ObjID(1);
+ } else {
+ objID = new ObjID(w.getName());
+ }
+
+ try {
+ PropertyList propList = new PropertyList();
+ propList.addProperty(new net2Property(a._attrID, a.getFlags(), a.getAccessFlags(), a._outgoing));
+ ws.sendNetworkMsg(new PropertySetCmd(objID, propList));
+ } catch (InfiniteWaitException var6) {
+ Console.println(Console.message("Net-shutdown") + var6.toString());
+ } catch (PacketTooLargeException var7) {
+ assert false;
+ }
+ }
+
+ public void setFromNetData(int attrID, byte[] data) {
+ if (this.prepQ != null) {
+ this.prepQueue();
+ }
+
+ Attribute a = this.getAttribute(attrID);
+ if (a == null) {
+ if ((this.getMode() & 1) != 0) {
+ Object[] arguments = new Object[]{new String("" + attrID), new String(this.getOwner().getName())};
+ Console.println(MessageFormat.format(Console.message("Unknown-attr"), arguments));
+ return;
+ }
+
+ a = new DynamicForwardAttribute(attrID);
+ this.addAttribute(a);
+ }
+
+ this.setData(a, data);
+ if (!a.loaded) {
+ a.loaded = true;
+ if (a.callbacks != null && a.callbacks.size() > 0) {
+ Enumeration<LoadedAttribute> e = a.callbacks.elements();
+
+ while (e.hasMoreElements()) {
+ LoadedAttribute la = e.nextElement();
+ la.loadedAttribute(a, null);
+ }
+
+ a.callbacks.removeAllElements();
+ }
+ }
+ }
+
+ private void setData(Attribute a, byte[] data) {
+ boolean matchesLastSent = Std.byteArraysEqual(data, a._serverData);
+ if (a._waitingForFeedback) {
+ if (!matchesLastSent) {
+ return;
+ }
+
+ a._waitingForFeedback = false;
+ if (data.length != 0 || a._outgoing != null) {
+ return;
+ }
+ } else if (matchesLastSent) {
+ return;
+ }
+
+ a._serverData = data;
+ if (Std.byteArraysEqual(data, a._outgoing)) {
+ a._outgoing = null;
+ } else if (a._outgoing == null) {
+ try {
+ a.setFromNetData(new DataInputStream(new ByteArrayInputStream(data)), data.length);
+ } catch (IOException var5) {
+ var5.printStackTrace();
+ Console.println(Console.message("Unrec-format") + a.getName());
+ }
+
+ ValueEvent e = new ValueEvent(Std.getFastTime(), this, (WObject)this.getOwner(), a);
+ a.trigger(e);
+ }
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ throw new NoSuchPropertyException();
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(2, classCookie);
+ super.saveState(s);
+ s.saveVector(this.getAttributesList());
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ this.setName(r.restoreString());
+ int nSharedAtts = r.restoreInt();
+ this.restoredAttributes = new Vector<Object>(nSharedAtts);
+
+ for (int i = 0; i < nSharedAtts; i++) {
+ this.restoredAttributes.addElement(r.restoreString());
+ }
+ break;
+ case 1:
+ this.setName(r.restoreString());
+ this.restoredAttributes = r.restoreVector();
+ break;
+ case 2:
+ super.restoreState(r);
+ this.restoredAttributes = r.restoreVector();
+ break;
+ default:
+ throw new TooNewException();
+ }
+ }
+
+ public void ownerPostRestore() {
+ int desiredMode = this.getMaybeDefaultMode();
+ ((WObject)this.getOwner()).setSharerMode(0);
+ this.setMode(desiredMode);
+ Enumeration<Object> e = this.restoredAttributes.elements();
+
+ while (e.hasMoreElements()) {
+ Attribute a = (Attribute)e.nextElement();
+ this.addAttribute(a);
+ }
+
+ this.restoredAttributes = null;
+ }
+
+ public void releaseAuxilaryData() {
+ for (int i = 0; i < 256; i++) {
+ Attribute a = this.attributes.elementAt(i);
+ if (a != null) {
+ a.releaseAuxilaryData();
+ }
+ }
+ }
+}
diff --git a/NET/worlds/scape/SlidePropertyAction.java b/NET/worlds/scape/SlidePropertyAction.java
new file mode 100644
index 0000000..1d16de2
--- /dev/null
+++ b/NET/worlds/scape/SlidePropertyAction.java
@@ -0,0 +1,65 @@
+package NET.worlds.scape;
+
+import NET.worlds.core.Std;
+import java.io.IOException;
+
+public abstract class SlidePropertyAction extends SetPropertyAction {
+ private float _duration = 0.0F;
+ private int _startMilliTime = 0;
+ private static Object classCookie = new Object();
+
+ protected boolean slide() {
+ return this._duration != 0.0F;
+ }
+
+ protected void start() {
+ this._startMilliTime = Std.getFastTime();
+ }
+
+ protected float fraction() {
+ return (Std.getFastTime() - this._startMilliTime) / (1000.0F * this._duration);
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Duration"));
+ } else {
+ if (mode == 1) {
+ return new Float(this._duration);
+ }
+
+ if (mode == 2) {
+ this._duration = (Float)value;
+ }
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 1, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(1, classCookie);
+ super.saveState(s);
+ s.saveFloat(this._duration);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 1:
+ super.restoreState(r);
+ this._duration = r.restoreFloat();
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/SmoothDriver.java b/NET/worlds/scape/SmoothDriver.java
new file mode 100644
index 0000000..ad02a17
--- /dev/null
+++ b/NET/worlds/scape/SmoothDriver.java
@@ -0,0 +1,473 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Window;
+import java.io.IOException;
+import java.util.Enumeration;
+
+public class SmoothDriver
+ extends SwitchableBehavior
+ implements MouseDeltaHandler,
+ KeyUpHandler,
+ KeyDownHandler,
+ FrameHandler,
+ MouseDownHandler,
+ MouseUpHandler,
+ MomentumBehavior {
+ protected float FB_force;
+ protected boolean FB_forceFromMouse;
+ protected float FB_vel;
+ protected float LR_force;
+ protected float LR_vel;
+ protected int lastTime;
+ protected float maxdvFB = 300.0F;
+ protected float FB_damp = -2.5F;
+ protected float minFB_vel = 4.0F;
+ protected float minFB_pixDouble = 40.0F;
+ protected float maxdvLR = 166.0F;
+ protected float LR_damp = -5.0F;
+ protected float minLR_vel = 3.0F;
+ protected float minLR_pixDouble = 40.0F;
+ protected float eyeHeight = 150.0F;
+ private int appliedForceThisFrame = 0;
+ private int forceDouble = 0;
+ protected float FB_key = 1200.0F;
+ protected float LR_key = 500.0F;
+ private static Object classCookie = new Object();
+
+ @Override
+ public boolean handle(MouseDeltaEvent e) {
+ if (UniverseHandler.handle(e)) {
+ return true;
+ } else {
+ if (e.dx != 0 || e.dy != 0) {
+ this.applyFrameForce(e);
+ float dx2 = e.dx * e.dx;
+ float dy2 = e.dy * e.dy;
+ double arrrr = Math.sqrt(dx2 + dy2);
+ if (e.dy < 0) {
+ dy2 = -dy2;
+ }
+
+ this.FB_vel -= (float)(1.1 * dy2 / arrrr);
+ if (e.dx < 0) {
+ dx2 = -dx2;
+ }
+
+ this.LR_vel -= (float)(0.5 * dx2 / arrrr);
+ }
+
+ return true;
+ }
+ }
+
+ public void setVelocityDamping(float pDamp) {
+ this.FB_damp = pDamp;
+ }
+
+ public float getVelocityDamping() {
+ return this.FB_damp;
+ }
+
+ public void setEyeHeight(float newHeight) {
+ this.eyeHeight = newHeight;
+ }
+
+ public float getEyeHeight() {
+ return this.eyeHeight;
+ }
+
+ public void applyFrameForce(Event e) {
+ if (e.receiver instanceof Pilot) {
+ Pilot pilot = (Pilot)e.receiver;
+ if (pilot.isActive()) {
+ this.appliedForceThisFrame++;
+ int now = e.time;
+ float dt = (now - this.lastTime) / 1000.0F;
+ if (!(dt <= 0.0F)) {
+ if (dt > 0.33F) {
+ dt = 0.33F;
+ }
+
+ this.lastTime = now;
+ float dx = this.FB_vel * dt;
+ float dv = 0.0F;
+ if (this.FB_force != 0.0F) {
+ dv += this.FB_force * dt;
+ dv = this.maxdvFB * (float)Math.atan(dv / this.maxdvFB);
+ this.FB_vel += dv;
+ dx += dv * dt;
+ }
+
+ float dz = this.eyeHeight - pilot.getZ();
+ Room room = pilot.getRoom();
+ if (room != null) {
+ dz += room.floorHeight(pilot.getX(), pilot.getY(), pilot.getZ());
+ }
+
+ if (dx != 0.0F || dz != 0.0F) {
+ this.moveLevel(pilot, dx, dz);
+ }
+
+ this.FB_vel = (float)(this.FB_vel * Math.exp(this.FB_damp * dt));
+ if (Math.abs(this.FB_vel) < this.minFB_vel) {
+ this.FB_vel = 0.0F;
+ }
+
+ dv = this.LR_vel * dt;
+ dz = 0.0F;
+ if (this.LR_force != 0.0F) {
+ dz += this.LR_force * dt;
+ dz = this.maxdvLR * (float)Math.atan(dz / this.maxdvLR);
+ this.LR_vel += dz;
+ dv += dz * dt;
+ }
+
+ if (dv != 0.0F) {
+ this.yawLevel(pilot, dv);
+ }
+
+ this.LR_vel = (float)(this.LR_vel * Math.exp(this.LR_damp * dt));
+ if (Math.abs(this.LR_vel) < this.minLR_vel) {
+ this.LR_vel = 0.0F;
+ }
+ }
+ }
+ }
+ }
+
+ private void moveLevel(Pilot pilot, float dx, float dz) {
+ float currentYaw = pilot.getYaw();
+ Point3Temp currentSpinAxis = Point3Temp.make();
+ float currentSpin = pilot.getSpin(currentSpinAxis);
+ Point3Temp currentPosition = pilot.getPosition();
+ pilot.makeIdentity().moveTo(currentPosition).yaw(-currentYaw);
+ pilot.premoveThrough(Point3Temp.make(0.0F, dx, dz));
+ pilot.yaw(currentYaw);
+ pilot.spin(currentSpinAxis, currentSpin);
+ }
+
+ private void yawLevel(Pilot pilot, float dTheta) {
+ float currentYaw = pilot.getYaw();
+ Point3Temp currentSpinAxis = Point3Temp.make();
+ float currentSpin = pilot.getSpin(currentSpinAxis);
+ Point3Temp currentPosition = pilot.getPosition();
+ pilot.makeIdentity().moveTo(currentPosition).yaw(-currentYaw);
+ pilot.yaw(dTheta);
+ pilot.yaw(currentYaw);
+ pilot.spin(currentSpinAxis, currentSpin);
+ }
+
+ @Override
+ public boolean handle(FrameEvent e) {
+ if (this.FB_forceFromMouse && !this.isDelta(e)) {
+ this.applyFrameForce(e);
+ this.FB_force = 0.0F;
+ this.FB_forceFromMouse = false;
+ }
+
+ if (this.appliedForceThisFrame == 0) {
+ this.applyFrameForce(e);
+ }
+
+ this.appliedForceThisFrame = 0;
+ return true;
+ }
+
+ @Override
+ public boolean handle(KeyDownEvent e) {
+ if (UniverseHandler.handle(e)) {
+ return true;
+ } else {
+ float FB;
+ if (e.key == '\ue326') {
+ FB = this.FB_key;
+ } else {
+ if (e.key != '\ue328') {
+ float LR;
+ if (e.key == '\ue325') {
+ LR = this.LR_key;
+ } else {
+ if (e.key != '\ue327') {
+ return true;
+ }
+
+ LR = -this.LR_key;
+ }
+
+ this.applyFrameForce(e);
+ this.LR_force = LR;
+ return true;
+ }
+
+ FB = -this.FB_key;
+ }
+
+ this.applyFrameForce(e);
+ this.FB_force = FB;
+ return true;
+ }
+ }
+
+ @Override
+ public boolean handle(KeyUpEvent e) {
+ if (UniverseHandler.handle(e)) {
+ return true;
+ } else {
+ if (e.key == '\ue326' || e.key == '\ue328') {
+ this.applyFrameForce(e);
+ this.FB_force = 0.0F;
+ } else if (e.key == '\ue325' || e.key == '\ue327') {
+ this.applyFrameForce(e);
+ this.LR_force = 0.0F;
+ }
+
+ return true;
+ }
+ }
+
+ private boolean isDelta(Event e) {
+ if (e.receiver instanceof Pilot && ((Pilot)e.receiver).isActive()) {
+ Window w = Window.getMainWindow();
+ return w != null && w.getDeltaMode();
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public boolean handle(MouseDownEvent e) {
+ if (e.key == '\ue302' && this.isDelta(e)) {
+ this.applyFrameForce(e);
+ this.FB_force = this.FB_key;
+ this.FB_forceFromMouse = true;
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean handle(MouseUpEvent e) {
+ if (e.key == '\ue302' && this.isDelta(e)) {
+ this.applyFrameForce(e);
+ this.FB_force = 0.0F;
+ this.FB_forceFromMouse = false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Eye Height"));
+ } else if (mode == 1) {
+ ret = new Float(this.getEyeHeight());
+ } else if (mode == 2) {
+ this.setEyeHeight((Float)value);
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Fore/aft max acceleration"));
+ } else if (mode == 1) {
+ ret = new Float(this.maxdvFB);
+ } else if (mode == 2) {
+ this.maxdvFB = (Float)value;
+ }
+ break;
+ case 2:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Fore/aft velocity damping"));
+ } else if (mode == 1) {
+ ret = new Float(this.FB_damp);
+ } else if (mode == 2) {
+ this.FB_damp = (Float)value;
+ }
+ break;
+ case 3:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Fore/aft min velocity"));
+ } else if (mode == 1) {
+ ret = new Float(this.minFB_vel);
+ } else if (mode == 2) {
+ this.minFB_vel = (Float)value;
+ }
+ break;
+ case 4:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Fore/aft velocity threshold for pixel doubling"));
+ } else if (mode == 1) {
+ ret = new Float(this.minFB_pixDouble);
+ } else if (mode == 2) {
+ this.minFB_pixDouble = (Float)value;
+ }
+ break;
+ case 5:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Yaw max acceleration"));
+ } else if (mode == 1) {
+ ret = new Float(this.maxdvLR);
+ } else if (mode == 2) {
+ this.maxdvLR = (Float)value;
+ }
+ break;
+ case 6:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Yaw rate damping"));
+ } else if (mode == 1) {
+ ret = new Float(this.LR_damp);
+ } else if (mode == 2) {
+ this.LR_damp = (Float)value;
+ }
+ break;
+ case 7:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Yaw min rate"));
+ } else if (mode == 1) {
+ ret = new Float(this.minLR_vel);
+ } else if (mode == 2) {
+ this.minLR_vel = (Float)value;
+ }
+ break;
+ case 8:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Yaw rate threshold for pixel doubling"));
+ } else if (mode == 1) {
+ ret = new Float(this.minLR_pixDouble);
+ } else if (mode == 2) {
+ this.minLR_pixDouble = (Float)value;
+ }
+ break;
+ case 9:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Fore/aft velocity increment for up/down arrow keys"));
+ } else if (mode == 1) {
+ ret = new Float(this.FB_key);
+ } else if (mode == 2) {
+ this.FB_key = (Float)value;
+ }
+ break;
+ case 10:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Yaw rate increment for up/down arrow keys"));
+ } else if (mode == 1) {
+ ret = new Float(this.LR_key);
+ } else if (mode == 2) {
+ this.LR_key = (Float)value;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 11, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(3, classCookie);
+ super.saveState(s);
+ s.saveFloat(this.FB_vel);
+ s.saveFloat(this.LR_vel);
+ s.saveFloat(this.maxdvFB);
+ s.saveFloat(this.FB_damp);
+ s.saveFloat(this.minFB_vel);
+ s.saveFloat(this.maxdvLR);
+ s.saveFloat(this.LR_damp);
+ s.saveFloat(this.minLR_vel);
+ s.saveFloat(this.eyeHeight);
+ s.saveFloat(this.FB_key);
+ s.saveFloat(this.LR_key);
+ s.saveInt(this.forceDouble);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ r.setOldFlag();
+ super.restoreState(r);
+ r.restoreFloat();
+ this.FB_vel = r.restoreFloat();
+ r.restoreFloat();
+ this.LR_vel = r.restoreFloat();
+ break;
+ case 1:
+ r.setOldFlag();
+ super.restoreState(r);
+ r.restoreFloat();
+ this.FB_vel = r.restoreFloat();
+ r.restoreFloat();
+ this.LR_vel = r.restoreFloat();
+ this.maxdvFB = r.restoreFloat();
+ this.FB_damp = r.restoreFloat();
+ this.minFB_vel = r.restoreFloat();
+ this.maxdvLR = r.restoreFloat();
+ this.LR_damp = r.restoreFloat();
+ this.minLR_vel = r.restoreFloat();
+ this.eyeHeight = r.restoreFloat();
+ this.FB_key = r.restoreFloat();
+ this.LR_key = r.restoreFloat();
+ break;
+ case 2:
+ r.setOldFlag();
+ super.restoreState(r);
+ r.restoreFloat();
+ this.FB_vel = r.restoreFloat();
+ r.restoreFloat();
+ this.LR_vel = r.restoreFloat();
+ this.maxdvFB = r.restoreFloat();
+ this.FB_damp = r.restoreFloat();
+ this.minFB_vel = r.restoreFloat();
+ this.maxdvLR = r.restoreFloat();
+ this.LR_damp = r.restoreFloat();
+ this.minLR_vel = r.restoreFloat();
+ this.eyeHeight = r.restoreFloat();
+ this.FB_key = r.restoreFloat();
+ this.LR_key = r.restoreFloat();
+ this.forceDouble = r.restoreInt();
+ break;
+ case 3:
+ super.restoreState(r);
+ this.FB_vel = r.restoreFloat();
+ this.LR_vel = r.restoreFloat();
+ this.maxdvFB = r.restoreFloat();
+ this.FB_damp = r.restoreFloat();
+ this.minFB_vel = r.restoreFloat();
+ this.maxdvLR = r.restoreFloat();
+ this.LR_damp = r.restoreFloat();
+ this.minLR_vel = r.restoreFloat();
+ this.eyeHeight = r.restoreFloat();
+ this.FB_key = r.restoreFloat();
+ this.LR_key = r.restoreFloat();
+ this.forceDouble = r.restoreInt();
+ break;
+ default:
+ throw new TooNewException();
+ }
+ }
+
+ @Override
+ public void transferFrom(Enumeration oldMBs) {
+ this.FB_force = 0.0F;
+ this.LR_force = 0.0F;
+
+ while (oldMBs.hasMoreElements()) {
+ SuperRoot sr = (SuperRoot)oldMBs.nextElement();
+ if (sr instanceof SmoothDriver) {
+ SmoothDriver sd = (SmoothDriver)sr;
+ this.FB_vel = sd.FB_vel;
+ this.LR_vel = sd.LR_vel;
+ this.lastTime = sd.lastTime;
+ return;
+ }
+ }
+
+ this.FB_vel = 0.0F;
+ this.LR_vel = 0.0F;
+ this.lastTime = 0;
+ }
+}
diff --git a/NET/worlds/scape/Sound.java b/NET/worlds/scape/Sound.java
new file mode 100644
index 0000000..aa9d5a3
--- /dev/null
+++ b/NET/worlds/scape/Sound.java
@@ -0,0 +1,623 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Main;
+import NET.worlds.console.MainCallback;
+import NET.worlds.core.IniFile;
+import NET.worlds.network.CacheFile;
+import NET.worlds.network.URL;
+import java.io.IOException;
+import java.util.Vector;
+
+public class Sound extends Action implements BGLoaded, StateContext {
+ static int debugLevel = IniFile.gamma().getIniInt("sounddebug", 0);
+ private String cachedName;
+ private URL soundURL;
+ protected CacheFile cachedFile = null;
+ protected float soundVolume = 1.0F;
+ protected float stopDistance = 1000.0F;
+ private int repeat = 1;
+ private boolean continuous = false;
+ private boolean attenuateOn = true;
+ private boolean panningOn = true;
+ protected SuperRoot activeSeq;
+ SoundPlayer player;
+ AudibilityFilter aFilter = null;
+ private int maxHopcount = 1;
+ private boolean doorMovementFlag = false;
+ private static boolean soundOn = true;
+ boolean playAfterLoading = true;
+ protected int state = 0;
+ protected static final int SYNC = 1;
+ protected static final int ASYNC = 2;
+ protected int backgroundState = 1;
+ private static SoundCallback closer;
+ static Vector cachedEntries;
+ private static Vector pendingEntries;
+ private boolean mainRan;
+ private boolean opened;
+ private static Object classCookie = new Object();
+
+ static {
+ debugOut(1, "SOUND DEBUGGING LEVEL = " + debugLevel);
+ }
+
+ private static void debugOut(int n, String s) {
+ if (debugLevel > n) {
+ System.out.println(s);
+ }
+ }
+
+ public Sound(URL soundURL) {
+ Transform.countClass(this, 1);
+ debugOut(9, "Sound " + soundURL);
+ this.setURL(soundURL);
+ }
+
+ public Sound() {
+ Transform.countClass(this, 1);
+ debugOut(9, "Sound ");
+ this.setURL(null);
+ }
+
+ public final void setURL(URL url) {
+ if (this.activeSeq != null) {
+ this.closePlayer();
+ }
+
+ this.soundURL = url;
+ }
+
+ public final URL getURL() {
+ return this.soundURL;
+ }
+
+ public final void setSoundVolume(float vol) {
+ this.soundVolume = vol;
+ }
+
+ public final float getSoundVolume() {
+ return this.soundVolume;
+ }
+
+ public final void setStopDistance(float i) {
+ this.stopDistance = i;
+ }
+
+ public final float getStopDistance() {
+ return this.stopDistance;
+ }
+
+ public final void setRepeat(int i) {
+ this.repeat = i;
+ }
+
+ public final int getRepeat() {
+ return this.repeat;
+ }
+
+ public final void setContinuous(boolean c) {
+ this.continuous = c;
+ }
+
+ public final boolean isContinuous() {
+ return this.continuous;
+ }
+
+ public final void setAttenuate(boolean b) {
+ this.attenuateOn = b;
+ }
+
+ public final boolean getAttenuate() {
+ return this.attenuateOn;
+ }
+
+ public final void setPanning(boolean b) {
+ this.panningOn = b;
+ }
+
+ public final boolean getPanning() {
+ return this.panningOn;
+ }
+
+ public final int getState() {
+ return this.player.getState();
+ }
+
+ public final int getHopcount() {
+ return this.maxHopcount;
+ }
+
+ public final void setHopcount(int i) {
+ this.maxHopcount = i;
+ if (this.aFilter != null) {
+ this.aFilter.setHopcount(this.maxHopcount);
+ }
+ }
+
+ public boolean getDoorMovementFlag() {
+ return this.doorMovementFlag;
+ }
+
+ public void setDoorMovementFlag(boolean b) {
+ this.doorMovementFlag = b;
+ if (this.aFilter != null) {
+ this.startAudibilityFilter();
+ }
+ }
+
+ private void startAudibilityFilter() {
+ debugOut(9, "startAudibilityFilter " + this.getURL());
+ WObject owner = (WObject)this.getOwner();
+ if (owner != null) {
+ if (this.doorMovementFlag) {
+ this.aFilter = new DoorBasedFilter(this, owner, this.maxHopcount, this.stopDistance);
+ } else {
+ this.aFilter = new AudibilityFilter(this, owner, this.maxHopcount);
+ }
+
+ this.aFilter.moveEmitter();
+ }
+ }
+
+ public static void turnSoundOn() {
+ soundOn = true;
+ }
+
+ public static void turnSoundOff() {
+ soundOn = false;
+ }
+
+ public void setPlayAfterLoading(boolean b) {
+ this.playAfterLoading = b;
+ }
+
+ protected boolean isRealAudio(URL s) {
+ return s.endsWith(".ram") || s.endsWith(".ra") || s.endsWith(".rm");
+ }
+
+ @Override
+ public void changeState(int s) {
+ debugOut(9, "changeState to " + s);
+ this.state = s;
+ }
+
+ protected Object doState(Object obj) {
+ return SoundState.instance().doState(this, obj);
+ }
+
+ private boolean isBackgroundProcessing() {
+ if (this.state != 0) {
+ debugOut(9, "backgroundProcessing " + this.state);
+ }
+
+ return this.state != 0;
+ }
+
+ private void startSound() {
+ this.backgroundState = 1;
+ if (this.aFilter == null) {
+ this.startAudibilityFilter();
+ }
+
+ if (this.aFilter != null) {
+ this.aFilter.setEmitterOn(true);
+ }
+
+ if (this.state == 0) {
+ this.state = 1;
+ }
+
+ this.doState(this.soundURL);
+ }
+
+ @Override
+ public Object asyncBackgroundLoad(String localName, URL remoteName) {
+ this.backgroundState = 2;
+ return this.doState(URL.make(localName));
+ }
+
+ @Override
+ public boolean syncBackgroundLoad(Object obj, URL remoteURL) {
+ this.backgroundState = 1;
+ this.doState(obj);
+ return false;
+ }
+
+ @Override
+ public Room getBackgroundLoadRoom() {
+ WObject owner = (WObject)this.getOwner();
+ return owner == null ? null : owner.getRoom();
+ }
+
+ protected void ensureClosure() {
+ if (closer == null) {
+ closer = new SoundCallback();
+ Main.register(closer);
+ }
+
+ if (cachedEntries == null) {
+ cachedEntries = new Vector();
+ }
+
+ cachedEntries.addElement(this.cachedFile);
+ }
+
+ protected void unlockCache() {
+ if (this.cachedFile != null) {
+ debugOut(6, "unlocking " + this.soundURL);
+ this.cachedFile.finalize();
+
+ assert cachedEntries != null;
+
+ assert cachedEntries.indexOf(this.cachedFile, 0) >= 0;
+
+ cachedEntries.removeElement(this.cachedFile);
+ this.cachedFile = null;
+ }
+ }
+
+ synchronized boolean openPlayer(URL url) {
+ assert this.player == null;
+
+ this.cachedName = url.unalias();
+ debugOut(4, "openPlayer on:: " + this.cachedName);
+ if (url.endsWith(".wav")) {
+ this.player = new WavSoundPlayer(this);
+ } else if (url.endsWith(".mid")) {
+ this.player = new MCISoundPlayer(this);
+ } else {
+ this.player = new WMPSoundPlayer(this);
+ }
+
+ if (Main.isMainThread()) {
+ this.openInMainThread();
+ } else {
+ this.mainRan = false;
+ Main.register(new MainCallback() {
+ @Override
+ public void mainCallback() {
+ Sound.this.openInMainThread();
+ Main.unregister(this);
+ }
+ });
+
+ while (!this.mainRan) {
+ try {
+ this.wait();
+ } catch (InterruptedException var3) {
+ }
+ }
+ }
+
+ return this.opened;
+ }
+
+ public synchronized void openInMainThread() {
+ this.opened = this.player.open(this.soundVolume, this.stopDistance, this.attenuateOn, this.panningOn);
+ if (!this.opened) {
+ this.closePlayer();
+ }
+
+ this.mainRan = true;
+ this.notify();
+ }
+
+ void closePlayer() {
+ if (this.player != null) {
+ this.player.stop();
+ this.unlockCache();
+ if (SoundResource.instance().syncUnlock()) {
+ this.player.close();
+ }
+
+ this.player = null;
+ }
+
+ debugOut(2, " closePlayer");
+ }
+
+ @Override
+ public Persister trigger(Event e, Persister seqID) {
+ debugOut(9, "trigger in: seqID " + seqID + " activeSeq " + this.activeSeq);
+ if (this.isBackgroundProcessing()) {
+ return this.activeSeq;
+ } else {
+ if (seqID == null) {
+ if (this.soundURL == null || this.getOwner() == null) {
+ return null;
+ }
+
+ if (this.activeSeq != null) {
+ this.closePlayer();
+ }
+
+ this.activeSeq = this;
+ Persister var3 = this.activeSeq;
+ debugOut(6, "triggering new sound " + var3);
+ this.startSound();
+ } else if (seqID != this.activeSeq) {
+ this.unlockCache();
+ if (!this.isContinuous()) {
+ this.aFilter.setEmitterOn(false);
+ }
+
+ return null;
+ }
+
+ if (this.player != null && this.player.getState() != 0 && !this.isContinuous()) {
+ this.aFilter.setEmitterOn(false);
+ }
+
+ if ((this.isBackgroundProcessing() || this.updateSound() && this.player.getState() == 0) && this.getOwner() != null) {
+ return this.activeSeq;
+ } else {
+ this.activeSeq = null;
+ this.closePlayer();
+ return null;
+ }
+ }
+ }
+
+ boolean updateSound() {
+ debugOut(9, "Sound::updateSound:: in");
+ if (this.player == null) {
+ debugOut(6, "update returning false because player is null");
+ return false;
+ } else if (!SoundResource.instance().isOK()) {
+ debugOut(2, "update registering not OK");
+ return false;
+ } else if (!this.aFilter.isAudible()) {
+ debugOut(4, "update stopping sound because isAudible false");
+ return false;
+ } else {
+ Point3Temp pilot = Point3Temp.make();
+ Point3Temp up = Point3Temp.make();
+ Point3Temp forward = Point3Temp.make();
+ Point3Temp obj = Point3Temp.make();
+ this.aFilter.getListenerPosition(pilot, up, forward);
+ this.aFilter.getEmitterPosition(obj);
+ if (!this.player.position(pilot, obj, forward, up)) {
+ debugOut(6, "update returning false because position false");
+ return false;
+ } else {
+ float vol = -1.0F;
+ if (soundOn) {
+ vol = this.aFilter.getEmitterVolume();
+ }
+
+ if (!this.player.setVolume(vol * this.soundVolume)) {
+ debugOut(6, "update returning false because volume false");
+ return false;
+ } else {
+ return true;
+ }
+ }
+ }
+ }
+
+ @Override
+ public void postRestore(int version) {
+ super.postRestore(version);
+ this.startAudibilityFilter();
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = URLPropertyEditor.make(new Property(this, index, "Sound File URL").allowSetNull(), "asf;wav;mid;ram;ra;rm;mp3");
+ } else if (mode == 1) {
+ ret = this.soundURL;
+ } else if (mode == 2) {
+ this.soundURL = (URL)value;
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Max Volume"));
+ } else if (mode == 1) {
+ ret = new Float(this.soundVolume);
+ } else if (mode == 2) {
+ this.soundVolume = (Float)value;
+ }
+ break;
+ case 2:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Stop Distance"));
+ } else if (mode == 1) {
+ ret = new Float(this.stopDistance);
+ } else if (mode == 2) {
+ this.stopDistance = (Float)value;
+ }
+ break;
+ case 3:
+ if (mode == 0) {
+ ret = IntegerPropertyEditor.make(new Property(this, index, "Times to Repeat"));
+ } else if (mode == 1) {
+ ret = new Integer(this.repeat);
+ } else if (mode == 2) {
+ this.repeat = (Integer)value;
+ }
+ break;
+ case 4:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Attenuate With Distance"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(this.attenuateOn);
+ } else if (mode == 2) {
+ this.attenuateOn = (Boolean)value;
+ }
+ break;
+ case 5:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Do panning"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(this.panningOn);
+ } else if (mode == 2) {
+ this.panningOn = (Boolean)value;
+ }
+ break;
+ case 6:
+ if (mode == 0) {
+ ret = IntegerPropertyEditor.make(new Property(this, index, "Room hops till sound dies"));
+ } else if (mode == 1) {
+ ret = new Integer(this.maxHopcount);
+ } else if (mode == 2) {
+ this.setHopcount((Integer)value);
+ }
+ break;
+ case 7:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Door based audibility"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(this.getDoorMovementFlag());
+ } else if (mode == 2) {
+ this.setDoorMovementFlag((Boolean)value);
+ }
+ break;
+ case 8:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Play after loading"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(this.playAfterLoading);
+ } else if (mode == 2) {
+ this.setPlayAfterLoading((Boolean)value);
+ }
+ break;
+ case 9:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Loop Infinite"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(this.continuous);
+ } else if (mode == 2) {
+ this.setContinuous((Boolean)value);
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 10, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(7, classCookie);
+ s.saveBoolean(this.playAfterLoading);
+ s.saveBoolean(this.doorMovementFlag);
+ s.saveBoolean(this.panningOn);
+ s.saveBoolean(this.attenuateOn);
+ s.saveInt(this.maxHopcount);
+ super.saveState(s);
+ URL.save(s, this.soundURL);
+ s.saveFloat(this.soundVolume);
+ s.saveFloat(this.stopDistance);
+ s.saveInt(this.repeat);
+ s.saveBoolean(this.continuous);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ int vers = r.restoreVersion(classCookie);
+ switch (vers) {
+ case 0:
+ this.setURL(URL.restore(r));
+ break;
+ case 1:
+ this.setURL(URL.restore(r));
+ this.soundVolume = r.restoreFloat();
+ this.stopDistance = r.restoreFloat();
+ this.repeat = r.restoreInt();
+ if (this.repeat < 0) {
+ this.setContinuous(true);
+ }
+ break;
+ case 2:
+ super.restoreState(r);
+ this.setURL(URL.restore(r));
+ this.soundVolume = r.restoreFloat();
+ this.stopDistance = r.restoreFloat();
+ this.repeat = r.restoreInt();
+ if (this.repeat < 0) {
+ this.setContinuous(true);
+ }
+ break;
+ case 3:
+ this.setHopcount(r.restoreInt());
+ super.restoreState(r);
+ this.setURL(URL.restore(r));
+ this.soundVolume = r.restoreFloat();
+ this.stopDistance = r.restoreFloat();
+ this.repeat = r.restoreInt();
+ if (this.repeat < 0) {
+ this.setContinuous(true);
+ }
+ break;
+ case 4:
+ this.setDoorMovementFlag(r.restoreBoolean());
+ this.setPanning(r.restoreBoolean());
+ this.setAttenuate(r.restoreBoolean());
+ this.setHopcount(r.restoreInt());
+ super.restoreState(r);
+ this.setURL(URL.restore(r));
+ this.soundVolume = r.restoreFloat();
+ this.stopDistance = r.restoreFloat();
+ this.repeat = r.restoreInt();
+ if (this.repeat < 0) {
+ this.setContinuous(true);
+ }
+ break;
+ case 5:
+ this.setPlayAfterLoading(r.restoreBoolean());
+ this.setDoorMovementFlag(r.restoreBoolean());
+ this.setPanning(r.restoreBoolean());
+ this.setAttenuate(r.restoreBoolean());
+ this.setHopcount(r.restoreInt());
+ super.restoreState(r);
+ this.setURL(URL.restore(r));
+ this.soundVolume = r.restoreFloat();
+ this.stopDistance = r.restoreFloat();
+ this.repeat = r.restoreInt();
+ if (this.repeat < 0) {
+ this.setContinuous(true);
+ }
+ break;
+ case 6:
+ this.setPlayAfterLoading(r.restoreBoolean());
+ this.setDoorMovementFlag(r.restoreBoolean());
+ this.setPanning(r.restoreBoolean());
+ this.setAttenuate(r.restoreBoolean());
+ this.setHopcount(r.restoreInt());
+ super.restoreState(r);
+ this.setURL(URL.restore(r));
+ this.soundVolume = r.restoreFloat();
+ this.stopDistance = r.restoreFloat();
+ this.repeat = r.restoreInt();
+ if (this.repeat < 0) {
+ this.setContinuous(true);
+ }
+ break;
+ case 7:
+ this.setPlayAfterLoading(r.restoreBoolean());
+ this.setDoorMovementFlag(r.restoreBoolean());
+ this.setPanning(r.restoreBoolean());
+ this.setAttenuate(r.restoreBoolean());
+ this.setHopcount(r.restoreInt());
+ super.restoreState(r);
+ this.setURL(URL.restore(r));
+ this.soundVolume = r.restoreFloat();
+ this.stopDistance = r.restoreFloat();
+ this.repeat = r.restoreInt();
+ this.setContinuous(r.restoreBoolean());
+ break;
+ default:
+ throw new TooNewException();
+ }
+
+ if (vers < 6 && this.continuous) {
+ this.setContinuous(false);
+ }
+ }
+}
diff --git a/NET/worlds/scape/SoundCallback.java b/NET/worlds/scape/SoundCallback.java
new file mode 100644
index 0000000..2a5123f
--- /dev/null
+++ b/NET/worlds/scape/SoundCallback.java
@@ -0,0 +1,28 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Main;
+import NET.worlds.console.MainCallback;
+import NET.worlds.console.MainTerminalCallback;
+import NET.worlds.core.IniFile;
+import NET.worlds.network.CacheFile;
+
+class SoundCallback implements MainCallback, MainTerminalCallback {
+ @Override
+ public void mainCallback() {
+ }
+
+ @Override
+ public void terminalCallback() {
+ while (!Sound.cachedEntries.isEmpty()) {
+ CacheFile file = (CacheFile)Sound.cachedEntries.firstElement();
+ if (IniFile.gamma().getIniInt("sounddebug", 0) > 6) {
+ System.out.println("terminal unlocking " + file.getLocalName());
+ }
+
+ Sound.cachedEntries.removeElementAt(0);
+ file.finalize();
+ }
+
+ Main.unregister(this);
+ }
+}
diff --git a/NET/worlds/scape/SoundPlayer.java b/NET/worlds/scape/SoundPlayer.java
new file mode 100644
index 0000000..8cb9a58
--- /dev/null
+++ b/NET/worlds/scape/SoundPlayer.java
@@ -0,0 +1,31 @@
+package NET.worlds.scape;
+
+public abstract class SoundPlayer {
+ Sound owner;
+ public static final int IS_PLAYING = 0;
+ public static final int IS_STOPPED = 1;
+ public static final int IS_TERMINATED = 2;
+ public static final int IS_ERROR = 3;
+
+ SoundPlayer(Sound owner) {
+ this.owner = owner;
+ }
+
+ public Sound getOwner() {
+ return this.owner;
+ }
+
+ public abstract boolean open(float var1, float var2, boolean var3, boolean var4);
+
+ public abstract void start(int var1);
+
+ public abstract boolean position(Point3Temp var1, Point3Temp var2, Point3Temp var3, Point3Temp var4);
+
+ public abstract int getState();
+
+ public abstract void stop();
+
+ public abstract void close();
+
+ public abstract boolean setVolume(float var1);
+}
diff --git a/NET/worlds/scape/SoundResource.java b/NET/worlds/scape/SoundResource.java
new file mode 100644
index 0000000..19975f2
--- /dev/null
+++ b/NET/worlds/scape/SoundResource.java
@@ -0,0 +1,89 @@
+package NET.worlds.scape;
+
+class SoundResource {
+ private static SoundResource instance = null;
+ public static final int RSX = 1;
+ public static final int RA = 2;
+ private int currentPlayer = 0;
+ private int counter = 0;
+ private boolean isShutdownTime = false;
+
+ private SoundResource() {
+ }
+
+ private static void debugOut(int n, String s) {
+ if (Sound.debugLevel > n) {
+ System.out.println(s);
+ }
+ }
+
+ public static SoundResource instance() {
+ if (instance == null) {
+ debugOut(6, "Instantiating a new SoundResource");
+ instance = new SoundResource();
+ }
+
+ return instance;
+ }
+
+ public boolean syncLock(int type) {
+ debugOut(6, "Calling syncLock with type " + type + " counter " + this.counter);
+ if (this.isShutdownTime) {
+ return false;
+ } else {
+ if (type != this.currentPlayer) {
+ this.currentPlayer = type;
+ if (this.counter > 0) {
+ this.isShutdownTime = true;
+ } else {
+ this.currentPlayer = type;
+ this.counter = 1;
+ }
+ } else {
+ this.counter++;
+ }
+
+ return true;
+ }
+ }
+
+ public synchronized void asyncLock() {
+ debugOut(6, "SoundResource::asyncLock with " + this.isShutdownTime);
+ boolean shutdown = false;
+
+ while (this.isShutdownTime) {
+ shutdown = true;
+ Thread.yield();
+ debugOut(6, "asyncLock yield");
+ }
+
+ if (shutdown) {
+ debugOut(6, "asyncLock: adding artificial delay");
+
+ try {
+ Thread.sleep(500L);
+ } catch (InterruptedException var3) {
+ }
+ }
+ }
+
+ public boolean syncUnlock() {
+ debugOut(6, "SoundResource::syncUnlock with " + this.counter);
+ boolean rv = false;
+ this.counter--;
+ if (this.counter <= 0) {
+ rv = true;
+ }
+
+ if (this.counter <= 0 && this.isShutdownTime) {
+ this.counter = 1;
+ this.isShutdownTime = false;
+ }
+
+ return rv;
+ }
+
+ public boolean isOK() {
+ return !this.isShutdownTime;
+ }
+}
diff --git a/NET/worlds/scape/SoundState.java b/NET/worlds/scape/SoundState.java
new file mode 100644
index 0000000..eef9d07
--- /dev/null
+++ b/NET/worlds/scape/SoundState.java
@@ -0,0 +1,307 @@
+package NET.worlds.scape;
+
+import NET.worlds.network.Cache;
+import NET.worlds.network.URL;
+
+class SoundState implements State {
+ public static final int IDLE = 0;
+ public static final int start = 1;
+ public static final int intel0 = 1000;
+ public static final int intel10 = 1010;
+ public static final int intel11 = 1011;
+ public static final int intel20 = 1020;
+ public static final int intel21 = 1021;
+ public static final int intel30 = 1030;
+ public static final int intel31 = 1031;
+ public static final int intel32 = 1032;
+ public static final int intel33 = 1033;
+ public static final int realAudio0 = 2000;
+ public static final int realAudio10 = 2010;
+ public static final int realAudio11 = 2011;
+ private static SoundState instance = new SoundState();
+ private static URL dummy = URL.make("home:dummy.wav");
+
+ private SoundState() {
+ }
+
+ private void debugOut(int n, String s) {
+ if (Sound.debugLevel > n) {
+ System.out.println(s);
+ }
+ }
+
+ public static State instance() {
+ return instance;
+ }
+
+ @Override
+ public Object doState(StateContext sc, Object obj) {
+ Sound sound = (Sound)sc;
+ Object rv;
+ switch (sound.state) {
+ case 1:
+ rv = this.start(sound, obj);
+ break;
+ case 1000:
+ rv = this.intel0(sound, obj);
+ break;
+ case 1010:
+ rv = this.intel10(sound, obj);
+ break;
+ case 1011:
+ rv = this.intel11(sound, obj);
+ break;
+ case 1020:
+ rv = this.intel20(sound, obj);
+ break;
+ case 1021:
+ rv = this.intel21(sound, obj);
+ break;
+ case 1030:
+ rv = this.intel30(sound, obj);
+ break;
+ case 1031:
+ rv = this.intel31(sound, obj);
+ break;
+ case 1032:
+ rv = this.intel32(sound, obj);
+ break;
+ case 1033:
+ rv = this.intel33(sound, obj);
+ break;
+ case 2000:
+ rv = this.realAudio0(sound, obj);
+ break;
+ case 2010:
+ rv = this.realAudio10(sound, obj);
+ break;
+ case 2011:
+ rv = this.realAudio11(sound, obj);
+ break;
+ default:
+ rv = this.error(sound, obj);
+ }
+
+ return rv;
+ }
+
+ private Object error(Sound sound, Object obj) {
+ this.debugOut(2, "Unknown state in SoundState " + sound.state);
+ return null;
+ }
+
+ private Object start(Sound sound, Object obj) {
+ this.debugOut(6, "Entering SoundState ");
+
+ assert sound.backgroundState == 1;
+
+ if (sound.isRealAudio(sound.getURL())) {
+ sound.changeState(2000);
+ } else {
+ sound.changeState(1000);
+ }
+
+ sound.doState(null);
+ return null;
+ }
+
+ private Object intel0(Sound sound, Object obj) {
+ this.debugOut(6, "Entering intel0 ");
+
+ assert sound.backgroundState == 1;
+
+ if (!SoundResource.instance().syncLock(1)) {
+ return null;
+ } else if (!sound.getURL().isRemote()) {
+ sound.changeState(1010);
+ BackgroundLoader.get(sound, sound.getURL());
+ return null;
+ } else {
+ sound.cachedFile = Cache.getFile(sound.getURL());
+ if (sound.cachedFile.done()) {
+ sound.ensureClosure();
+ sound.changeState(1020);
+ BackgroundLoader.get(sound, sound.getURL());
+ return null;
+ } else {
+ sound.cachedFile.finalize();
+ sound.cachedFile = null;
+ sound.changeState(1030);
+ BackgroundLoader.get(sound, dummy);
+ return null;
+ }
+ }
+ }
+
+ private Object intel10(Sound sound, Object localName) {
+ assert sound.backgroundState == 2;
+
+ assert localName != null;
+
+ SoundResource.instance().asyncLock();
+ sound.changeState(1011);
+ if (sound.openPlayer((URL)localName)) {
+ return localName;
+ } else {
+ this.debugOut(2, "intel10: couldn't open sound " + sound.getURL());
+ return null;
+ }
+ }
+
+ private Object intel11(Sound sound, Object obj) {
+ this.debugOut(6, "Entering intel11 ");
+
+ assert sound.backgroundState == 1;
+
+ if (obj != null) {
+ if (sound.updateSound()) {
+ sound.player.start(sound.getRepeat());
+ } else {
+ sound.closePlayer();
+ }
+ }
+
+ sound.changeState(0);
+ return null;
+ }
+
+ private Object intel20(Sound sound, Object obj) {
+ this.debugOut(6, "Entering intel20 ");
+
+ assert sound.backgroundState == 2;
+
+ SoundResource.instance().asyncLock();
+ if (sound.openPlayer((URL)obj)) {
+ sound.changeState(1021);
+ return obj;
+ } else {
+ this.debugOut(2, "intel20: couldn't open player on sound " + sound.getURL());
+ sound.changeState(1021);
+ return null;
+ }
+ }
+
+ private Object intel21(Sound sound, Object obj) {
+ this.debugOut(6, "Entering intel21 ");
+
+ assert sound.backgroundState == 1;
+
+ if (obj == null) {
+ sound.unlockCache();
+ } else if (sound.updateSound()) {
+ this.debugOut(6, "intel21 starting sound");
+ sound.player.start(sound.getRepeat());
+ } else {
+ this.debugOut(6, "intel21 closing player");
+ sound.closePlayer();
+ }
+
+ sound.changeState(0);
+ return null;
+ }
+
+ private Object intel30(Sound sound, Object obj) {
+ this.debugOut(6, "Entering intel30 ");
+
+ assert sound.backgroundState == 2;
+
+ SoundResource.instance().asyncLock();
+ if (sound.openPlayer(dummy)) {
+ sound.changeState(1031);
+ return obj;
+ } else {
+ this.debugOut(2, "intel30: couldn't open player on file " + sound.getURL());
+ sound.changeState(1031);
+ return null;
+ }
+ }
+
+ private Object intel31(Sound sound, Object obj) {
+ this.debugOut(6, "Entering intel31 ");
+
+ assert sound.backgroundState == 1;
+
+ if (obj == null) {
+ sound.changeState(0);
+ } else if (sound.updateSound()) {
+ sound.player.start(1);
+ sound.changeState(1032);
+ BackgroundLoader.get(sound, sound.getURL());
+ } else {
+ sound.closePlayer();
+ sound.changeState(0);
+ }
+
+ return null;
+ }
+
+ private Object intel32(Sound sound, Object obj) {
+ this.debugOut(6, "Entering intel32 ");
+
+ assert sound.backgroundState == 2;
+
+ sound.changeState(1033);
+ return obj;
+ }
+
+ private Object intel33(Sound sound, Object obj) {
+ this.debugOut(6, "Entering intel33 ");
+
+ assert sound.backgroundState == 1;
+
+ if (obj != null && sound.playAfterLoading) {
+ sound.closePlayer();
+ sound.changeState(1000);
+ sound.doState(obj);
+ } else {
+ sound.changeState(0);
+ }
+
+ return null;
+ }
+
+ private Object realAudio0(Sound sound, Object obj) {
+ this.debugOut(6, "Entering RealAudio0 ");
+
+ assert sound.backgroundState == 1;
+
+ if (!SoundResource.instance().syncLock(2)) {
+ return null;
+ } else {
+ sound.changeState(2010);
+ BackgroundLoader.get(sound, dummy);
+ return null;
+ }
+ }
+
+ private Object realAudio10(Sound sound, Object obj) {
+ this.debugOut(6, "Entering realAudio10 ");
+
+ assert sound.backgroundState == 2;
+
+ SoundResource.instance().asyncLock();
+ if (sound.openPlayer(sound.getURL())) {
+ sound.changeState(2011);
+ return sound;
+ } else {
+ return null;
+ }
+ }
+
+ private Object realAudio11(Sound sound, Object obj) {
+ this.debugOut(6, "Entering realAudio11 ");
+
+ assert sound.backgroundState == 1;
+
+ if (obj != null) {
+ if (sound.updateSound()) {
+ sound.player.start(sound.getRepeat());
+ } else {
+ sound.closePlayer();
+ }
+ }
+
+ sound.changeState(0);
+ return null;
+ }
+}
diff --git a/NET/worlds/scape/SpinBehavior.java b/NET/worlds/scape/SpinBehavior.java
new file mode 100644
index 0000000..92be2d4
--- /dev/null
+++ b/NET/worlds/scape/SpinBehavior.java
@@ -0,0 +1,122 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+public class SpinBehavior extends SwitchableBehavior implements FrameHandler {
+ protected float cycleTime;
+ protected float ax;
+ protected float ay;
+ protected float az;
+ private static Object classCookie = new Object();
+
+ public SpinBehavior() {
+ this(5.0F);
+ }
+
+ public SpinBehavior(float cycleTime) {
+ this(cycleTime, 0.0F, 0.0F, 1.0F);
+ }
+
+ public SpinBehavior(Point3Temp axis) {
+ this(5.0F, axis);
+ }
+
+ public SpinBehavior(float ax, float ay, float az) {
+ this(5.0F, ax, ay, az);
+ }
+
+ public SpinBehavior(float cycleTime, Point3Temp axis) {
+ this(cycleTime, axis.x, axis.y, axis.z);
+ }
+
+ public SpinBehavior(float cycleTime, float ax, float ay, float az) {
+ this.cycleTime = cycleTime;
+ this.ax = ax;
+ this.ay = ay;
+ this.az = az;
+ }
+
+ public float getCycleTime() {
+ return this.cycleTime;
+ }
+
+ public void setCycleTime(float t) {
+ this.cycleTime = t;
+ }
+
+ public Point3Temp getAxis() {
+ return Point3Temp.make(this.ax, this.ay, this.az);
+ }
+
+ public void setAxis(Point3Temp axis) {
+ this.ax = axis.x;
+ this.ay = axis.y;
+ this.az = axis.z;
+ }
+
+ @Override
+ public boolean handle(FrameEvent e) {
+ if (this.enabled && this.cycleTime > 0.0F) {
+ e.receiver.spin(this.ax, this.ay, this.az, 0.36F * e.dt / this.cycleTime);
+ }
+
+ return true;
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Cycle Time"));
+ } else if (mode == 1) {
+ ret = new Float(this.cycleTime);
+ } else if (mode == 2) {
+ this.cycleTime = (Float)value;
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = Point3PropertyEditor.make(new Property(this, index, "Axis"));
+ } else if (mode == 1) {
+ ret = new Point3(this.getAxis());
+ } else if (mode == 2) {
+ this.setAxis((Point3)value);
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 2, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + "[axis " + this.getAxis() + ", cycleTime " + this.cycleTime + ", enabled " + this.enabled + "]";
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(0, classCookie);
+ s.saveFloat(this.cycleTime);
+ s.saveFloat(this.ax);
+ s.saveFloat(this.ay);
+ s.saveFloat(this.az);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ this.cycleTime = r.restoreFloat();
+ this.ax = r.restoreFloat();
+ this.ay = r.restoreFloat();
+ this.az = r.restoreFloat();
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/StandardTexture.java b/NET/worlds/scape/StandardTexture.java
new file mode 100644
index 0000000..1ad283b
--- /dev/null
+++ b/NET/worlds/scape/StandardTexture.java
@@ -0,0 +1,45 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+public class StandardTexture extends Texture implements Persister {
+ private String urlName;
+ private static Object classCookie = new Object();
+
+ public StandardTexture(String urlName, String filename) {
+ this.urlName = urlName;
+ this.makeTexture(urlName, filename);
+ }
+
+ protected StandardTexture() {
+ }
+
+ private void makeTexture(String urlName, String filename) {
+ this.textureID = new ImageConverter(urlName, filename).convert();
+ }
+
+ @Override
+ public String getName() {
+ return this.urlName;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(0, classCookie);
+ super.saveState(s);
+ s.saveString(this.urlName);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ this.urlName = r.restoreString();
+ this.makeTexture(this.urlName, this.urlName);
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/StandardTextureDecoder.java b/NET/worlds/scape/StandardTextureDecoder.java
new file mode 100644
index 0000000..8501008
--- /dev/null
+++ b/NET/worlds/scape/StandardTextureDecoder.java
@@ -0,0 +1,15 @@
+package NET.worlds.scape;
+
+class StandardTextureDecoder extends TextureDecoder {
+ private String exts = "gif;jpg;jpeg;jpe;jfif;xbm";
+
+ @Override
+ protected String getExts() {
+ return this.exts;
+ }
+
+ @Override
+ protected Texture read(String urlName, String filename) {
+ return new StandardTexture(urlName, filename);
+ }
+}
diff --git a/NET/worlds/scape/StartupSensor.java b/NET/worlds/scape/StartupSensor.java
new file mode 100644
index 0000000..08f8e87
--- /dev/null
+++ b/NET/worlds/scape/StartupSensor.java
@@ -0,0 +1,41 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+public class StartupSensor extends Sensor implements FrameHandler {
+ private boolean hasTriggered = false;
+ private static Object classCookie = new Object();
+
+ @Override
+ public void addAction(Action o) {
+ this.hasTriggered = false;
+ super.addAction(o);
+ }
+
+ @Override
+ public boolean handle(FrameEvent e) {
+ if (!this.hasTriggered) {
+ this.hasTriggered = true;
+ this.trigger(e);
+ }
+
+ return true;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(0, classCookie);
+ super.saveState(s);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/State.java b/NET/worlds/scape/State.java
new file mode 100644
index 0000000..93e0cd8
--- /dev/null
+++ b/NET/worlds/scape/State.java
@@ -0,0 +1,5 @@
+package NET.worlds.scape;
+
+public interface State {
+ Object doState(StateContext var1, Object var2);
+}
diff --git a/NET/worlds/scape/StateContext.java b/NET/worlds/scape/StateContext.java
new file mode 100644
index 0000000..df29a2d
--- /dev/null
+++ b/NET/worlds/scape/StateContext.java
@@ -0,0 +1,5 @@
+package NET.worlds.scape;
+
+public interface StateContext {
+ void changeState(int var1);
+}
diff --git a/NET/worlds/scape/StdoutAction.java b/NET/worlds/scape/StdoutAction.java
new file mode 100644
index 0000000..bbb043f
--- /dev/null
+++ b/NET/worlds/scape/StdoutAction.java
@@ -0,0 +1,96 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+public class StdoutAction extends Action {
+ String txt = null;
+ boolean dumpArg = false;
+ private static Object classCookie = new Object();
+
+ public StdoutAction() {
+ }
+
+ public StdoutAction(String text) {
+ this.txt = text;
+ }
+
+ @Override
+ public Persister trigger(Event arg, Persister seqID) {
+ if (this.txt != null) {
+ System.out.println(this.txt);
+ } else {
+ System.out.println("StdoutAction " + this.getName() + ", no text!");
+ }
+
+ if (this.dumpArg) {
+ if (arg == null) {
+ System.out.println("<Null event>");
+ } else {
+ System.out.println("<" + arg + ">");
+ }
+ }
+
+ System.out.flush();
+ return null;
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Text Out"));
+ } else if (mode == 1) {
+ ret = this.txt;
+ } else if (mode == 2) {
+ this.txt = (String)value;
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Dump Event"), "Don't print event", "Print event");
+ } else if (mode == 1) {
+ ret = new Boolean(this.dumpArg);
+ } else if (mode == 2) {
+ this.dumpArg = (Boolean)value;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 2, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(1, classCookie);
+ super.saveState(s);
+ s.saveString(this.txt);
+ s.saveBoolean(this.dumpArg);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ this.txt = r.restoreString();
+ r.setOldFlag();
+ break;
+ case 1:
+ super.restoreState(r);
+ this.txt = r.restoreString();
+ this.dumpArg = r.restoreBoolean();
+ break;
+ default:
+ throw new TooNewException();
+ }
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + "[" + this.txt + "]";
+ }
+}
diff --git a/NET/worlds/scape/StopRecordingAction.java b/NET/worlds/scape/StopRecordingAction.java
new file mode 100644
index 0000000..9b63a91
--- /dev/null
+++ b/NET/worlds/scape/StopRecordingAction.java
@@ -0,0 +1,36 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.BlackBox;
+import java.io.IOException;
+
+public class StopRecordingAction extends Action {
+ private static Object classCookie = new Object();
+
+ @Override
+ public Persister trigger(Event e, Persister p) {
+ BlackBox.getInstance().stop();
+ return null;
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ return super.properties(index, offset, mode, value);
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(1, classCookie);
+ super.saveState(s);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 1:
+ super.restoreState(r);
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/StringAttribute.java b/NET/worlds/scape/StringAttribute.java
new file mode 100644
index 0000000..abbf536
--- /dev/null
+++ b/NET/worlds/scape/StringAttribute.java
@@ -0,0 +1,81 @@
+package NET.worlds.scape;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class StringAttribute extends Attribute {
+ String value = "";
+ private static Object classCookie = new Object();
+
+ public StringAttribute(int attrID) {
+ super(attrID);
+ }
+
+ public StringAttribute() {
+ }
+
+ public void set(String x) {
+ this.value = x;
+ this.noteChange();
+ }
+
+ public String get() {
+ return this.value;
+ }
+
+ @Override
+ public void generateNetData(DataOutputStream s) throws IOException {
+ s.writeUTF(this.value);
+ }
+
+ @Override
+ public void setFromNetData(DataInputStream ds, int len) throws IOException {
+ this.value = ds.readUTF();
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "value"));
+ } else if (mode == 1) {
+ ret = this.get();
+ } else if (mode == 2) {
+ this.set((String)value);
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 1, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(0, classCookie);
+ super.saveState(s);
+ s.saveString(this.value);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ this.value = r.restoreString();
+ this.set(this.value);
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + "[" + this.get() + "]";
+ }
+}
diff --git a/NET/worlds/scape/StringFieldEditorDialog.java b/NET/worlds/scape/StringFieldEditorDialog.java
new file mode 100644
index 0000000..d027cd8
--- /dev/null
+++ b/NET/worlds/scape/StringFieldEditorDialog.java
@@ -0,0 +1,31 @@
+package NET.worlds.scape;
+
+class StringFieldEditorDialog extends FieldEditorDialog {
+ Property property;
+
+ StringFieldEditorDialog(EditTile parent, String title, Property property) {
+ super(parent, title);
+ this.property = property;
+ this.ready();
+ }
+
+ @Override
+ protected String getValue() {
+ String s = (String)this.property.get();
+ return s != null ? s : "";
+ }
+
+ @Override
+ protected boolean setValue(String text) {
+ if (text.length() == 0) {
+ if (!this.property.canSetNull()) {
+ return false;
+ }
+
+ text = null;
+ }
+
+ this.parent.addUndoableSet(this.property, text);
+ return true;
+ }
+}
diff --git a/NET/worlds/scape/StringPropertyEditor.java b/NET/worlds/scape/StringPropertyEditor.java
new file mode 100644
index 0000000..f3a90ef
--- /dev/null
+++ b/NET/worlds/scape/StringPropertyEditor.java
@@ -0,0 +1,19 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.PolledDialog;
+
+public class StringPropertyEditor extends PropEditor {
+ private StringPropertyEditor(Property property) {
+ super(property);
+ }
+
+ @Override
+ public PolledDialog edit(EditTile parent, String title) {
+ return new StringFieldEditorDialog(parent, title, this.property);
+ }
+
+ public static Property make(Property property) {
+ property.setPropertyType(3);
+ return property.setEditor(new StringPropertyEditor(property));
+ }
+}
diff --git a/NET/worlds/scape/StringTexture.java b/NET/worlds/scape/StringTexture.java
new file mode 100644
index 0000000..813dfdc
--- /dev/null
+++ b/NET/worlds/scape/StringTexture.java
@@ -0,0 +1,103 @@
+package NET.worlds.scape;
+
+import java.awt.Color;
+import java.io.IOException;
+
+public class StringTexture extends Texture implements Persister {
+ private String _text;
+ private String _font;
+ private int _size;
+ private Color _fore;
+ private Color _back;
+ private char[] _array;
+ private int _length;
+ private static Object classCookie = new Object();
+
+ static {
+ nativeInit();
+ }
+
+ public StringTexture(String text, String font, int size, Color fore, Color back) {
+ this._text = text;
+ this._font = font;
+ this._size = size;
+ this._fore = fore;
+ this._back = back;
+ this._array = text.toCharArray();
+ this._length = text.length();
+ this.makeStringTexture();
+ }
+
+ protected StringTexture() {
+ }
+
+ public static native void nativeInit();
+
+ private native void makeStringTexture();
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(0, classCookie);
+ super.saveState(s);
+ s.saveString(this._text);
+ s.saveString(this._font);
+ s.saveInt(this._size);
+ s.saveInt(this._fore.getRGB());
+ s.saveInt(this._back.getRGB());
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ this._text = r.restoreString();
+ this._array = this._text.toCharArray();
+ this._length = this._text.length();
+ this._font = r.restoreString();
+ this._size = r.restoreInt();
+ this._fore = new Color(r.restoreInt());
+ this._back = new Color(r.restoreInt());
+ this.makeStringTexture();
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+
+ public String getText() {
+ return this._text;
+ }
+
+ public String getFont() {
+ return this._font;
+ }
+
+ public int getSize() {
+ return this._size;
+ }
+
+ public Color getForegroundColor() {
+ return this._fore;
+ }
+
+ public Color getBackgroundColor() {
+ return this._back;
+ }
+
+ @Override
+ public String toString() {
+ return super.toString()
+ + "["
+ + this._text
+ + ", Font "
+ + this._font
+ + ", Size "
+ + this._size
+ + ", Forground "
+ + this._fore
+ + ", Background "
+ + this._back
+ + "]";
+ }
+}
diff --git a/NET/worlds/scape/SubclumpShape.java b/NET/worlds/scape/SubclumpShape.java
new file mode 100644
index 0000000..000786f
--- /dev/null
+++ b/NET/worlds/scape/SubclumpShape.java
@@ -0,0 +1,47 @@
+package NET.worlds.scape;
+
+public class SubclumpShape extends Shape implements ShapeLoaderListener {
+ private Material pendingMaterial = null;
+ private static final boolean debug = false;
+
+ @Override
+ public void setMaterial(Material m) {
+ SuperRoot parentObj = this.getOwner();
+ if (!(parentObj instanceof Shape)) {
+ super.setMaterial(m);
+ } else {
+ Shape parent = (Shape)parentObj;
+ if (!parent.isFullyLoaded()) {
+ parent.addLoadListener(this);
+ this.pendingMaterial = m;
+ } else {
+ super.setMaterial(m);
+ }
+ }
+ }
+
+ @Override
+ protected synchronized void addRwChildren(WObject container) {
+ SuperRoot o = this.getOwner();
+ if (o instanceof Shape) {
+ Shape parent = (Shape)o;
+ if (!parent.isFullyLoaded()) {
+ this.setState(LOADING, null);
+ parent.addLoadListener(this);
+ }
+ }
+
+ super.addRwChildren(container);
+ }
+
+ @Override
+ public void notifyShapeLoaded(Shape s) {
+ this.setState(NORMAL, null);
+ this.shapeRedraw();
+ if (this.pendingMaterial != null) {
+ super.setMaterial(this.pendingMaterial);
+ }
+
+ this.pendingMaterial = null;
+ }
+}
diff --git a/NET/worlds/scape/SuperRoot.java b/NET/worlds/scape/SuperRoot.java
new file mode 100644
index 0000000..384bf05
--- /dev/null
+++ b/NET/worlds/scape/SuperRoot.java
@@ -0,0 +1,388 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.network.URL;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.text.MessageFormat;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+public class SuperRoot implements Properties, Persister {
+ private String name;
+ protected static String helpURL = "home:internal/";
+ private SuperRoot owner;
+ protected URL sourceURL;
+ private static Object classCookie = new Object();
+ static Hashtable<Class<? extends Object>, Integer> finalizedClasses = new Hashtable<Class<? extends Object>, Integer>();
+ static Hashtable<Class<? extends Object>, Integer> classCounter = new Hashtable<Class<? extends Object>, Integer>();
+
+ public final String getShortClassName() {
+ String s = this.getClass().getName();
+ int index;
+ if ((index = s.lastIndexOf(46)) != -1) {
+ s = s.substring(index + 1);
+ }
+
+ return s;
+ }
+
+ public String getName() {
+ if (this.name == null) {
+ int digits = 0;
+ String classname = this.getShortClassName();
+ Enumeration<Object> en = this.getRoot().getDeepOwned();
+
+ while (en.hasMoreElements()) {
+ SuperRoot x = (SuperRoot)en.nextElement();
+ if (x.name != null && x.name.startsWith(classname)) {
+ try {
+ int tmp = Integer.valueOf(x.name.substring(classname.length()));
+ if (tmp > digits) {
+ digits = tmp;
+ }
+ } catch (NumberFormatException var6) {
+ }
+ }
+ }
+
+ this.name = classname + ++digits;
+ }
+
+ return this.name;
+ }
+
+ public String getNameMaybeNull() {
+ return this.name;
+ }
+
+ public void setName(String v) {
+ if (v == null && this.owner != null) {
+ Object[] arguments = new Object[]{new String(this.owner.getName())};
+ Console.println(MessageFormat.format(Console.message("Warning-null-name"), arguments));
+ }
+
+ this.name = v;
+ }
+
+ public static SuperRoot nameSearch(Enumeration<?> enumeration, String name) {
+ while (enumeration.hasMoreElements()) {
+ SuperRoot n = (SuperRoot)enumeration.nextElement();
+ if (name.equals(n.name)) {
+ return n;
+ }
+ }
+
+ return null;
+ }
+
+ public URL getHelpURL() {
+ String helpString = helpURL + this.getClass().getName() + Console.message(".html");
+ URL helpPage = URL.make(helpString);
+ if (Console.wasHttpNoSuchFile(helpString)) {
+ helpPage = URL.make(helpURL + this.getClass().getName() + ".html");
+ }
+
+ return helpPage;
+ }
+
+ public URL getHelpURL(Property p) {
+ String namesub = p.getName().replace(' ', '_');
+ String helpString = helpURL + this.getClass().getName() + "#" + namesub + Console.message(".html");
+ URL helpPage = URL.make(helpString);
+ if (Console.wasHttpNoSuchFile(helpString)) {
+ helpPage = URL.make(helpURL + this.getClass().getName() + "#" + namesub + ".html");
+ }
+
+ return helpPage;
+ }
+
+ @Override
+ public String toString() {
+ return this.isActive() ? this.getName() : this.getName() + "(inactive)";
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Name"));
+ } else if (mode == 1) {
+ ret = this.getName();
+ } else if (mode == 4) {
+ this.setName(null);
+ } else if (mode == 2) {
+ String s = (String)value;
+ if (!s.equals(this.name) && this.owner != null && nameSearch(this.getRoot().getDeepOwned(), s) != null) {
+ Object[] arguments = new Object[]{new String(s), new String(this.getRoot().getName())};
+ Console.println(MessageFormat.format(Console.message("Name-in-use"), arguments));
+ } else {
+ this.setName((String)value);
+ }
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = URLPropertyEditor.make(new Property(this, index, "Source URL").allowSetNull(), "*wob", false);
+ } else if (mode == 1) {
+ ret = this.sourceURL;
+ } else if (mode == 2) {
+ this.setSourceURL((URL)value);
+ }
+ break;
+ default:
+ throw new NoSuchPropertyException();
+ }
+
+ return ret;
+ }
+
+ @Override
+ public Object propertyParent() {
+ return this.owner;
+ }
+
+ public SuperRoot getOwner() {
+ return this.owner;
+ }
+
+ public void discard() {
+ this.detach();
+ }
+
+ protected void add(SuperRoot x) {
+ if (x.owner != null && x.owner != this) {
+ System.out.println("double-setting owner of " + x + " from " + x.owner + " to " + this);
+ throw new Error("double-setting owner of " + x);
+ } else {
+ x.noteAddingTo(this);
+ x.owner = this;
+ }
+ }
+
+ public void detach() {
+ if (this.owner != null) {
+ this.owner.noteUnadding(this);
+ this.owner = null;
+ }
+ }
+
+ protected void noteAddingTo(SuperRoot s) {
+ }
+
+ protected void noteUnadding(SuperRoot s) {
+ }
+
+ public Enumeration<Object> getOwned() {
+ return new ShallowEnumeration(this);
+ }
+
+ public Enumeration<Object> getDeepOwned() {
+ return new DeepEnumeration<Object>(this);
+ }
+
+ public void getChildren(DeepEnumeration<?> d) {
+ }
+
+ public World getWorld() {
+ SuperRoot owner = this.getOwner();
+ return owner == null ? null : owner.getWorld();
+ }
+
+ public Room getRoom() {
+ SuperRoot owner = this.getOwner();
+ return owner == null ? null : owner.getRoom();
+ }
+
+ public SuperRoot getRoot() {
+ SuperRoot owner = this.getOwner();
+ return owner == null ? this : owner.getRoot();
+ }
+
+ public boolean isActive() {
+ return this.getWorld() != null;
+ }
+
+ public URL getSourceURL() {
+ return this.sourceURL;
+ }
+
+ public void setSourceURL(URL s) {
+ this.sourceURL = s;
+ }
+
+ public URL getContainingSourceURL() {
+ if (this.sourceURL != null) {
+ return this.sourceURL;
+ } else {
+ return this.owner != null ? this.owner.getContainingSourceURL() : null;
+ }
+ }
+
+ public void markEdited() {
+ if (this.owner != null) {
+ this.owner.markEdited();
+ }
+ }
+
+ public static SuperRoot readFile(String urlLocal, URL url) {
+ try {
+ Restorer r = new Restorer(urlLocal, url);
+ SuperRoot o = (SuperRoot)r.restore();
+ r.done();
+ o.setSourceURL(url);
+ return o;
+ } catch (FileNotFoundException var5) {
+ } catch (ClassCastException var6) {
+ } catch (IOException var7) {
+ } catch (TooNewException var8) {
+ } catch (BadFormatException var9) {
+ }
+
+ return null;
+ }
+
+ public static SuperRoot readFile(URL url) {
+ return readFile(url.unalias(), url);
+ }
+
+ public void loadInit() {
+ }
+
+ public void saveFile(URL url) throws IOException {
+ if (this instanceof NonPersister) {
+ throw new IOException("Can't save NonPersister");
+ } else {
+ Saver s = new Saver(url);
+ s.save(this);
+ s.done();
+ this.setSourceURL(url);
+ }
+ }
+
+ @Override
+ public Object clone() {
+ byte[] b = this.getByteCopy();
+ return getCopyFromBytes(b);
+ }
+
+ public byte[] getByteCopy() {
+ if (this instanceof NonPersister) {
+ return null;
+ } else {
+ ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+
+ try {
+ Saver saver = new Saver(new DataOutputStream(buffer));
+ saver.save(this);
+ saver.done();
+ return buffer.toByteArray();
+ } catch (Exception var3) {
+ var3.printStackTrace(System.out);
+ throw new Error("Can't save");
+ }
+ }
+ }
+
+ public static SuperRoot getCopyFromBytes(byte[] b) {
+ if (b == null) {
+ return null;
+ } else {
+ try {
+ Restorer r = new Restorer(new DataInputStream(new ByteArrayInputStream(b)));
+ SuperRoot obj = (SuperRoot)r.restore();
+ r.done();
+ return obj;
+ } catch (Exception var3) {
+ var3.printStackTrace(System.out);
+ throw new Error("Can't restore");
+ }
+ }
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(2, classCookie);
+ s.saveString(this.name);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ this.restoreStateSuperRoot(r);
+ }
+
+ protected final void restoreStateSuperRoot(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ r.setOldFlag();
+ case 2:
+ String n;
+ if ((n = r.restoreString()) != null) {
+ this.setName(n);
+ }
+ break;
+ case 1:
+ r.setOldFlag();
+ String nx;
+ if ((nx = r.restoreString()) != null) {
+ this.setName(nx);
+ }
+
+ r.restoreMaybeNull();
+ break;
+ default:
+ throw new TooNewException();
+ }
+ }
+
+ @Override
+ public void postRestore(int version) {
+ }
+
+ public static void finalizeCounter(Object o) {
+ Class<? extends Object> c = (Class<? extends Object>)o.getClass();
+ Integer icnt = finalizedClasses.get(c);
+ int cnt = 0;
+ if (icnt != null) {
+ cnt = icnt;
+ }
+
+ if (++cnt == 1000) {
+ System.out.println("Finalized 1000 times: " + c);
+ cnt = 0;
+ }
+
+ finalizedClasses.put((Class<? extends Object>)o.getClass(), new Integer(cnt));
+ }
+
+ @Override
+ protected void finalize() {
+ }
+
+ public static void countClass(Object o, int inc) {
+ Class<? extends Object> c = (Class<? extends Object>)o.getClass();
+ Integer icnt = classCounter.get(c);
+ int cnt = 0;
+ if (icnt != null) {
+ cnt = icnt;
+ }
+
+ cnt += inc;
+ classCounter.put(c, new Integer(cnt));
+ }
+
+ public static void printClassCounts() {
+ Enumeration<Class<? extends Object>> e = classCounter.keys();
+
+ while (e.hasMoreElements()) {
+ Class<?> c = e.nextElement();
+ System.out.println("Class " + c.getName() + " has " + classCounter.get(c));
+ }
+ }
+}
diff --git a/NET/worlds/scape/Surface.java b/NET/worlds/scape/Surface.java
new file mode 100644
index 0000000..61fce10
--- /dev/null
+++ b/NET/worlds/scape/Surface.java
@@ -0,0 +1,190 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import java.awt.Color;
+import java.io.IOException;
+import java.text.MessageFormat;
+
+public class Surface extends WObject implements Animatable {
+ private int[] polygonIDs;
+ protected Material material;
+ private static Object classCookie = new Object();
+
+ static {
+ nativeInit();
+ }
+
+ public Surface(Material m) {
+ if (m != null && m.getOwner() != null) {
+ m = (Material)m.clone();
+ }
+
+ this.setMaterial(m);
+ }
+
+ Surface() {
+ }
+
+ public static native void nativeInit();
+
+ @Override
+ public void loadInit() {
+ this.setMaterial(null);
+ }
+
+ @Override
+ protected void markVoid() {
+ super.markVoid();
+ this.polygonIDs = null;
+ this.material.markVoid();
+ }
+
+ @Override
+ public void recursiveAddRwChildren(WObject container) {
+ this.material.addRwChildren();
+ super.recursiveAddRwChildren(container);
+ int hres = this.material.getHRes();
+ int vres = this.material.getVRes();
+ int numVerts = this.getNumVerts();
+ if (numVerts != 4 || !this.material.getHiRes() && !this.uvOutOfRange()) {
+ assert numVerts > 0;
+
+ int[] vi = new int[numVerts];
+
+ for (int i = 0; i < numVerts; i++) {
+ vi[i] = i + 1;
+ }
+
+ this.polygonIDs = new int[1];
+ this.addPolygon(vi);
+ } else {
+ int numTiles = this.addSubPolys(hres, vres);
+ if (numTiles >= 100 && Console.getFrame().isShaperVisible()) {
+ Object[] arguments = new Object[]{new Integer(numTiles), new String(this.getRoom().getName()), new String(this.getName())};
+ Console.println(MessageFormat.format(Console.message("Memory-hog"), arguments));
+ }
+ }
+
+ this.nativeSetMaterial();
+ this.doneWithEditing();
+ }
+
+ protected void setVFlip(boolean b) {
+ if (b) {
+ this.flags |= 1048576;
+ } else {
+ this.flags &= -1048577;
+ }
+ }
+
+ protected void setUFlip(boolean b) {
+ if (b) {
+ this.flags |= 524288;
+ } else {
+ this.flags &= -524289;
+ }
+ }
+
+ protected boolean getUFlip() {
+ return (this.flags & 524288) != 0;
+ }
+
+ protected boolean getVFlip() {
+ return (this.flags & 1048576) != 0;
+ }
+
+ @Override
+ public void setMaterial(Material m) {
+ this.setMaterial(m, false);
+ }
+
+ public void setMaterial(Material m, boolean forceReload) {
+ if (m == null) {
+ m = new Material(new Color((int)(Math.random() * 1.6777216E7)));
+ } else if (this.material == m && !forceReload) {
+ return;
+ }
+
+ boolean sameSize = this.polygonIDs != null
+ && this.polygonIDs.length >= 1
+ && this.material.getHRes() == m.getHRes()
+ && this.material.getVRes() == m.getVRes();
+ if (this.material != m) {
+ if (this.material != null) {
+ this.material.detach();
+ }
+
+ this.add(m);
+ this.material = m;
+ }
+
+ if (this.polygonIDs != null) {
+ if (sameSize) {
+ this.nativeSetMaterial();
+ } else {
+ this.reclump();
+ }
+ }
+ }
+
+ private native void nativeSetMaterial();
+
+ private native boolean uvOutOfRange();
+
+ public Material getMaterial() {
+ return this.material;
+ }
+
+ native void addVertex(float var1, float var2, float var3, float var4, float var5);
+
+ native void addPolygon(int[] var1);
+
+ private native int addSubPolys(int var1, int var2);
+
+ @Override
+ public void getChildren(DeepEnumeration d) {
+ super.getChildren(d);
+ d.addChildElement(this.material);
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = new Property(this, index, "Material");
+ } else if (mode == 1) {
+ ret = this.material;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 1, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(1, classCookie);
+ super.saveState(s);
+ s.save(this.material);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ this.setMaterial(Material.restore(r));
+ break;
+ case 1:
+ super.restoreState(r);
+ this.setMaterial((Material)r.restore());
+ break;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/SwitchableBehavior.java b/NET/worlds/scape/SwitchableBehavior.java
new file mode 100644
index 0000000..645c6c4
--- /dev/null
+++ b/NET/worlds/scape/SwitchableBehavior.java
@@ -0,0 +1,62 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+public class SwitchableBehavior extends SuperRoot {
+ protected boolean enabled = true;
+ private static Object classCookie = new Object();
+
+ public boolean getEnabled() {
+ return this.enabled;
+ }
+
+ public SwitchableBehavior setEnabled(boolean s) {
+ this.enabled = s;
+ return this;
+ }
+
+ public SwitchableBehavior toggleEnabled() {
+ this.setEnabled(!this.getEnabled());
+ return this;
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Enabled"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(this.enabled);
+ } else if (mode == 2) {
+ this.enabled = (Boolean)value;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 1, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(1, classCookie);
+ super.saveState(s);
+ s.saveBoolean(this.enabled);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 1:
+ super.restoreState(r);
+ case 0:
+ this.enabled = r.restoreBoolean();
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/TCompressor.java b/NET/worlds/scape/TCompressor.java
new file mode 100644
index 0000000..d9411dd
--- /dev/null
+++ b/NET/worlds/scape/TCompressor.java
@@ -0,0 +1,465 @@
+package NET.worlds.scape;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class TCompressor {
+ private static final int CMAP_MAXPOSCOMP = 128;
+ private static final int CMAP_DEFAULTAXIS = 0;
+ private static final int CMAP_XUNITARY = 32;
+ private static final int CMAP_YUNITARY = 64;
+ private static final int CMAP_ZUNITARY = 96;
+ private static final int CMAP_ROTATION = 16;
+ private static final int CMAP_ROTSIGN1 = 8;
+ private static final int CMAP_ROTSIGN2 = 4;
+ private static final int CMAP_SCALE = 2;
+ private static final int CMAP_UNIFORMSCALE = 1;
+ private static final int MODE_SENDCMAP = 8388608;
+ private static final int MODE_SENDZ = 4194304;
+ private static final int MODE_MAXPOSCOMP = 128;
+ private static final int MODE_SENDROTAXIS = 96;
+ private static final int MODE_SENDROTATION = 16;
+ private static final int MODE_SENDSCALE = 2;
+ public static final int USER_SEND_POSITION = 32768;
+ public static final int USER_SEND_ROTATION = 16384;
+ public static final int USER_SEND_SCALE = 8192;
+ public static final int USER_SEND_ALL = 57344;
+ private static final int LOW21BITSMASK = 2097151;
+ private static final int LOW18BITSMASK = 262143;
+ private static final int LOW12BITSMASK = 4095;
+ private static final int LOW10BITSMASK = 1023;
+ private static final int LOW8BITSMASK = 255;
+ private static final int BIT20 = 1048576;
+ private static final double SCFACT = 16.0;
+ private static final double SCOFFSET = 121.6;
+ static int wroteBytes = 0;
+ public static boolean dontSend = false;
+
+ public static void compress(WObject w, Point3Temp defPos, Point3Temp defRAxis, float defRotation, Point3Temp defScale, int inputModes, DataOutputStream ds) throws IOException {
+ Point3Temp pos = w.getPosition();
+ Point3Temp rAxis = Point3Temp.make();
+ float rotation = w.getSpin(rAxis);
+ Point3Temp scale = w.getScale();
+ if (dontSend) {
+ System.err.println("DONTSEND is TRUE on COMPRESS CALL");
+ } else {
+ int mode = inputModes;
+ if ((inputModes & 32768) != 0) {
+ if (pos.x >= 0.0F && pos.x <= 4095.0 && pos.y >= 0.0F && pos.y <= 4095.0 && (pos.z >= 0.0F && pos.z <= 255.0 || pos.z == defPos.z)) {
+ mode = inputModes | 128;
+ }
+
+ if (pos.z != defPos.z) {
+ mode |= 4194304;
+ }
+ }
+
+ int outaxis1 = 0;
+ int outaxis2 = 0;
+ if ((mode & 16384) != 0 && !rAxis.sameValue(defRAxis)) {
+ int axisFlag = 0;
+ float maxAxis = rAxis.x;
+ int var24 = 32;
+ if (Math.abs(rAxis.y) > Math.abs(maxAxis)) {
+ maxAxis = rAxis.y;
+ var24 = 64;
+ }
+
+ if (Math.abs(rAxis.z) > Math.abs(maxAxis)) {
+ maxAxis = rAxis.z;
+ var24 = 96;
+ }
+
+ rAxis.x /= maxAxis;
+ rAxis.y /= maxAxis;
+ rAxis.z /= maxAxis;
+ mode |= var24;
+ if (maxAxis < 0.0F) {
+ rotation *= -1.0F;
+ }
+
+ switch (var24) {
+ case 32:
+ if (rAxis.y < 0.0F) {
+ mode |= 8;
+ }
+
+ if (rAxis.z < 0.0F) {
+ mode |= 4;
+ }
+
+ outaxis1 = Math.round(Math.abs(255.0F * rAxis.y));
+ outaxis2 = Math.round(Math.abs(255.0F * rAxis.z));
+ break;
+ case 64:
+ if (rAxis.x < 0.0F) {
+ mode |= 8;
+ }
+
+ if (rAxis.z < 0.0F) {
+ mode |= 4;
+ }
+
+ outaxis1 = Math.round(Math.abs(255.0F * rAxis.x));
+ outaxis2 = Math.round(Math.abs(255.0F * rAxis.z));
+ break;
+ case 96:
+ if (rAxis.x < 0.0F) {
+ mode |= 8;
+ }
+
+ if (rAxis.y < 0.0F) {
+ mode |= 4;
+ }
+
+ outaxis1 = Math.round(Math.abs(255.0F * rAxis.x));
+ outaxis2 = Math.round(Math.abs(255.0F * rAxis.y));
+ }
+
+ if (outaxis1 == 0 && outaxis2 == 0 && maxAxis < 0.0F) {
+ mode |= 8;
+ mode |= 4;
+ }
+
+ while (rotation >= 360.0F) {
+ rotation -= 360.0F;
+ }
+
+ while (rotation < 0.0F) {
+ rotation += 360.0F;
+ }
+
+ if (rotation != defRotation) {
+ mode |= 8388608;
+ mode |= 16;
+ }
+ }
+
+ if ((mode & 8192) != 0 && !scale.sameValue(defScale)) {
+ mode |= 8388608;
+ mode |= 2;
+ if (scale.x == scale.y && scale.x == scale.z) {
+ mode |= 1;
+ }
+ }
+
+ if ((mode & 8388608) != 0) {
+ ds.writeByte(mode & 0xFF);
+ wroteBytes++;
+ }
+
+ if ((mode & 32768) != 0) {
+ if ((mode & 128) != 0) {
+ maxCompressXY(pos.x, pos.y, ds);
+ if ((mode & 4194304) != 0 || (mode & 8388608) != 0) {
+ short iz = (short)Math.round(pos.z);
+ int outbyte = iz & 255;
+ ds.writeByte(outbyte);
+ wroteBytes++;
+ }
+ } else {
+ minCompressXYZ(pos.x, pos.y, pos.z, ds);
+ }
+ }
+
+ if ((mode & 96) != 0) {
+ ds.writeByte(outaxis1);
+ ds.writeByte(outaxis2);
+ wroteBytes += 2;
+ }
+
+ if ((mode & 16) != 0) {
+ int outbyte = (int)Math.round(256.0 * (rotation / 360.0));
+ ds.writeByte(outbyte);
+ wroteBytes++;
+ }
+
+ if ((mode & 2) != 0) {
+ double y = 16.0 * Math.log(scale.x / defScale.x) + 121.6;
+ if (y < 0.0) {
+ y = 0.0;
+ }
+
+ if (y > 255.0) {
+ y = 255.0;
+ }
+
+ int outbyte = (int)Math.round(y);
+ ds.writeByte(outbyte);
+ wroteBytes++;
+ if ((mode & 1) == 0) {
+ y = 16.0 * Math.log(scale.y / defScale.y) + 121.6;
+ if (y < 0.0) {
+ y = 0.0;
+ }
+
+ if (y > 255.0) {
+ y = 255.0;
+ }
+
+ outbyte = (int)Math.round(y);
+ ds.writeByte(outbyte);
+ wroteBytes++;
+ y = 16.0 * Math.log(scale.z / defScale.z) + 121.6;
+ if (y < 0.0) {
+ y = 0.0;
+ }
+
+ if (y > 255.0) {
+ y = 255.0;
+ }
+
+ outbyte = (int)Math.round(y);
+ ds.writeByte(outbyte);
+ wroteBytes++;
+ }
+ }
+
+ wroteBytes = 0;
+ }
+ }
+
+ private static void maxCompressXY(float x, float y, DataOutputStream ds) throws IOException {
+ short ix = (short)Math.round(x);
+ short iy = (short)Math.round(y);
+ ix = (short)(ix & 4095);
+ iy = (short)(iy & 4095);
+ int posbyte = ix >>> 4;
+ ds.writeByte(posbyte);
+ wroteBytes++;
+ ix = (short)(ix << 4);
+ ix = (short)(ix & 255);
+ posbyte = ix | iy >>> 8;
+ ds.writeByte(posbyte);
+ wroteBytes++;
+ posbyte = iy & 255;
+ ds.writeByte(posbyte);
+ wroteBytes++;
+ }
+
+ private static void minCompressXYZ(float x, float y, float z, DataOutputStream ds) throws IOException {
+ int xval = floatTo21bits(x);
+ int yval = floatTo21bits(y);
+ int zval = floatTo21bits(z);
+ int outbits = xval << 10 | yval >>> 11;
+ ds.writeInt(outbits);
+ wroteBytes += 4;
+ outbits = yval << 21 | zval;
+ ds.writeInt(outbits);
+ wroteBytes += 4;
+ }
+
+ private static int floatTo21bits(float f) {
+ for (int e = 0; e <= 3; e++) {
+ double decimal = Math.pow(10.0, e - 2);
+ float limit = (float)(262144.0 * decimal);
+ float af = Math.abs(f);
+ if (af < limit || e == 3) {
+ int m = (int)Math.round(af / decimal);
+ m &= 262143;
+ m <<= 2;
+ m |= e;
+ if (f < 0.0F) {
+ m |= 1048576;
+ }
+
+ return m;
+ }
+ }
+
+ return 0;
+ }
+
+ public static void decompress(
+ WObject w, Point3Temp defPos, Point3Temp defRAxis, float defRotation, Point3Temp defScale, int inputModes, int len, DataInputStream ds
+ ) throws IOException {
+ Point3Temp pos = w.getPosition();
+ Point3Temp rAxis = Point3Temp.make();
+ float rotation = w.getSpin(rAxis);
+ Point3Temp scale = w.getScale();
+ dontSend = true;
+ if (len == 0) {
+ w.moveTo(defPos);
+ scale.x = defScale.x / scale.x;
+ scale.y = defScale.y / scale.y;
+ scale.z = defScale.z / scale.z;
+ w.scale(scale);
+ dontSend = false;
+ } else if (len == 24) {
+ pos.x = ds.readFloat();
+ pos.y = ds.readFloat();
+ pos.z = ds.readFloat();
+ scale.x = ds.readFloat() / scale.x;
+ scale.y = ds.readFloat() / scale.y;
+ scale.z = ds.readFloat() / scale.z;
+ w.moveTo(pos);
+ w.scale(scale);
+ dontSend = false;
+ } else {
+ int mode;
+ if (len > 4) {
+ mode = inputModes | 8388608;
+ } else {
+ mode = inputModes | 128;
+ }
+
+ if (len == 4) {
+ mode |= 4194304;
+ }
+
+ if ((mode & 8388608) != 0) {
+ int inbyte = ds.readUnsignedByte();
+ mode |= inbyte;
+ mode |= 4194304;
+ }
+
+ if ((mode & 32768) != 0) {
+ if ((mode & 128) != 0) {
+ pos = maxDecompressXY(pos, ds);
+ if ((mode & 4194304) != 0) {
+ int iz = ds.readUnsignedByte();
+ pos.z = iz;
+ }
+ } else {
+ pos = minDecompressXYZ(pos, ds);
+ }
+
+ w.moveTo(pos);
+ }
+
+ if ((mode & 8388608) == 0) {
+ dontSend = false;
+ } else {
+ if ((mode & 16) != 0) {
+ w.spin(rAxis.x, rAxis.y, rAxis.z, -rotation);
+ }
+
+ rAxis.x = defRAxis.x;
+ rAxis.y = defRAxis.y;
+ rAxis.z = defRAxis.z;
+ if ((mode & 96) != 0) {
+ int inaxis1 = ds.readUnsignedByte();
+ int inaxis2 = ds.readUnsignedByte();
+ switch (mode & 96) {
+ case 0:
+ default:
+ break;
+ case 32:
+ rAxis.x = 1.0F;
+ rAxis.y = (float)(inaxis1 / 255.0);
+ rAxis.z = (float)(inaxis2 / 255.0);
+ if ((mode & 8) != 0) {
+ rAxis.y = (float)(rAxis.y * -1.0);
+ }
+
+ if ((mode & 4) != 0) {
+ rAxis.z = (float)(rAxis.z * -1.0);
+ }
+
+ if (rAxis.y == 0.0F && rAxis.z == 0.0F && (mode & 8) != 0 && (mode & 4) != 0) {
+ rAxis.x = -1.0F;
+ }
+ break;
+ case 64:
+ rAxis.y = 1.0F;
+ rAxis.x = (float)(inaxis1 / 255.0);
+ rAxis.z = (float)(inaxis2 / 255.0);
+ if ((mode & 8) != 0) {
+ rAxis.x = (float)(rAxis.x * -1.0);
+ }
+
+ if ((mode & 4) != 0) {
+ rAxis.z = (float)(rAxis.z * -1.0);
+ }
+
+ if (rAxis.x == 0.0F && rAxis.z == 0.0F && (mode & 8) != 0 && (mode & 4) != 0) {
+ rAxis.y = -1.0F;
+ }
+ break;
+ case 96:
+ rAxis.z = 1.0F;
+ rAxis.x = (float)(inaxis1 / 255.0);
+ rAxis.y = (float)(inaxis2 / 255.0);
+ if ((mode & 8) != 0) {
+ rAxis.x = (float)(rAxis.x * -1.0);
+ }
+
+ if ((mode & 4) != 0) {
+ rAxis.y = (float)(rAxis.y * -1.0);
+ }
+
+ if (rAxis.x == 0.0F && rAxis.y == 0.0F && (mode & 8) != 0 && (mode & 4) != 0) {
+ rAxis.z = -1.0F;
+ }
+ }
+ }
+
+ if ((mode & 16) != 0) {
+ int inbyte = ds.readUnsignedByte();
+ rotation = (float)(360.0 * (inbyte / 256.0));
+ w.worldSpin(rAxis.x, rAxis.y, rAxis.z, rotation);
+ }
+
+ if ((mode & 2) != 0) {
+ int inbyte = ds.readUnsignedByte();
+ double s = defScale.x * Math.exp((inbyte - 121.6) / 16.0);
+ scale.x = (float)s;
+ if ((mode & 1) != 0) {
+ scale.y = scale.x;
+ scale.z = scale.x;
+ } else {
+ inbyte = ds.readUnsignedByte();
+ s = defScale.y * Math.exp((inbyte - 121.6) / 16.0);
+ scale.y = (float)s;
+ inbyte = ds.readUnsignedByte();
+ s = defScale.z * Math.exp((inbyte - 121.6) / 16.0);
+ scale.z = (float)s;
+ }
+
+ Point3Temp oldScale = w.getScale();
+ scale.x = scale.x / oldScale.x;
+ scale.y = scale.y / oldScale.y;
+ scale.z = scale.z / oldScale.z;
+ w.scale(scale);
+ }
+
+ dontSend = false;
+ }
+ }
+ }
+
+ private static Point3Temp maxDecompressXY(Point3Temp pos, DataInputStream ds) throws IOException {
+ int ix = ds.readUnsignedByte();
+ ix <<= 4;
+ int iy = ds.readUnsignedByte();
+ ix |= iy >>> 4;
+ iy &= 15;
+ iy <<= 8;
+ iy |= ds.readUnsignedByte();
+ pos.x = ix;
+ pos.y = iy;
+ return pos;
+ }
+
+ private static Point3Temp minDecompressXYZ(Point3Temp pos, DataInputStream ds) throws IOException {
+ int i1 = ds.readInt();
+ int i2 = ds.readInt();
+ int tmp = i1 >>> 10;
+ pos.x = floatFrom21bits(tmp);
+ tmp = (i1 & 1023) << 11;
+ tmp |= i2 >>> 21;
+ pos.y = floatFrom21bits(tmp);
+ tmp = i2 & 2097151;
+ pos.z = floatFrom21bits(tmp);
+ return pos;
+ }
+
+ private static float floatFrom21bits(int bits) {
+ int e = bits & 3;
+ int s = (bits & 1048576) << 11 | 1;
+ int m = (bits & -1048577) >>> 2;
+ double d = Math.pow(10.0, e - 2);
+ return (float)(m * d * s);
+ }
+}
diff --git a/NET/worlds/scape/TabbedDisplayPanel.java b/NET/worlds/scape/TabbedDisplayPanel.java
new file mode 100644
index 0000000..c5b99f8
--- /dev/null
+++ b/NET/worlds/scape/TabbedDisplayPanel.java
@@ -0,0 +1,98 @@
+package NET.worlds.scape;
+
+import java.awt.CardLayout;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Insets;
+import java.awt.Panel;
+import java.awt.Point;
+import java.util.Vector;
+
+class TabbedDisplayPanel extends Panel {
+ private int count;
+ private Vector cards = new Vector();
+ private Vector cardNames = new Vector();
+
+ TabbedDisplayPanel() {
+ this.setLayout(new CardLayout());
+ }
+
+ void addItem(Component c) {
+ this.insertItem(this.cards.size(), c);
+ }
+
+ void insertItem(int index, Component c) {
+ String cardName = "" + this.count++;
+ this.cardNames.insertElementAt(cardName, index);
+ this.cards.insertElementAt(c, index);
+ this.add(cardName, c);
+ this.validate();
+ this.repaint();
+ }
+
+ void removeItem(int index) {
+ this.remove((Component)this.cards.elementAt(index));
+ this.cards.removeElementAt(index);
+ this.cardNames.removeElementAt(index);
+ }
+
+ @Override
+ public Component getComponent(int index) {
+ return (Component)this.cards.elementAt(index);
+ }
+
+ void setChoice(int index) {
+ ((CardLayout)this.getLayout()).show(this, (String)this.cardNames.elementAt(index));
+ }
+
+ @Override
+ public Insets insets() {
+ return new Insets(0, 2, 2, 0);
+ }
+
+ @Override
+ public void paint(Graphics g) {
+ g.setColor(this.getBackground());
+ if (this.cards.size() != 0) {
+ Dimension size = this.size();
+ vLine(g, 1, 0, size.height);
+ g.setColor(this.getBackground().brighter());
+ vLine(g, 0, 0, size.height - 2);
+ g.setColor(this.getBackground().darker());
+ hLine(g, 0, size.height - 1, size.width - 1);
+ vLine(g, size.width - 1, size.height - 1, 0);
+ hLine(g, 1, size.height - 2, size.width - 2);
+ vLine(g, size.width - 2, size.height - 2, 0);
+ } else {
+ g.fillRect(0, 0, this.size().width, this.size().height);
+ }
+ }
+
+ private static void vLine(Graphics g, int x1, int y1, int y2) {
+ g.drawLine(x1, y1, x1, y2);
+ }
+
+ private static void hLine(Graphics g, int x1, int y1, int x2) {
+ g.drawLine(x1, y1, x2, y1);
+ }
+
+ @Override
+ public Component locate(int x, int y) {
+ if (!this.inside(x, y)) {
+ return null;
+ } else {
+ int n = this.countComponents();
+
+ for (int i = 0; i < n; i++) {
+ Component c = this.getComponent(i);
+ Point loc = c.location();
+ if (c != null && c.isVisible() && c.inside(x - loc.x, y - loc.y)) {
+ return c;
+ }
+ }
+
+ return this;
+ }
+ }
+}
diff --git a/NET/worlds/scape/TabbedPanel.java b/NET/worlds/scape/TabbedPanel.java
new file mode 100644
index 0000000..3e7b3fd
--- /dev/null
+++ b/NET/worlds/scape/TabbedPanel.java
@@ -0,0 +1,274 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.DialogDisabled;
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Insets;
+import java.awt.Panel;
+import java.awt.Point;
+import java.util.Vector;
+
+public class TabbedPanel extends Panel implements ClickEventHandler, DialogDisabled {
+ private Vector entries = new Vector();
+ private int rows;
+ private int itemWidth;
+ private int itemHeight;
+ private int itemsPerRow;
+ private int choice;
+ private Font nFont;
+ private FontMetrics nFontMetrics;
+ private Font bFont;
+ private FontMetrics bFontMetrics;
+ private int fontHeight;
+ private TabbedDisplayPanel disp = new TabbedDisplayPanel();
+ private ClickEventHandler handler;
+ private boolean needRecalc;
+ private boolean isDialogDisabled;
+
+ public TabbedPanel(ClickEventHandler handler) {
+ this.handler = handler;
+ this.setLayout(new BorderLayout());
+ this.add("Center", this.disp);
+ }
+
+ public TabbedPanel() {
+ this(null);
+ this.handler = this;
+ }
+
+ public void addItem(String name, Component c) {
+ this.entries.addElement(name);
+ this.needRecalc = true;
+ this.repaint();
+ this.disp.addItem(c);
+ }
+
+ public void insertItem(int index, String name, Component c) {
+ this.entries.insertElementAt(name, index);
+ this.disp.insertItem(index, c);
+ if (index <= this.choice) {
+ this.choice = Math.min(this.choice + 1, this.entries.size() - 1);
+ }
+
+ this.needRecalc = true;
+ this.repaint();
+ }
+
+ public void removeItem(int index) {
+ this.entries.removeElementAt(index);
+ this.disp.removeItem(index);
+ if (index == this.choice) {
+ int count = this.entries.size();
+ if (count > 0) {
+ this.choice = Math.min(this.choice, count - 1);
+ this.disp.setChoice(this.choice);
+ }
+ } else if (index < this.choice) {
+ this.choice--;
+ }
+
+ this.needRecalc = true;
+ this.repaint();
+ }
+
+ public void select(int index) {
+ this.choice = index;
+ this.repaint();
+ this.disp.setChoice(index);
+ }
+
+ public String getName(int index) {
+ return (String)this.entries.elementAt(index);
+ }
+
+ public void setName(int index, String name) {
+ this.entries.setElementAt(name, index);
+ this.needRecalc = true;
+ this.repaint();
+ }
+
+ @Override
+ public Component getComponent(int index) {
+ return index < this.entries.size() ? this.disp.getComponent(index) : null;
+ }
+
+ public int selected() {
+ return this.choice;
+ }
+
+ public int itemAt(Point p) {
+ if (!this.needRecalc) {
+ Point tab = new Point(0, 0);
+ int count = this.entries.size();
+
+ for (int i = 0; i < count; i++) {
+ this.getPosition(i, tab);
+ if (p.x >= tab.x && p.y >= tab.y && p.x < tab.x + this.itemWidth && p.y < tab.y + this.itemHeight) {
+ return i;
+ }
+ }
+ }
+
+ return -1;
+ }
+
+ @Override
+ public void addNotify() {
+ super.addNotify();
+ this.nFont = new Font(Console.message("NotifyFont"), 0, 13);
+ this.nFontMetrics = this.getFontMetrics(this.nFont);
+ this.bFont = new Font(Console.message("NotifyFont"), 1, 14);
+ this.bFontMetrics = this.getFontMetrics(this.bFont);
+ this.fontHeight = Math.max(this.nFontMetrics.getHeight(), this.bFontMetrics.getHeight());
+ this.itemHeight = this.fontHeight + 5;
+ }
+
+ @Override
+ public Insets insets() {
+ if (this.needRecalc) {
+ this.recalc();
+ }
+
+ return new Insets(this.rows * this.itemHeight, 0, 0, 0);
+ }
+
+ @Override
+ public void reshape(int x, int y, int width, int height) {
+ super.reshape(x, y, width, height);
+ this.needRecalc = true;
+ this.repaint();
+ }
+
+ private void recalc() {
+ int row = 0;
+ int itemsOnRow = 0;
+ int x = 0;
+ int count = this.entries.size();
+ this.itemWidth = 0;
+
+ for (int i = 0; i < count; i++) {
+ String name = (String)this.entries.elementAt(i);
+ int w = Math.max(this.bFontMetrics.stringWidth(name), this.nFontMetrics.stringWidth(" " + name + " "));
+ this.itemWidth = Math.max(w, this.itemWidth);
+ }
+
+ this.itemWidth += 4;
+ this.itemsPerRow = Math.max(1, this.size().width / this.itemWidth);
+ this.rows = (count + this.itemsPerRow - 1) / this.itemsPerRow;
+ this.needRecalc = false;
+ this.invalidate();
+ this.validate();
+ }
+
+ private void getPosition(int entry, Point pos) {
+ int count = this.entries.size();
+ int firstRow = this.choice / this.itemsPerRow;
+ int entryRow = entry / this.itemsPerRow;
+ int column = entry - entryRow * this.itemsPerRow;
+ pos.x = column * this.itemWidth;
+ pos.y = (this.rows - 1 - entryRow) * this.itemHeight - 2;
+ }
+
+ private static void vLine(Graphics g, int x1, int y1, int y2) {
+ g.drawLine(x1, y1, x1, y2);
+ }
+
+ private static void hLine(Graphics g, int x1, int y1, int x2) {
+ g.drawLine(x1, y1, x2, y1);
+ }
+
+ @Override
+ public void paint(Graphics g) {
+ if (this.needRecalc) {
+ this.recalc();
+ }
+
+ g.setColor(this.getBackground());
+ g.fillRect(0, 0, this.size().width, this.size().height);
+ int count = this.entries.size();
+ if (count != 0) {
+ Point p = new Point(0, 0);
+ int maxWidth = this.itemWidth - 4;
+
+ for (int i = 0; i < count; i++) {
+ this.getPosition(i, p);
+ String ent = (String)this.entries.elementAt(i);
+ int x1 = p.x;
+ int y1 = p.y + 4;
+ int y2 = y1 + this.fontHeight;
+ int yFont = y1;
+ Font font = this.nFont;
+ FontMetrics fm = this.nFontMetrics;
+ boolean selected = i == this.choice;
+ if (selected) {
+ y1 = p.y + 2;
+ y2 = y1 + this.fontHeight + 4;
+ yFont = y1 + 1;
+ font = this.bFont;
+ fm = this.bFontMetrics;
+ }
+
+ int width = fm.stringWidth(ent);
+ int spacing = (maxWidth - width) / 2;
+ int x2 = x1 + maxWidth;
+ g.setFont(font);
+ g.setColor(this.getBackground().brighter());
+ if (selected) {
+ hLine(g, 0, y2, x1);
+ hLine(g, x2 + 3, y2, this.size().width);
+ }
+
+ vLine(g, x1, y2, y1 + 2);
+ g.drawLine(x1, y1 + 2, x1 + 2, y1);
+ hLine(g, x1 + 2, y1, x2);
+ g.setColor(this.getBackground().darker());
+ vLine(g, x2 + 1, y1 + 1, y2);
+ vLine(g, x2 + 2, y1 + 2, y2);
+ g.setColor(this.getForeground());
+ g.drawString(ent, x1 + 1 + spacing, yFont + fm.getAscent() + fm.getLeading());
+ }
+ }
+ }
+
+ @Override
+ public void clickEvent(Component who, Point location, int flags) {
+ }
+
+ @Override
+ public boolean mouseDown(java.awt.Event event, int x, int y) {
+ Point p = new Point(x, y);
+ int tmp = this.itemAt(p);
+ if (tmp != -1) {
+ this.choice = tmp;
+ this.repaint();
+ this.disp.setChoice(this.choice);
+ int flags = 1;
+ if (event.metaDown()) {
+ flags |= 4;
+ }
+
+ this.handler.clickEvent(this, p, flags);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public boolean handleEvent(java.awt.Event event) {
+ return this.isDialogDisabled ? false : super.handleEvent(event);
+ }
+
+ @Override
+ public void dialogDisable(boolean disable) {
+ this.isDialogDisabled = disable;
+ Component c = this.getComponent(this.selected());
+ if (c != null && c instanceof DialogDisabled) {
+ ((DialogDisabled)c).dialogDisable(disable);
+ }
+ }
+}
diff --git a/NET/worlds/scape/TalkAction.java b/NET/worlds/scape/TalkAction.java
new file mode 100644
index 0000000..7929ea3
--- /dev/null
+++ b/NET/worlds/scape/TalkAction.java
@@ -0,0 +1,66 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+public class TalkAction extends Action {
+ String txt = null;
+ private static Object classCookie = new Object();
+
+ public TalkAction() {
+ }
+
+ public TalkAction(String text) {
+ this.txt = text;
+ }
+
+ @Override
+ public Persister trigger(Event arg, Persister seqID) {
+ Pilot.getActive();
+ Pilot.sendText(this.txt);
+ return null;
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Message"));
+ } else if (mode == 1) {
+ ret = this.txt;
+ } else if (mode == 2) {
+ this.txt = (String)value;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 1, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(0, classCookie);
+ super.saveState(s);
+ s.saveString(this.txt);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ this.txt = r.restoreString();
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + "[" + this.txt + "]";
+ }
+}
diff --git a/NET/worlds/scape/Teleport.java b/NET/worlds/scape/Teleport.java
new file mode 100644
index 0000000..5034290
--- /dev/null
+++ b/NET/worlds/scape/Teleport.java
@@ -0,0 +1,122 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import java.io.IOException;
+import java.text.MessageFormat;
+
+public class Teleport extends SwitchableBehavior implements FrameHandler, Persister, MouseDownHandler, BumpHandler, TeleportStatus {
+ String trigger = "none";
+ String externalTriggerTag = "";
+ String worldName = "";
+ private Room currentRoom = null;
+
+ @Override
+ public boolean handle(FrameEvent e) {
+ return true;
+ }
+
+ @Override
+ public boolean handle(MouseDownEvent e) {
+ if (this.enabled && this.trigger.equals("click")) {
+ this.currentRoom = e.target.getRoom();
+ TeleportAction.teleport(this.worldName, this);
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean handle(BumpEventTemp e) {
+ if (this.enabled && this.trigger.equals("bump")) {
+ this.currentRoom = e.target.getRoom();
+ TeleportAction.teleport(this.worldName, this);
+ }
+
+ return true;
+ }
+
+ @Override
+ public void teleportStatus(String err, String url) {
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Trigger"));
+ } else if (mode == 1) {
+ ret = new String(this.trigger);
+ } else if (mode == 2) {
+ this.trigger = ((String)value).trim();
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "External Trigger Tag"));
+ } else if (mode == 1) {
+ ret = new String(this.externalTriggerTag);
+ } else if (mode == 2) {
+ this.externalTriggerTag = ((String)value).trim();
+ }
+ break;
+ case 2:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "World Name"));
+ } else if (mode == 1) {
+ ret = new String(this.worldName);
+ } else if (mode == 2) {
+ this.worldName = ((String)value).trim();
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 3, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public String toString() {
+ return super.toString()
+ + "[trigger "
+ + this.trigger
+ + ", External trigger"
+ + this.externalTriggerTag
+ + ", World Name "
+ + this.worldName
+ + ", enabled "
+ + this.enabled
+ + "]";
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveString(this.trigger);
+ s.saveString(this.externalTriggerTag);
+ s.saveString(this.worldName);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException {
+ this.trigger = r.restoreString();
+ this.externalTriggerTag = r.restoreString();
+ this.worldName = r.restoreString();
+ }
+
+ @Override
+ public void postRestore(int version) {
+ String name = this.getName();
+ String arg1 = name == null ? "<null>" : name;
+ SuperRoot owner = this.getOwner();
+ String oname = "";
+ if (owner != null) {
+ oname = owner.getName();
+ }
+
+ String arg2 = oname == null ? "<null>" : oname;
+ Object[] arguments = new Object[]{new String(arg1), new String(arg2)};
+ Console.println(MessageFormat.format(Console.message("Teleport-obs"), arguments));
+ }
+}
diff --git a/NET/worlds/scape/TeleportAction.java b/NET/worlds/scape/TeleportAction.java
new file mode 100644
index 0000000..c73dada
--- /dev/null
+++ b/NET/worlds/scape/TeleportAction.java
@@ -0,0 +1,539 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.DialogReceiver;
+import NET.worlds.console.Main;
+import NET.worlds.console.MainCallback;
+import NET.worlds.console.WorldsMarkPart;
+import NET.worlds.core.IniFile;
+import NET.worlds.network.NetUpdate;
+import NET.worlds.network.URL;
+import java.awt.Frame;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.text.MessageFormat;
+
+public class TeleportAction extends Action implements LoadedURLSelf, MainCallback, DialogReceiver {
+ private Point3 targetCoords = new Point3();
+ private float targetRot = 0.0F;
+ private Point3 targetAxis = new Point3(0.0F, 0.0F, -1.0F);
+ private String targetRoomName = null;
+ private String targetDimension = null;
+ private URL targetWorldURL = null;
+ private boolean useDefCoordinates = false;
+ private boolean done = false;
+ private boolean showDialog = true;
+ private boolean forceWorldLoad = false;
+ private boolean forceNoWorldLoad = false;
+ private String targetURL;
+ private static TeleportAction activeTeleport = null;
+ private TeleportDialog dialog = null;
+ private TeleportStatus doneCallback;
+ String tempParseStr;
+ private static Object classCookie = new Object();
+
+ public TeleportAction() {
+ }
+
+ @Override
+ public Persister trigger(Event e, Persister seqID) {
+ if (activeTeleport != this) {
+ this.targetURL = this.asURL();
+ this.startTeleport();
+ }
+
+ return !this.done && activeTeleport != this ? this : null;
+ }
+
+ public void stopLoading() {
+ this.done = true;
+ if (activeTeleport == this) {
+ this.stopTeleport(null);
+ }
+ }
+
+ public static boolean isTeleporting() {
+ return activeTeleport != null;
+ }
+
+ public static void teleport(String url, TeleportStatus callback) {
+ TeleportAction t = new TeleportAction(url, callback);
+ if (Main.isMainThread()) {
+ t.startTeleport();
+ } else {
+ Main.register(t);
+ }
+ }
+
+ public static void teleport(String url, TeleportStatus callback, boolean forceWorldLoad) {
+ TeleportAction t = new TeleportAction(url, callback);
+ t.forceWorldLoad = forceWorldLoad;
+ t.forceNoWorldLoad = !forceWorldLoad;
+ if (Main.isMainThread()) {
+ t.startTeleport();
+ } else {
+ Main.register(t);
+ }
+ }
+
+ public static void teleport(String url, TeleportStatus callback, boolean forceWorldLoad, boolean pShowDialog) {
+ TeleportAction t = new TeleportAction(url, callback);
+ t.showDialog = pShowDialog;
+ t.forceWorldLoad = forceWorldLoad;
+ t.forceNoWorldLoad = !forceWorldLoad;
+ if (Main.isMainThread()) {
+ t.startTeleport();
+ } else {
+ Main.register(t);
+ }
+ }
+
+ @Override
+ public void mainCallback() {
+ Main.unregister(this);
+ this.startTeleport();
+ }
+
+ public static String toURLString(String url) {
+ if (url == null || url.equals("world:")) {
+ url = WorldsMarkPart.getFirstSystemMarkURL();
+ }
+
+ if (url == null) {
+ url = "home:NewWorld.world";
+ }
+
+ if (url.startsWith("world:")) {
+ if (url.equals("world:restart")) {
+ url = IniFile.gamma().getIniString("RestartAt", WorldsMarkPart.getFirstSystemMarkURL());
+ } else if (url.equals("world:store")) {
+ url = World.getHomeStore().getAbsolute();
+ } else {
+ url = url.substring(6);
+ }
+
+ int i = url.indexOf(".world?");
+ if (i >= 0) {
+ url = url.substring(0, i) + ".world#" + url.substring(i + 7);
+ }
+ }
+
+ if (url.indexOf(58) < 0) {
+ if (url.indexOf(47) < 0 && url.indexOf(92) < 0 && !url.endsWith(".world")) {
+ url = "home:" + url + "/" + url + ".world";
+ } else {
+ url = "file:" + url;
+ }
+ }
+
+ return url;
+ }
+
+ private TeleportAction(String url, TeleportStatus callback) {
+ this.doneCallback = callback;
+ this.targetURL = toURLString(url);
+ url = this.setFromURL(this.targetURL);
+
+ try {
+ if (this.targetURL.startsWith("http://")) {
+ this.targetWorldURL = new URL(url);
+ } else {
+ this.targetWorldURL = new URL(URL.getCurDir(), URL.maybeAddExt(url, ".world"));
+ }
+ } catch (MalformedURLException var4) {
+ this.targetWorldURL = URL.make("error:\"" + url + '"');
+ }
+ }
+
+ private float getNextFloat(float def) {
+ String s = this.tempParseStr;
+ int end = this.tempParseStr.indexOf(44);
+ if (end == -1) {
+ end = this.tempParseStr.length();
+ this.tempParseStr = "";
+ } else {
+ this.tempParseStr = this.tempParseStr.substring(end + 1);
+ }
+
+ try {
+ return Float.valueOf(s.substring(0, end));
+ } catch (NumberFormatException var5) {
+ return def;
+ }
+ }
+
+ private String setFromURL(String url) {
+ this.useDefCoordinates = true;
+ int roomNameStart = url.lastIndexOf(35);
+ if (roomNameStart >= 0) {
+ String rest = url.substring(roomNameStart + 1);
+ url = url.substring(0, roomNameStart);
+ int roomNameEnd = rest.lastIndexOf(64);
+ if (roomNameEnd < 0) {
+ this.targetRoomName = rest;
+ } else {
+ this.useDefCoordinates = false;
+ this.targetRoomName = rest.substring(0, roomNameEnd);
+ this.tempParseStr = rest.substring(roomNameEnd + 1);
+ this.targetCoords.x = this.getNextFloat(this.targetCoords.x);
+ this.targetCoords.y = this.getNextFloat(this.targetCoords.y);
+ this.targetCoords.z = this.getNextFloat(this.targetCoords.z);
+ this.targetRot = this.getNextFloat(this.targetRot);
+ this.targetAxis.x = this.getNextFloat(this.targetAxis.x);
+ this.targetAxis.y = this.getNextFloat(this.targetAxis.y);
+ this.targetAxis.z = this.getNextFloat(this.targetAxis.z);
+ this.tempParseStr = null;
+ }
+ }
+
+ if (this.targetRoomName != null) {
+ int rightAngle = this.targetRoomName.lastIndexOf(62);
+ int leftAngle = this.targetRoomName.lastIndexOf(60);
+ if (rightAngle + 1 == this.targetRoomName.length() && leftAngle >= 0) {
+ this.targetDimension = this.targetRoomName.substring(leftAngle + 1, rightAngle);
+ this.targetRoomName = this.targetRoomName.substring(0, leftAngle);
+ }
+ }
+
+ return url;
+ }
+
+ private void makeTeleportDialog(URL url) {
+ if (this.showDialog) {
+ Frame gf = Console.getFrame();
+ if (gf != null && gf.isShowing()) {
+ this.dialog = new TeleportDialog(gf, this);
+ }
+ }
+ }
+
+ private void startTeleport() {
+ if (activeTeleport != null) {
+ if (activeTeleport.doneCallback != null) {
+ activeTeleport.doneCallback.teleportStatus("overridden by new teleport", activeTeleport.targetURL);
+ }
+
+ activeTeleport.stopTeleport(null);
+ }
+
+ activeTeleport = this;
+ Console.setFreezeFrameEvents(true);
+ this.done = false;
+ Console.teleportNotification("", this.targetURL);
+ if (this.targetWorldURL != null) {
+ this.makeTeleportDialog(this.targetWorldURL);
+ World.load(this.targetWorldURL, this, this.forceWorldLoad);
+ } else {
+ Pilot pilot = Pilot.getActive();
+ World w;
+ if (pilot != null && (w = pilot.getWorld()) != null) {
+ this.makeTeleportDialog(w.getSourceURL());
+ this.loadedURLSelf(w, this.targetWorldURL, null);
+ } else {
+ this.stopTeleport("Pilot not in a room for intraworld teleport");
+ }
+ }
+ }
+
+ private Room stopTeleport(String err) {
+ assert this == activeTeleport;
+
+ this.done = true;
+ activeTeleport = null;
+ Console.setFreezeFrameEvents(false);
+ if (this.doneCallback != null) {
+ this.doneCallback.teleportStatus(err, this.targetURL);
+ }
+
+ if (err != null && !this.forceNoWorldLoad) {
+ Console.teleportNotification(err, this.targetURL);
+ Console.println(err);
+ }
+
+ if (this.dialog != null) {
+ this.dialog.closeIt(true);
+ this.dialog = null;
+ }
+
+ return null;
+ }
+
+ @Override
+ public synchronized void dialogDone(Object who, boolean confirmed) {
+ if (activeTeleport != null) {
+ activeTeleport.stopTeleport(null);
+ }
+ }
+
+ public static String getReadableNameOfWorld(URL url) {
+ String worldDir = url.getAbsolute();
+ String readable = worldDir;
+ String packageName = null;
+ if (worldDir.startsWith("home:") && worldDir.length() > 6) {
+ readable = worldDir.substring(worldDir.charAt(5) == '/' ? 6 : 5);
+ int slash = readable.indexOf(47);
+ if (slash > 0) {
+ packageName = readable.substring(0, slash);
+ if (readable.regionMatches(true, slash + 1, readable, 0, slash)) {
+ readable = packageName;
+ String s = WorldsMarkPart.getExternalName(packageName);
+ if (s != null) {
+ readable = s;
+ }
+ }
+ }
+
+ int tail = readable.indexOf(".world");
+ if (tail > 0) {
+ readable = readable.substring(0, tail);
+ }
+
+ readable = "the " + readable + " world";
+ }
+
+ return readable;
+ }
+
+ public static String getPackageNameOfWorld(URL url) {
+ String worldDir = url.getAbsolute();
+ String packageName = null;
+ if (worldDir.startsWith("home:") && worldDir.length() > 6) {
+ String readable = worldDir.substring(worldDir.charAt(5) == '/' ? 6 : 5);
+ int slash = readable.indexOf(47);
+ if (slash > 0) {
+ packageName = readable.substring(0, slash);
+ }
+ }
+
+ return packageName;
+ }
+
+ @Override
+ public void loadedURLSelf(URLSelf o, URL url, String err) {
+ if (activeTeleport != this) {
+ if (o != null) {
+ o.decRef();
+ }
+ } else if (err == null && o instanceof World) {
+ String roomName = this.targetRoomName;
+ if (roomName == null) {
+ roomName = ((World)o).getDefaultRoomName();
+ }
+
+ Room room = ((World)o).getRoom(roomName);
+ if (room == null) {
+ this.stopTeleport("Error finding room " + this.targetRoomName);
+ } else if (room.getVIPOnly() && !((World)o).getConsole().getVIP()) {
+ this.stopTeleport("Only VIPs may go there.");
+ if (this.forceNoWorldLoad) {
+ Console.println(Console.message("Only-VIPs-there"));
+ }
+ } else {
+ Console.teleportNotification(null, this.targetURL);
+ Pilot pilot = Pilot.changeActiveRoom(room);
+ if (this.targetDimension != null) {
+ pilot.changeChannel(this.targetDimension);
+ }
+
+ pilot.makeIdentity();
+ if (this.useDefCoordinates) {
+ pilot.moveTo(room.getDefaultPosition()).spin(room.getDefaultOrientationAxis(), room.getDefaultOrientation());
+ } else {
+ pilot.moveTo(this.targetCoords).spin(this.targetAxis, this.targetRot);
+ }
+
+ this.stopTeleport(null);
+ }
+ } else {
+ if (err == null) {
+ err = "file " + url + " doesn't contain a World";
+ o.decRef();
+ }
+
+ String readable = getReadableNameOfWorld(url);
+ String packageName = getPackageNameOfWorld(url);
+ Object[] arguments = new Object[]{new String(readable)};
+ this.stopTeleport(MessageFormat.format(Console.message("cant-teleport"), arguments));
+ if (packageName != null && !this.forceNoWorldLoad) {
+ NetUpdate.loadWorld(packageName, this.forceWorldLoad);
+ }
+ }
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = Point3PropertyEditor.make(new Property(this, index, "X, Y, Z"));
+ } else if (mode == 1) {
+ ret = new Point3(this.targetCoords);
+ } else if (mode == 2) {
+ this.targetCoords.copy((Point3)value);
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Dir"));
+ } else if (mode == 1) {
+ ret = new Float(this.targetRot);
+ } else if (mode == 2) {
+ this.targetRot = (Float)value;
+ }
+ break;
+ case 2:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Room Name").allowSetNull());
+ } else if (mode == 1) {
+ if (this.targetRoomName == null) {
+ ret = "";
+ } else {
+ ret = new String(this.targetRoomName);
+ }
+ } else if (mode == 2) {
+ this.targetRoomName = (String)value;
+ this.stopLoading();
+ }
+ break;
+ case 3:
+ if (mode == 0) {
+ ret = URLPropertyEditor.make(new Property(this, index, "World URL").allowSetNull(), "world");
+ } else if (mode == 1) {
+ ret = this.targetWorldURL;
+ } else if (mode == 2) {
+ this.targetWorldURL = (URL)value;
+ this.stopLoading();
+ }
+ break;
+ case 4:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Use default coordinates"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(this.useDefCoordinates);
+ } else if (mode == 2) {
+ this.useDefCoordinates = (Boolean)value;
+ }
+ break;
+ case 5:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Dimension Name").allowSetNull());
+ } else if (mode == 1) {
+ if (this.targetDimension == null) {
+ ret = "";
+ } else {
+ ret = new String(this.targetDimension);
+ }
+ } else if (mode == 2) {
+ this.targetDimension = (String)value;
+ if (this.targetDimension.equals("")) {
+ this.targetDimension = null;
+ }
+
+ this.stopLoading();
+ }
+ break;
+ case 6:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Show dialog"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(this.showDialog);
+ } else if (mode == 2) {
+ this.showDialog = (Boolean)value;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 7, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(3, classCookie);
+ super.saveState(s);
+ s.save(this.targetCoords);
+ s.saveFloat(this.targetRot);
+ s.save(this.targetAxis);
+ s.saveString(this.targetRoomName);
+ URL.save(s, this.targetWorldURL);
+ s.saveBoolean(this.useDefCoordinates);
+ s.saveString(this.targetDimension);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ int vers = r.restoreVersion(classCookie);
+ switch (vers) {
+ case 0:
+ super.restoreState(r);
+ this.targetCoords = (Point3)r.restore();
+ this.targetRot = r.restoreInt();
+ this.targetRoomName = r.restoreString();
+ this.targetWorldURL = URL.restore(r, ".world");
+ this.useDefCoordinates = r.restoreBoolean();
+ this.targetDimension = null;
+ break;
+ case 1:
+ case 2:
+ super.restoreState(r);
+ this.targetCoords = (Point3)r.restore();
+ this.targetRot = r.restoreFloat();
+ this.targetAxis = (Point3)r.restore();
+ this.targetRoomName = r.restoreString();
+ this.targetWorldURL = URL.restore(r, ".world");
+ this.useDefCoordinates = r.restoreBoolean();
+ this.targetDimension = null;
+ break;
+ case 3:
+ super.restoreState(r);
+ this.targetCoords = (Point3)r.restore();
+ this.targetRot = r.restoreFloat();
+ this.targetAxis = (Point3)r.restore();
+ this.targetRoomName = r.restoreString();
+ this.targetWorldURL = URL.restore(r, ".world");
+ this.useDefCoordinates = r.restoreBoolean();
+ this.targetDimension = r.restoreString();
+ break;
+ default:
+ throw new TooNewException();
+ }
+
+ if (vers < 2 && this.targetAxis.x == 0.0F && this.targetAxis.y == 0.0F && this.targetAxis.z == 1.0F) {
+ this.targetAxis.z = -1.0F;
+ this.targetRot = 360.0F - this.targetRot;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + "[" + this.asURL() + "]";
+ }
+
+ public String asURL() {
+ String url;
+ if (this.targetWorldURL != null) {
+ url = this.targetWorldURL.getRelativeTo(this) + "#";
+ } else {
+ url = "#";
+ }
+
+ if (this.targetRoomName != null) {
+ url = url + this.targetRoomName;
+ }
+
+ if (this.targetDimension != null) {
+ url = url + "<" + this.targetDimension + ">";
+ }
+
+ if (!this.useDefCoordinates) {
+ url = url + "@" + this.targetCoords + "," + this.targetRot;
+ if (this.targetAxis.x != 0.0F || this.targetAxis.y != 0.0F || this.targetAxis.z != 1.0F) {
+ url = url + "," + this.targetAxis;
+ }
+ }
+
+ return url;
+ }
+}
diff --git a/NET/worlds/scape/TeleportDialog.java b/NET/worlds/scape/TeleportDialog.java
new file mode 100644
index 0000000..7f9d7fc
--- /dev/null
+++ b/NET/worlds/scape/TeleportDialog.java
@@ -0,0 +1,44 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.DialogReceiver;
+import NET.worlds.console.ImageButtons;
+import NET.worlds.console.ImageButtonsCallback;
+import NET.worlds.console.PolledDialog;
+import NET.worlds.core.IniFile;
+import java.awt.Component;
+import java.awt.Rectangle;
+import java.awt.Window;
+
+public class TeleportDialog extends PolledDialog implements ImageButtonsCallback {
+ private ImageButtons ib;
+
+ public TeleportDialog(Window parent, DialogReceiver receiver) {
+ super(parent, receiver, Console.message("Teleporting"), true);
+ Rectangle[] rects = new Rectangle[1];
+ int cancelX = IniFile.override().getIniInt("teleportCancelX", 61);
+ int cancelY = IniFile.override().getIniInt("teleportCancelY", 24);
+ int cancelW = IniFile.override().getIniInt("teleportCancelW", 84);
+ int cancelH = IniFile.override().getIniInt("teleportCancelH", 20);
+ rects[0] = new Rectangle(cancelX, cancelY, cancelW, cancelH);
+ String teleportGif = IniFile.override().getIniString("teleportDlg", Console.message("hangon.gif"));
+ this.ib = new ImageButtons(teleportGif, rects, this);
+ this.ready();
+ }
+
+ @Override
+ protected void build() {
+ this.add("Center", this.ib);
+ }
+
+ @Override
+ public Object imageButtonsCallback(Component who, int which) {
+ this.done(false);
+ return null;
+ }
+
+ @Override
+ public boolean keyDown(java.awt.Event event, int key) {
+ return key == 27 ? this.done(false) : super.keyDown(event, key);
+ }
+}
diff --git a/NET/worlds/scape/TeleportStatus.java b/NET/worlds/scape/TeleportStatus.java
new file mode 100644
index 0000000..0c710e1
--- /dev/null
+++ b/NET/worlds/scape/TeleportStatus.java
@@ -0,0 +1,5 @@
+package NET.worlds.scape;
+
+public interface TeleportStatus {
+ void teleportStatus(String var1, String var2);
+}
diff --git a/NET/worlds/scape/Texture.java b/NET/worlds/scape/Texture.java
new file mode 100644
index 0000000..9850a38
--- /dev/null
+++ b/NET/worlds/scape/Texture.java
@@ -0,0 +1,102 @@
+package NET.worlds.scape;
+
+import NET.worlds.network.URL;
+import java.io.IOException;
+import java.net.MalformedURLException;
+
+public abstract class Texture implements Persister {
+ protected int textureID = 0;
+ int refs = 1;
+ private static Object classCookie = new Object();
+
+ static {
+ nativeInit();
+ }
+
+ protected Texture() {
+ }
+
+ public static native void nativeInit();
+
+ private static native int nativeGetW(int var0);
+
+ public int getW() {
+ return nativeGetW(this.textureID);
+ }
+
+ private static native int nativeGetH(int var0);
+
+ public int getH() {
+ return nativeGetH(this.textureID);
+ }
+
+ public URL getURL() {
+ URL u = null;
+ String s = this.getName();
+ if (s != null) {
+ try {
+ u = new URL(URL.getCurDir(), s);
+ } catch (MalformedURLException var4) {
+ }
+ }
+
+ return u;
+ }
+
+ public void incRef() {
+ assert this.refs > 0;
+
+ if (this.textureID != 0) {
+ this.refs++;
+ }
+ }
+
+ public void copyFrom(int dc, int x1, int x2, int y1, int y2) {
+ assert this.textureID != 0;
+
+ nativeCopyFrom(this.textureID, dc, x1, x2, y1, y2);
+ }
+
+ private static native void nativeCopyFrom(int var0, int var1, int var2, int var3, int var4, int var5);
+
+ private static native void nativeRelease(int var0);
+
+ public synchronized void decRef() {
+ if (--this.refs <= 0 && this.textureID != 0) {
+ nativeRelease(this.textureID);
+ this.textureID = 0;
+ }
+ }
+
+ @Override
+ protected void finalize() {
+ if (this.refs > 0) {
+ this.refs = 1;
+ this.decRef();
+ this.refs = 1000000;
+ }
+ }
+
+ protected String getName() {
+ return null;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(0, classCookie);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+
+ @Override
+ public void postRestore(int version) {
+ }
+}
diff --git a/NET/worlds/scape/TextureDecoder.java b/NET/worlds/scape/TextureDecoder.java
new file mode 100644
index 0000000..42477db
--- /dev/null
+++ b/NET/worlds/scape/TextureDecoder.java
@@ -0,0 +1,73 @@
+package NET.worlds.scape;
+
+import NET.worlds.network.URL;
+import java.io.File;
+import java.util.Hashtable;
+import java.util.StringTokenizer;
+
+public abstract class TextureDecoder {
+ protected static Hashtable handlers = new Hashtable();
+ private static TextureDecoder defaultDecoder;
+ private static String allExts;
+
+ static {
+ addHandler(defaultDecoder = new FileTextureDecoder());
+ addHandler(new StandardTextureDecoder());
+ addHandler(new ScapePicTextureDecoder());
+ }
+
+ protected abstract String getExts();
+
+ protected abstract Texture read(String var1, String var2);
+
+ private static void addHandler(TextureDecoder decoder) {
+ StringTokenizer e = new StringTokenizer(decoder.getExts(), ";");
+
+ while (e.hasMoreTokens()) {
+ String ext = e.nextToken().toLowerCase();
+ handlers.put(ext, decoder);
+ if (allExts == null) {
+ allExts = ext;
+ } else {
+ allExts = allExts + File.pathSeparator + ext;
+ }
+ }
+ }
+
+ public static String getAllExts() {
+ return allExts;
+ }
+
+ public static String getJavaExts() {
+ return new StandardTextureDecoder().getExts();
+ }
+
+ public static Texture decode(URL url, String filename) {
+ return decode(url, url.getAbsolute(), filename);
+ }
+
+ public static Texture decode(URL url, String lookupName, String filename) {
+ Texture tex = FileTexture.dictLookup(lookupName);
+ if (tex != null) {
+ return tex;
+ } else {
+ String urlName = url.getInternal();
+ int delim = urlName.lastIndexOf(46);
+ int lastPath = urlName.lastIndexOf(47);
+ lastPath = Math.max(lastPath, urlName.lastIndexOf(92));
+ lastPath = Math.max(lastPath, urlName.lastIndexOf(58));
+ if (delim > lastPath) {
+ String ext = urlName.substring(delim + 1).toLowerCase();
+ TextureDecoder decoder = (TextureDecoder)handlers.get(ext);
+ if (decoder != null) {
+ Texture t = decoder.read(lookupName, filename);
+ if (t.textureID != 0) {
+ return t;
+ }
+ }
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/NET/worlds/scape/TextureSurface.java b/NET/worlds/scape/TextureSurface.java
new file mode 100644
index 0000000..abdd240
--- /dev/null
+++ b/NET/worlds/scape/TextureSurface.java
@@ -0,0 +1,85 @@
+package NET.worlds.scape;
+
+public class TextureSurface {
+ private Texture[] _textures;
+ private int _hwnd;
+ private int _oldObject;
+ private int _offscreen;
+ private int _texWidth;
+ private int _texHeight;
+ private int _width;
+ private int _height;
+ private int _rows;
+ private int _cols;
+
+ public TextureSurface(Texture[] texList, int rows, int w, int h) {
+ this._width = w;
+ this._height = h;
+ this._oldObject = 0;
+ this._hwnd = this.nativeInit(w, h);
+ this._offscreen = this.nativeMakeDC(this._hwnd, w, h);
+ if (texList != null) {
+ this.setTextures(texList, rows);
+ }
+ }
+
+ @Override
+ public void finalize() {
+ this.nativeDestroyDC(this._offscreen);
+ this._oldObject = 0;
+ }
+
+ public void setTextures(Texture[] texList, int rows) {
+ this._textures = texList;
+ this._rows = rows;
+ this._cols = texList.length / rows;
+ this._texWidth = this._width / this._cols;
+ this._texHeight = this._height / this._rows;
+ }
+
+ public synchronized boolean draw(TextureSurfaceRenderer renderer) {
+ renderer.renderTo(this._offscreen);
+ int idx = 0;
+
+ for (int row = this._rows - 1; row >= 0; row--) {
+ for (int col = 0; col < this._cols; col++) {
+ if (this._textures[idx] != null) {
+ this._textures[idx]
+ .copyFrom(this._offscreen, col * this._texWidth, (col + 1) * this._texWidth, row * this._texHeight, (row + 1) * this._texHeight);
+ }
+
+ idx++;
+ }
+ }
+
+ return false;
+ }
+
+ public void sendLeftClick(int x, int y) {
+ this.nativeLeftClick(this._hwnd, x, y);
+ }
+
+ public int getHwnd() {
+ return this._hwnd;
+ }
+
+ public int getWidth() {
+ return this._width;
+ }
+
+ public int getHeight() {
+ return this._height;
+ }
+
+ private native int nativeInit(int var1, int var2);
+
+ private native int nativeMakeDC(int var1, int var2, int var3);
+
+ private native int nativeGetDC(int var1);
+
+ private native void nativeReleaseDC(int var1, int var2);
+
+ private native void nativeDestroyDC(int var1);
+
+ private native void nativeLeftClick(int var1, int var2, int var3);
+}
diff --git a/NET/worlds/scape/TextureSurfaceRenderer.java b/NET/worlds/scape/TextureSurfaceRenderer.java
new file mode 100644
index 0000000..d374143
--- /dev/null
+++ b/NET/worlds/scape/TextureSurfaceRenderer.java
@@ -0,0 +1,5 @@
+package NET.worlds.scape;
+
+public interface TextureSurfaceRenderer {
+ void renderTo(int var1);
+}
diff --git a/NET/worlds/scape/Toggle.java b/NET/worlds/scape/Toggle.java
new file mode 100644
index 0000000..e70da37
--- /dev/null
+++ b/NET/worlds/scape/Toggle.java
@@ -0,0 +1,165 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import java.io.IOException;
+import java.text.MessageFormat;
+
+public class Toggle extends TriggeredSwitchableBehavior implements Persister, FrameHandler, MouseDownHandler, BumpHandler {
+ protected boolean toggleBumpable;
+ protected boolean toggleVisible;
+ protected WObject o;
+ protected boolean initialized = false;
+
+ public Toggle() {
+ this.trigger = new String("none");
+ this.externalTriggerTag = new String("");
+ this.toggleBumpable = true;
+ this.toggleVisible = true;
+ }
+
+ @Override
+ public void ExternalTrigger(Trigger trigger_source, int sequence_no, int event_no) {
+ this.trigger_source = trigger_source;
+ this.sequence_no = sequence_no;
+ this.event_no = event_no;
+ this.toggle();
+ }
+
+ public void toggle() {
+ if (this.toggleBumpable) {
+ this.o.setBumpable(true);
+ } else {
+ this.o.setBumpable(false);
+ }
+
+ if (this.toggleVisible) {
+ this.o.setVisible(true);
+ } else {
+ this.o.setVisible(false);
+ }
+
+ if (this.trigger_source != null) {
+ this.trigger_source.registerFinishedTriggerTag(this.sequence_no, this.event_no);
+ }
+ }
+
+ @Override
+ public boolean handle(FrameEvent e) {
+ if (!this.initialized) {
+ this.o = e.receiver;
+ this.initialized = true;
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean handle(MouseDownEvent e) {
+ if (this.enabled && this.trigger.equals("click")) {
+ this.toggle();
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean handle(BumpEventTemp e) {
+ if (this.enabled && this.trigger.equals("bump")) {
+ this.toggle();
+ }
+
+ return true;
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Trigger"));
+ } else if (mode == 1) {
+ ret = new String(this.trigger);
+ } else if (mode == 2) {
+ this.trigger = ((String)value).toString().trim();
+ if (this.trigger.equals("external")) {
+ Trigger.TriggeredSwitchableBehaviorList[Trigger.TriggeredSwitchableBehaviorListCount] = this;
+ Trigger.TriggeredSwitchableBehaviorListCount++;
+ }
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "External Trigger Tag"));
+ } else if (mode == 1) {
+ ret = new String(this.externalTriggerTag);
+ } else if (mode == 2) {
+ this.externalTriggerTag = ((String)value).toString().trim();
+ }
+ break;
+ case 2:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Toggle Bumpable"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(this.toggleBumpable);
+ } else if (mode == 2) {
+ this.toggleBumpable = (Boolean)value;
+ }
+ break;
+ case 3:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Toggle Visible"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(this.toggleVisible);
+ } else if (mode == 2) {
+ this.toggleVisible = (Boolean)value;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 4, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + "[" + " enabled " + this.enabled + ", trigger " + this.trigger + ", externalTriggerTag " + this.externalTriggerTag + "]";
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveString(this.trigger);
+ s.saveString(this.externalTriggerTag);
+ s.saveBoolean(this.toggleBumpable);
+ s.saveBoolean(this.toggleVisible);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException {
+ this.trigger = r.restoreString();
+ if (this.trigger.equals("external")) {
+ Trigger.TriggeredSwitchableBehaviorList[Trigger.TriggeredSwitchableBehaviorListCount] = this;
+ Trigger.TriggeredSwitchableBehaviorListCount++;
+ }
+
+ this.externalTriggerTag = r.restoreString();
+ this.toggleBumpable = r.restoreBoolean();
+ this.toggleVisible = r.restoreBoolean();
+ }
+
+ @Override
+ public void postRestore(int version) {
+ String name = this.getName();
+ String arg1 = name == null ? "<null>" : name;
+ SuperRoot owner = this.getOwner();
+ String oname = "";
+ if (owner != null) {
+ oname = owner.getName();
+ }
+
+ String arg2 = oname == null ? "<null>" : oname;
+ Object[] arguments = new Object[]{new String(arg1), new String(arg2)};
+ Console.println(MessageFormat.format(Console.message("Toggle-obs"), arguments));
+ }
+}
diff --git a/NET/worlds/scape/ToggleZoomMode.java b/NET/worlds/scape/ToggleZoomMode.java
new file mode 100644
index 0000000..ffea022
--- /dev/null
+++ b/NET/worlds/scape/ToggleZoomMode.java
@@ -0,0 +1,20 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Window;
+
+public class ToggleZoomMode extends Action {
+ @Override
+ public Persister trigger(Event e, Persister seqID) {
+ if (e.receiver instanceof Pilot && ((Pilot)e.receiver).isActive()) {
+ Window w = Window.getMainWindow();
+ if (w == null) {
+ return null;
+ } else {
+ w.setDeltaMode(!w.getDeltaMode());
+ return null;
+ }
+ } else {
+ return null;
+ }
+ }
+}
diff --git a/NET/worlds/scape/TooNewException.java b/NET/worlds/scape/TooNewException.java
new file mode 100644
index 0000000..1172031
--- /dev/null
+++ b/NET/worlds/scape/TooNewException.java
@@ -0,0 +1,10 @@
+package NET.worlds.scape;
+
+public class TooNewException extends Exception {
+ public TooNewException() {
+ }
+
+ public TooNewException(String s) {
+ super(s);
+ }
+}
diff --git a/NET/worlds/scape/ToolBar.java b/NET/worlds/scape/ToolBar.java
new file mode 100644
index 0000000..ebf0cc9
--- /dev/null
+++ b/NET/worlds/scape/ToolBar.java
@@ -0,0 +1,238 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.DialogDisabled;
+import NET.worlds.console.ExposedPanel;
+import NET.worlds.console.Main;
+import NET.worlds.console.MainCallback;
+import NET.worlds.console.Window;
+import java.awt.Color;
+import java.awt.FlowLayout;
+import java.util.Enumeration;
+import java.util.Vector;
+
+class ToolBar extends ExposedPanel implements MainCallback, DialogDisabled {
+ private Vector buttons = new Vector();
+ private WidgetButton active;
+ private boolean activeDown;
+ private WidgetButton entered;
+ private WObject curWObj;
+ private boolean haveDelta = false;
+ private WObjectHighlighter highlight;
+ private boolean initialDrag;
+ private boolean isDialogDisabled;
+ private boolean testConstrained;
+ private boolean constrainToX;
+ private boolean constrainToY;
+ private int cumx;
+ private int cumy;
+ private float motionDivisor = 1.0F;
+ private static final int constrainThresh = 5;
+
+ public ToolBar() {
+ this.setLayout(new FlowLayout(0, 1, 1));
+ this.addButton(new HTransWidget(this));
+ this.addButton(new VTransWidget(this));
+ this.addButton(new PitchWidget(this));
+ this.addButton(new RollWidget(this));
+ this.addButton(new YawWidget(this));
+ this.addButton(new ScaleWidget(this));
+ this.addButton(new CutWidget(this));
+ this.addButton(new CopyWidget(this));
+ this.addButton(new PasteWidget(this));
+ this.addButton(new SaveWidget(this));
+ this.addButton(new UndoWidget(this));
+ this.setBackground(Color.lightGray);
+ }
+
+ public void done() {
+ if (this.highlight != null) {
+ this.highlight.stop();
+ }
+ }
+
+ private void addButton(WidgetButton button) {
+ this.add(button);
+ this.buttons.addElement(button);
+ }
+
+ public void setCurrentObject(Object obj) {
+ this.curWObj = obj instanceof WObject ? (WObject)obj : null;
+ if (this.highlight != null) {
+ this.highlight.stop();
+ this.highlight = null;
+ }
+
+ if (this.curWObj != null) {
+ this.highlight = new WObjectHighlighter(this.curWObj);
+ }
+
+ Enumeration e = this.buttons.elements();
+ this.clearPrompt();
+
+ while (e.hasMoreElements()) {
+ ((WidgetButton)e.nextElement()).repaint();
+ }
+ }
+
+ public WObject getCurrentWObject() {
+ return this.curWObj;
+ }
+
+ @Override
+ public void dialogDisable(boolean disable) {
+ this.isDialogDisabled = disable;
+ }
+
+ @Override
+ public boolean handleEvent(java.awt.Event event) {
+ return this.isDialogDisabled ? false : super.handleEvent(event);
+ }
+
+ @Override
+ public synchronized boolean mouseDown(java.awt.Event event, int x, int y) {
+ WidgetButton button;
+ if (event.target instanceof WidgetButton && (event.modifiers & 4) == 0 && this.active == null && (button = (WidgetButton)event.target).available()) {
+ this.active = button;
+ this.active.draw(true);
+ if (this.active.usesDrag()) {
+ this.initialDrag = true;
+ this.highlight.stop();
+ Window.hideCursor();
+ Main.register(this);
+ this.haveDelta = true;
+ } else {
+ this.activeDown = true;
+ }
+ }
+
+ return true;
+ }
+
+ @Override
+ public synchronized boolean mouseDrag(java.awt.Event event, int x, int y) {
+ if (this.active != null) {
+ if (this.active.usesDrag()) {
+ if ((event.modifiers & 1) != 0 && !this.constrainToX && !this.constrainToY) {
+ this.testConstrained = true;
+ this.cumx = this.cumy = 0;
+ }
+
+ this.motionDivisor = (event.modifiers & 2) != 0 ? 10.0F : 1.0F;
+ this.haveDelta = true;
+ } else {
+ boolean inside = this.active.getBounds().inside(x, y);
+ if (inside != this.activeDown) {
+ this.active.draw(this.activeDown = inside);
+ }
+ }
+ }
+
+ return true;
+ }
+
+ @Override
+ public synchronized void mainCallback() {
+ if (this.haveDelta && this.active != null) {
+ int[] pos = Window.getHiddenCursorDelta();
+ if (this.testConstrained) {
+ this.cumx = this.cumx + pos[0];
+ this.cumy = this.cumy + pos[1];
+ int acumx = Math.abs(this.cumx);
+ int acumy = Math.abs(this.cumy);
+ if (acumx > acumy + 5) {
+ this.constrainToX = true;
+ } else {
+ if (acumy <= acumx + 5) {
+ return;
+ }
+
+ this.constrainToY = true;
+ }
+
+ this.testConstrained = false;
+ }
+
+ if (this.constrainToX) {
+ pos[0] += this.cumx;
+ this.cumx = 0;
+ pos[1] = 0;
+ } else if (this.constrainToY) {
+ pos[1] += this.cumy;
+ this.cumy = 0;
+ pos[0] = 0;
+ }
+
+ this.setPrompt(this.active.drag(this.initialDrag, pos[0] / this.motionDivisor, -pos[1] / this.motionDivisor));
+ this.initialDrag = false;
+ this.haveDelta = false;
+ }
+ }
+
+ @Override
+ public synchronized boolean mouseUp(java.awt.Event event, int x, int y) {
+ if (this.active != null) {
+ this.active.draw(false);
+ boolean needUpdate = true;
+ if (this.active.usesDrag()) {
+ this.highlight.start();
+ Main.unregister(this);
+ } else if (this.activeDown) {
+ this.active.perform();
+ this.activeDown = false;
+ } else {
+ needUpdate = false;
+ }
+
+ this.active = null;
+ if (needUpdate) {
+ Console.getFrame().getEditTile().update();
+ }
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean mouseEnter(java.awt.Event event, int x, int y) {
+ WidgetButton button;
+ if (this.active == null && event.target instanceof WidgetButton && (button = (WidgetButton)event.target).available()) {
+ this.entered = button;
+ this.setPrompt(this.entered.getPrompt());
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean mouseMove(java.awt.Event event, int x, int y) {
+ return this.mouseEnter(event, x, y);
+ }
+
+ @Override
+ public synchronized boolean keyUp(java.awt.Event event, int key) {
+ if ((event.modifiers & 1) == 0) {
+ this.testConstrained = this.constrainToX = this.constrainToY = false;
+ }
+
+ return true;
+ }
+
+ public void setPrompt(String prompt) {
+ Console.getFrame().getEditTile().setPrompt(prompt);
+ }
+
+ private void clearPrompt() {
+ this.entered = null;
+ Console.getFrame().getEditTile().setPrompt(null);
+ }
+
+ @Override
+ public boolean mouseExit(java.awt.Event event, int x, int y) {
+ if (this.active == null && event.target == this.entered) {
+ this.clearPrompt();
+ }
+
+ return true;
+ }
+}
diff --git a/NET/worlds/scape/ToolTipManager.java b/NET/worlds/scape/ToolTipManager.java
new file mode 100644
index 0000000..e578dd1
--- /dev/null
+++ b/NET/worlds/scape/ToolTipManager.java
@@ -0,0 +1,102 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.DefaultConsole;
+import NET.worlds.console.MultiLineLabel;
+import NET.worlds.core.IniFile;
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Frame;
+import java.awt.Window;
+
+public class ToolTipManager {
+ private static ToolTipManager manager_ = null;
+ private static final int FRAME_DELAY = 15;
+ private int savedX;
+ private int savedY;
+ private int savedLoops;
+ private boolean toolTipActive;
+ private WObject savedObject;
+ private Window toolTipWindow;
+ private MultiLineLabel toolTipTextArea;
+ private Font toolTipFont;
+
+ private ToolTipManager() {
+ this.savedX = this.savedY = this.savedLoops = 0;
+ this.toolTipActive = false;
+ this.savedObject = null;
+ this.toolTipFont = new Font("Arial", 0, 10);
+ Console.getActive();
+ this.toolTipWindow = new Window((Frame)Console.getFrame());
+ this.toolTipTextArea = new MultiLineLabel();
+ this.toolTipTextArea.setBackground(Color.yellow);
+ this.toolTipTextArea.setForeground(Color.black);
+ this.toolTipTextArea.setMarginWidth(2);
+ this.toolTipTextArea.setMarginHeight(2);
+ this.toolTipWindow.setFont(this.toolTipFont);
+ this.toolTipWindow.add(this.toolTipTextArea);
+ }
+
+ public static ToolTipManager toolTipManager() {
+ if (manager_ == null) {
+ manager_ = new ToolTipManager();
+ }
+
+ return manager_;
+ }
+
+ public void heartbeat() {
+ if (IniFile.gamma().getIniInt("DisableToolTips", 0) != 1) {
+ WObject obj = Camera.getMousePickWObject();
+ int x = (int)Camera.getMousePickX();
+ int y = (int)Camera.getMousePickY();
+ if (obj != null && x > 0 && y > 0 && x == this.savedX && y == this.savedY && this.savedObject == obj) {
+ this.savedLoops++;
+ } else {
+ if (this.toolTipActive) {
+ this.removeToolTip();
+ this.toolTipActive = false;
+ }
+
+ this.savedLoops = 0;
+ }
+
+ if (!this.toolTipActive && obj != null && this.savedLoops > 15) {
+ this.toolTipActive = true;
+ if (obj != null) {
+ this.savedObject = obj;
+ if (obj.getToolTipText() != null) {
+ String oldText = obj.getToolTipText();
+ String newText = oldText.replace('|', '\n');
+ this.createToolTip(this.savedX, this.savedY, newText);
+ }
+ }
+ }
+
+ this.savedX = x;
+ this.savedY = y;
+ this.savedObject = obj;
+ }
+ }
+
+ void createToolTip(int winX, int winY, String text) {
+ int baseX = ((DefaultConsole)Console.getActive()).getRender().getLocationOnScreen().x;
+ int baseY = ((DefaultConsole)Console.getActive()).getRender().getLocationOnScreen().y;
+ int offsetX = 16;
+ int offsetY = 16;
+ this.toolTipWindow.setLocation(winX + baseX + offsetX, winY + baseY + offsetY);
+ this.toolTipTextArea.setLabel(text);
+ this.toolTipWindow.setSize(this.toolTipTextArea.preferredSize());
+ this.toolTipWindow.setEnabled(false);
+ this.toolTipWindow.show();
+ }
+
+ public void removeToolTip() {
+ this.toolTipWindow.hide();
+ }
+
+ public void killToolTip() {
+ this.savedLoops = 0;
+ this.toolTipWindow.hide();
+ }
+}
diff --git a/NET/worlds/scape/TradeAction.java b/NET/worlds/scape/TradeAction.java
new file mode 100644
index 0000000..9efc9d3
--- /dev/null
+++ b/NET/worlds/scape/TradeAction.java
@@ -0,0 +1,151 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.Main;
+import NET.worlds.console.MainCallback;
+import NET.worlds.console.OkCancelDialog;
+import NET.worlds.console.PolledDialog;
+import java.io.IOException;
+
+public class TradeAction extends DialogAction {
+ int userItems = 1;
+ String userItem = "A";
+ int serverItems = 1;
+ String serverItem = "A";
+ private static Object classCookie = new Object();
+
+ @Override
+ public void doIt() {
+ StringBuffer deal = new StringBuffer();
+ deal.append("&|+deal>TRADE ");
+ if (this.userItems > 0) {
+ deal.append(this.userItem);
+ deal.append(this.userItems);
+ }
+
+ deal.append(",");
+ if (this.serverItems > 0) {
+ deal.append(this.serverItem);
+ deal.append(this.serverItems);
+ }
+
+ final String dealStr = deal.toString();
+ Main.register(new MainCallback() {
+ @Override
+ public void mainCallback() {
+ Pilot.sendText("TRADE", dealStr);
+ Main.unregister(this);
+ }
+ });
+ }
+
+ @Override
+ public PolledDialog getDialog() {
+ return InventoryManager.getInventoryManager().checkInventoryFor(this.userItem) >= this.userItems
+ ? new OkCancelDialog(
+ Console.getFrame(),
+ this,
+ "Trade?",
+ "No",
+ "Yes",
+ "Do you want to give "
+ + InventoryManager.getInventoryManager().itemName(this.userItem, this.userItems)
+ + " in return for "
+ + InventoryManager.getInventoryManager().itemName(this.serverItem, this.serverItems)
+ + "?",
+ false
+ )
+ : new OkCancelDialog(
+ Console.getFrame(),
+ this,
+ "Can't trade!",
+ "Ok",
+ null,
+ "You need " + InventoryManager.getInventoryManager().itemName(this.userItem, this.userItems) + " in order to trade here.",
+ false
+ );
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "User Item Type"));
+ } else if (mode == 1) {
+ ret = this.userItem;
+ } else if (mode == 2) {
+ this.userItem = ((String)value).toString().trim();
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = IntegerPropertyEditor.make(new Property(this, index, "Number of User Items"));
+ } else if (mode == 1) {
+ ret = new Integer(this.userItems);
+ } else if (mode == 2) {
+ this.userItems = (Integer)value;
+ }
+ break;
+ case 2:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Merchant Item Type"));
+ } else if (mode == 1) {
+ ret = this.serverItem;
+ } else if (mode == 2) {
+ this.serverItem = ((String)value).toString().trim();
+ }
+ break;
+ case 3:
+ if (mode == 0) {
+ ret = IntegerPropertyEditor.make(new Property(this, index, "Number of Merchant Items"));
+ } else if (mode == 1) {
+ ret = new Integer(this.serverItems);
+ } else if (mode == 2) {
+ this.serverItems = (Integer)value;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 4, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public String toString() {
+ return super.toString()
+ + "[give "
+ + InventoryManager.getInventoryManager().itemName(this.userItem, this.userItems)
+ + " for "
+ + InventoryManager.getInventoryManager().itemName(this.serverItem, this.serverItems)
+ + "]";
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(0, classCookie);
+ super.saveState(s);
+ s.saveString(this.userItem);
+ s.saveInt(this.userItems);
+ s.saveString(this.serverItem);
+ s.saveInt(this.serverItems);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ int ver = r.restoreVersion(classCookie);
+ switch (ver) {
+ case 0:
+ super.restoreState(r);
+ this.userItem = r.restoreString();
+ this.userItems = r.restoreInt();
+ this.serverItem = r.restoreString();
+ this.serverItems = r.restoreInt();
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/TrajectoryBehavior.java b/NET/worlds/scape/TrajectoryBehavior.java
new file mode 100644
index 0000000..88abf49
--- /dev/null
+++ b/NET/worlds/scape/TrajectoryBehavior.java
@@ -0,0 +1,305 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+public class TrajectoryBehavior extends SwitchableBehavior implements FrameHandler, BumpHandler {
+ protected Point3 dir;
+ public float linearVel;
+ public Point3 axis;
+ public float angularVel;
+ private RollingAttribute attr;
+ public float linearDamp;
+ public float bounceDamp;
+ public float angularDamp;
+ public float gravity;
+ private long lastTime;
+ private boolean bumplock = false;
+ private static Object classCookie = new Object();
+
+ public TrajectoryBehavior(Point3Temp linearVelocity, float linearDamping, Point3Temp angularAxis, float angularVelocity, float angularDamping) {
+ this.dir = new Point3();
+ this.linearVel = 0.0F;
+ this.linearDamp = linearDamping;
+ this.addVelocity(linearVelocity);
+ this.axis = new Point3(angularAxis);
+ this.axis.normalize();
+ this.angularVel = angularVelocity;
+ this.angularDamp = angularDamping;
+ }
+
+ public TrajectoryBehavior() {
+ this(Point3Temp.make(0.0F, 0.0F, 0.0F));
+ }
+
+ public TrajectoryBehavior(Point3Temp vel) {
+ this(vel, 0.0F, Point3Temp.make(0.0F, 0.0F, 1.0F), 0.0F, 0.0F);
+ }
+
+ public void setDir(Point3Temp d) {
+ double len = Math.sqrt(d.x * d.x + d.y * d.y + d.z * d.z);
+ if (len == 0.0) {
+ this.dir.x = 0.0F;
+ this.dir.y = 0.0F;
+ this.dir.z = 0.0F;
+ } else {
+ this.dir.x = (float)(d.x / len);
+ this.dir.y = (float)(d.y / len);
+ this.dir.z = (float)(d.z / len);
+ }
+ }
+
+ public TrajectoryBehavior addVelocity(Point3Temp vector) {
+ this.dir.times(this.linearVel).plus(vector);
+ float len = this.dir.length();
+ if (len > 0.0F) {
+ this.dir.dividedBy(len);
+ }
+
+ this.linearVel = len;
+ return this;
+ }
+
+ public void setNotifyAttribute(RollingAttribute attr) {
+ this.attr = attr;
+ }
+
+ @Override
+ public boolean handle(FrameEvent e) {
+ this.bumplock = false;
+ WObject o = e.receiver;
+ float dT = (float)(e.time - this.lastTime) / 1000.0F;
+ if (this.lastTime == 0L) {
+ this.lastTime = e.time;
+ return true;
+ } else {
+ this.lastTime = e.time;
+ Room room = o.getRoom();
+ if (o.getZ() > room.floorHeight(o.getX(), o.getY(), o.getZ())) {
+ this.addVelocity(Point3Temp.make(0.0F, 0.0F, -this.gravity * dT));
+ } else if (this.dir.z < 0.0F) {
+ this.dir.z = -this.dir.z;
+ if (this.bounceDamp < 1.0) {
+ this.linearVel = this.linearVel * this.bounceDamp;
+ if (this.linearVel < 0.2 && this.linearVel > -0.2) {
+ this.linearVel = 0.0F;
+ }
+ }
+ }
+
+ if (this.linearVel != 0.0F) {
+ Point3Temp dist = Point3Temp.make(this.dir).times(dT * this.linearVel);
+ o.moveThrough(dist);
+ if (this.linearDamp != 0.0F) {
+ this.linearVel = (float)(this.linearVel * Math.exp(-this.linearDamp * dT));
+ if (Math.abs(this.linearVel) < this.linearDamp * 16.0F) {
+ this.linearVel = 0.0F;
+ if (this.attr != null) {
+ this.attr.notifyStopped();
+ }
+ }
+ }
+ }
+
+ if (this.angularVel != 0.0F) {
+ o.spin(this.axis.x, this.axis.y, this.axis.z, this.angularVel * dT);
+ if (this.angularDamp != 0.0F) {
+ this.angularVel = (float)(this.angularVel * Math.exp(-this.angularDamp * dT));
+ if (Math.abs(this.angularVel) < this.angularDamp * 0.6F) {
+ this.angularVel = 0.0F;
+ }
+ }
+ }
+
+ return true;
+ }
+ }
+
+ @Override
+ public boolean handle(BumpEventTemp b) {
+ if (this.bumplock) {
+ return true;
+ } else {
+ if (this.attr != null) {
+ this.attr.handle(b);
+ } else {
+ this.processBumpEvent(b);
+ }
+
+ this.bumplock = true;
+ return true;
+ }
+ }
+
+ public void processBumpEvent(BumpEventTemp b) {
+ b.postBumpPath.minus(b.postBumpPath);
+ if (this.dir.x != 0.0F || this.dir.y != 0.0F || this.dir.z != 0.0F) {
+ WObject bumper = b.receiver == b.target ? (WObject)b.source : b.target;
+ Point3Temp norm;
+ if (!(bumper instanceof Camera) && !(bumper instanceof Hologram)) {
+ norm = Point3Temp.make(b.bumpNormal);
+ } else {
+ float orientation = (float)((360.0F - bumper.getYaw() + 90.0F) * Math.PI / 180.0);
+ norm = Point3Temp.make((float)Math.cos(orientation), (float)Math.sin(orientation), 0.0F);
+ }
+
+ float lb = (float)Math.sqrt(norm.x * norm.x + norm.y * norm.y + norm.z * norm.z);
+ norm.x /= lb;
+ norm.y /= lb;
+ norm.z /= lb;
+ float projection = Math.abs(this.dir.x * norm.x + this.dir.y * norm.y + this.dir.z * norm.z);
+ this.dir.x = this.dir.x + norm.x * 2.0F * projection;
+ this.dir.y = this.dir.y + norm.y * 2.0F * projection;
+ this.dir.z = this.dir.z + norm.z * 2.0F * projection;
+ double n = Math.sqrt(this.dir.x * this.dir.x + this.dir.y * this.dir.y + this.dir.z * this.dir.z);
+ if (n != 0.0) {
+ this.dir.x = (float)(this.dir.x / n);
+ this.dir.y = (float)(this.dir.y / n);
+ this.dir.z = (float)(this.dir.z / n);
+ }
+
+ if (this.bounceDamp < 1.0) {
+ this.linearVel = this.linearVel * this.bounceDamp;
+ if (this.linearVel < 0.2 && this.linearVel > -0.2) {
+ this.linearVel = 0.0F;
+ }
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ return super.toString()
+ + "["
+ + this.getName()
+ + ": lin. velocity "
+ + this.linearVel
+ + ", lin. damp "
+ + this.linearDamp
+ + ", direction "
+ + this.dir
+ + ", ang. vel "
+ + this.angularVel
+ + ", ang. damp "
+ + this.angularDamp
+ + ", axis "
+ + this.axis
+ + "]";
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Linear Velocity"));
+ } else if (mode == 1) {
+ ret = new Float(this.linearVel);
+ } else if (mode == 2) {
+ this.linearVel = (Float)value;
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Linear Damping"));
+ } else if (mode == 1) {
+ ret = new Float(this.linearDamp);
+ } else if (mode == 2) {
+ this.linearDamp = (Float)value;
+ }
+ break;
+ case 2:
+ if (mode == 0) {
+ ret = Point3PropertyEditor.make(new Property(this, index, "Direction"));
+ } else if (mode == 1) {
+ ret = new Point3(this.dir);
+ } else if (mode == 2) {
+ this.dir = (Point3)value;
+ }
+ break;
+ case 3:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Angular Velocity"));
+ } else if (mode == 1) {
+ ret = new Float(this.angularVel);
+ } else if (mode == 2) {
+ this.angularVel = (Float)value;
+ }
+ break;
+ case 4:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Angular Damping"));
+ } else if (mode == 1) {
+ ret = new Float(this.angularDamp);
+ } else if (mode == 2) {
+ this.angularDamp = (Float)value;
+ }
+ break;
+ case 5:
+ if (mode == 0) {
+ ret = Point3PropertyEditor.make(new Property(this, index, "Axis"));
+ } else if (mode == 1) {
+ ret = new Point3(this.axis);
+ } else if (mode == 2) {
+ this.axis = (Point3)value;
+ }
+ break;
+ case 6:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Gravitational Acceleration"));
+ } else if (mode == 1) {
+ ret = new Float(this.gravity);
+ } else if (mode == 2) {
+ this.gravity = (Float)value;
+ }
+ break;
+ case 7:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Bounce Damping (1 = superball, 0 = beanbag)"));
+ } else if (mode == 1) {
+ ret = new Float(this.bounceDamp);
+ } else if (mode == 2) {
+ this.bounceDamp = (Float)value;
+ this.bounceDamp = (float)Math.max(0.0, Math.min(1.0, (double)this.bounceDamp));
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 8, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(0, classCookie);
+ super.saveState(s);
+ s.saveFloat(this.linearVel);
+ s.saveFloat(this.linearDamp);
+ s.save(this.dir);
+ s.saveFloat(this.angularVel);
+ s.saveFloat(this.angularDamp);
+ s.save(this.axis);
+ s.saveFloat(this.gravity);
+ s.saveFloat(this.bounceDamp);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ this.linearVel = r.restoreFloat();
+ this.linearDamp = r.restoreFloat();
+ this.dir = (Point3)r.restore();
+ this.angularVel = r.restoreFloat();
+ this.angularDamp = r.restoreFloat();
+ this.axis = (Point3)r.restore();
+ this.gravity = r.restoreFloat();
+ this.bounceDamp = r.restoreFloat();
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/TransAttribute.java b/NET/worlds/scape/TransAttribute.java
new file mode 100644
index 0000000..bd74407
--- /dev/null
+++ b/NET/worlds/scape/TransAttribute.java
@@ -0,0 +1,214 @@
+package NET.worlds.scape;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class TransAttribute extends Attribute {
+ private Point3 defPos;
+ private Point3 defRAxis;
+ private float defRotation;
+ private Point3 defScale;
+ private int _sharingMode = 57344;
+ private static Object classCookie = new Object();
+
+ public TransAttribute(int attrID) {
+ super(attrID);
+ }
+
+ public TransAttribute() {
+ }
+
+ @Override
+ protected void noteAddingTo(SuperRoot owner) {
+ WObject w = (WObject)((Sharer)owner).getOwner();
+ w._transformAttribute = this;
+ this.initDefault();
+ }
+
+ @Override
+ public void detach() {
+ WObject w = (WObject)((Sharer)this.getOwner()).getOwner();
+ w._transformAttribute = null;
+ super.detach();
+ }
+
+ @Override
+ public void noteChange() {
+ if (!TCompressor.dontSend) {
+ super.noteChange();
+ }
+ }
+
+ @Override
+ public void generateNetData(DataOutputStream s) throws IOException {
+ WObject w = (WObject)this.getOwner().getOwner();
+ if (this._shorthandVersion == 0) {
+ Point3Temp pos = w.getPosition();
+ s.writeFloat(pos.x);
+ s.writeFloat(pos.y);
+ s.writeFloat(pos.z);
+ Point3Temp scale = w.getScale();
+ s.writeFloat(scale.x);
+ s.writeFloat(scale.y);
+ s.writeFloat(scale.z);
+ } else {
+ this.initDefault();
+ TCompressor.compress(w, this.defPos, this.defRAxis, this.defRotation, this.defScale, this._sharingMode, s);
+ }
+ }
+
+ private void initDefault() {
+ if (this.defPos == null) {
+ WObject w = (WObject)((Sharer)this.getOwner()).getOwner();
+ this.defPos = new Point3(w.getPosition());
+ this.defRAxis = new Point3();
+ this.defRotation = w.getSpin(this.defRAxis);
+ this.defScale = new Point3(w.getScale());
+ }
+ }
+
+ @Override
+ public void setFromNetData(DataInputStream ds, int len) throws IOException {
+ WObject w = (WObject)this.getOwner().getOwner();
+ this.initDefault();
+
+ try {
+ TCompressor.decompress(w, this.defPos, this.defRAxis, this.defRotation, this.defScale, this._sharingMode, len, ds);
+ } catch (IOException var5) {
+ TCompressor.dontSend = false;
+ throw var5;
+ }
+ }
+
+ public boolean getSharingPosition() {
+ return (this._sharingMode & 32768) != 0;
+ }
+
+ public void setSharingPosition(boolean b) {
+ if (b) {
+ this._sharingMode |= 32768;
+ } else {
+ this._sharingMode &= -32769;
+ }
+ }
+
+ public boolean getSharingRotation() {
+ return (this._sharingMode & 16384) != 0;
+ }
+
+ public void setSharingRotation(boolean b) {
+ if (b) {
+ this._sharingMode |= 16384;
+ } else {
+ this._sharingMode &= -16385;
+ }
+ }
+
+ public boolean getSharingScale() {
+ return (this._sharingMode & 8192) != 0;
+ }
+
+ public void setSharingScale(boolean b) {
+ if (b) {
+ this._sharingMode |= 8192;
+ } else {
+ this._sharingMode &= -8193;
+ }
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Share Position"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(this.getSharingPosition());
+ } else if (mode == 2) {
+ this.setSharingPosition((Boolean)value);
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Share Rotation"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(this.getSharingRotation());
+ } else if (mode == 2) {
+ this.setSharingRotation((Boolean)value);
+ }
+ break;
+ case 2:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Share Scale"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(this.getSharingScale());
+ } else if (mode == 2) {
+ this.setSharingScale((Boolean)value);
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 3, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(2, classCookie);
+ super.saveState(s);
+ this.initDefault();
+ s.saveInt(this._sharingMode);
+ s.saveFloat(this.defPos.x);
+ s.saveFloat(this.defPos.y);
+ s.saveFloat(this.defPos.z);
+ s.saveFloat(this.defRAxis.x);
+ s.saveFloat(this.defRAxis.y);
+ s.saveFloat(this.defRAxis.z);
+ s.saveFloat(this.defRotation);
+ s.saveFloat(this.defScale.x);
+ s.saveFloat(this.defScale.y);
+ s.saveFloat(this.defScale.z);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ int vers = r.restoreVersion(classCookie);
+ switch (vers) {
+ case 0:
+ super.restoreState(r);
+ break;
+ case 1:
+ case 2:
+ this.defPos = new Point3();
+ this.defRAxis = new Point3();
+ this.defScale = new Point3();
+ super.restoreState(r);
+ this._sharingMode = r.restoreInt();
+ this.defPos.x = r.restoreFloat();
+ this.defPos.y = r.restoreFloat();
+ this.defPos.z = r.restoreFloat();
+ this.defRAxis.x = r.restoreFloat();
+ this.defRAxis.y = r.restoreFloat();
+ this.defRAxis.z = r.restoreFloat();
+ this.defRotation = r.restoreFloat();
+ this.defScale.x = r.restoreFloat();
+ this.defScale.y = r.restoreFloat();
+ this.defScale.z = r.restoreFloat();
+ break;
+ default:
+ throw new TooNewException();
+ }
+
+ if (vers < 2) {
+ this._shorthandVersion = vers;
+ }
+ }
+
+ @Override
+ public int getMaxShorthandVersion() {
+ return 1;
+ }
+}
diff --git a/NET/worlds/scape/Transform.java b/NET/worlds/scape/Transform.java
new file mode 100644
index 0000000..8b7bc26
--- /dev/null
+++ b/NET/worlds/scape/Transform.java
@@ -0,0 +1,362 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.Main;
+import java.io.IOException;
+import java.util.Vector;
+
+public class Transform extends SuperRoot {
+ private static Vector<Transform> recycled = new Vector<Transform>();
+ private int transformID;
+ private float xScale;
+ private float yScale;
+ private float zScale;
+ private static Object classCookie = new Object();
+
+ static {
+ nativeInit();
+ }
+
+ public static native void nativeInit();
+
+ public static Transform make() {
+ assert Main.isMainThread();
+
+ int last = recycled.size() - 1;
+ if (last == -1) {
+ return new Transform();
+ } else {
+ Transform ret = recycled.elementAt(last);
+ recycled.removeElementAt(last);
+ return ret;
+ }
+ }
+
+ public void recycle() {
+ if (recycled.size() < 100) {
+ this.makeIdentity();
+ recycled.addElement(this);
+ }
+ }
+
+ protected Transform() {
+ this.makeIdentity();
+ }
+
+ public native float getX();
+
+ public native float getY();
+
+ public native float getZ();
+
+ public Point3Temp getPosition() {
+ return Point3Temp.make(this.getX(), this.getY(), this.getZ());
+ }
+
+ public void setZ(float z) {
+ this.moveTo(this.getX(), this.getY(), z);
+ }
+
+ public float getScaleX() {
+ return this.xScale;
+ }
+
+ public float getScaleY() {
+ return this.yScale;
+ }
+
+ public float getScaleZ() {
+ return this.zScale;
+ }
+
+ public Point3Temp getScale() {
+ return Point3Temp.make(this.getScaleX(), this.getScaleY(), this.getScaleZ());
+ }
+
+ public float getTotalScale() {
+ return (this.getScaleX() + this.getScaleY() + this.getScaleZ()) / 3.0F;
+ }
+
+ public native float getYaw();
+
+ public native float getPitch();
+
+ public native float getSpin(Point3Temp var1);
+
+ protected void noteTransformChange() {
+ }
+
+ public Transform raise(float z) {
+ return this.moveBy(0.0F, 0.0F, z);
+ }
+
+ public Transform lower(float z) {
+ return this.moveBy(0.0F, 0.0F, -z);
+ }
+
+ public Transform yaw(float a) {
+ return this.spin(0.0F, 0.0F, 1.0F, a);
+ }
+
+ public Transform roll(float a) {
+ return this.spin(0.0F, 1.0F, 0.0F, a);
+ }
+
+ public Transform pitch(float a) {
+ return this.spin(1.0F, 0.0F, 0.0F, a);
+ }
+
+ public Transform scale(float s) {
+ return this.scale(s, s, s);
+ }
+
+ @Override
+ protected void finalize() {
+ this.nativeFinalize();
+ super.finalize();
+ }
+
+ public native Transform pre(Transform var1);
+
+ public Transform post(Transform t) {
+ Point3Temp v = t.getScale();
+ if (!this.checkPostScale(v)) {
+ return this;
+ } else {
+ this.xScale = this.xScale * v.x;
+ this.yScale = this.yScale * v.y;
+ this.zScale = this.zScale * v.z;
+ return this.postHelper(t);
+ }
+ }
+
+ private boolean checkPostScale(Point3Temp v) {
+ if (this.getSpin(Point3Temp.make()) != 0.0F && (v.x != v.y || v.y != v.z)) {
+ Console.println(Console.message("non-uniform"));
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ private native Transform postHelper(Transform var1);
+
+ public native Transform makeIdentity();
+
+ public Transform moveBy(Point3Temp p) {
+ return this.moveBy(p.x, p.y, p.z);
+ }
+
+ public native Transform moveBy(float var1, float var2, float var3);
+
+ public Transform moveTo(Point3Temp p) {
+ return this.moveTo(p.x, p.y, p.z);
+ }
+
+ public native Transform moveTo(float var1, float var2, float var3);
+
+ public native Transform premoveBy(float var1, float var2, float var3);
+
+ public native Transform scale(float var1, float var2, float var3);
+
+ public Transform scale(Point3Temp s) {
+ return this.scale(s.x, s.y, s.z);
+ }
+
+ public void setScale(float x, float y, float z) {
+ this.scale(x / this.xScale, y / this.yScale, z / this.zScale);
+ }
+
+ public void setScale(Point3Temp s) {
+ this.setScale(s.x, s.y, s.z);
+ }
+
+ public Transform postscale(float x, float y, float z) {
+ return this.postscale(Point3Temp.make(x, y, z));
+ }
+
+ public Transform postscale(Point3Temp s) {
+ if (!this.checkPostScale(s)) {
+ return this;
+ } else {
+ this.xScale = this.xScale * s.x;
+ this.yScale = this.yScale * s.y;
+ this.zScale = this.zScale * s.z;
+ return this.postscaleHelper(s.x, s.y, s.z);
+ }
+ }
+
+ private native Transform postscaleHelper(float var1, float var2, float var3);
+
+ public Transform worldScale(float x, float y, float z) {
+ return this.worldScale(Point3Temp.make(x, y, z));
+ }
+
+ public Transform worldScale(Point3Temp s) {
+ return !this.checkPostScale(s) ? this : this.scale(s);
+ }
+
+ public native Transform spin(float var1, float var2, float var3, float var4);
+
+ public Transform spin(Point3Temp p, float a) {
+ return this.spin(p.x, p.y, p.z, a);
+ }
+
+ public Transform postspin(Point3Temp axis, float a) {
+ return this.postspin(axis.x, axis.y, axis.z, a);
+ }
+
+ public native Transform postspin(float var1, float var2, float var3, float var4);
+
+ public Transform worldSpin(float x, float y, float z, float a) {
+ return this.spin(this.worldVecToObjectVec(Point3Temp.make(x, y, z)), a);
+ }
+
+ private native void nativeFinalize();
+
+ public Transform getTransform() {
+ Transform t = make();
+ t.setTransform(this);
+ return t;
+ }
+
+ public native void setTransform(Transform var1);
+
+ public native Transform invert();
+
+ public Transform getObjectToWorldMatrix() {
+ return this.getTransform();
+ }
+
+ private Point3Temp worldVecToObjectVec(Point3Temp worldVec) {
+ Transform inv = this.getObjectToWorldMatrix().invert();
+ Point3Temp p = Point3Temp.make(worldVec).vectorTimes(inv).times(this.getScale());
+ inv.recycle();
+ return p;
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = TransformPropertyEditor.make(new Property(this, index, "Transform"));
+ } else if (mode == 1) {
+ ret = this.getTransform();
+ } else if (mode == 2) {
+ this.setTransform((Transform)value);
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 1, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(2, classCookie);
+ super.saveState(s);
+ s.saveFloat(this.xScale);
+ s.saveFloat(this.yScale);
+ s.saveFloat(this.zScale);
+ float[] guts = this.getGuts();
+
+ for (int i = 0; i < 16; i++) {
+ s.saveFloat(guts[i]);
+ }
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 1:
+ super.restoreState(r);
+ case 0:
+ this.xScale = this.yScale = this.zScale = r.restoreFloat();
+ float[] guts = new float[16];
+
+ for (int i = 0; i < 16; i++) {
+ guts[i] = r.restoreFloat();
+ }
+
+ this.setGuts(guts);
+ break;
+ case 2:
+ super.restoreState(r);
+ this.xScale = r.restoreFloat();
+ this.yScale = r.restoreFloat();
+ this.zScale = r.restoreFloat();
+ float[] guts = new float[16];
+
+ for (int i = 0; i < 16; i++) {
+ guts[i] = r.restoreFloat();
+ }
+
+ this.setGuts(guts);
+ break;
+ default:
+ throw new TooNewException();
+ }
+ }
+
+ private native float[] getGuts();
+
+ public native boolean isTransformEqual(Transform var1);
+
+ private native void setGuts(float[] var1);
+
+ public String toTransformSubstring() {
+ Point3Temp axis = Point3Temp.make();
+ float angle = this.getSpin(axis);
+ Point3Temp pos = this.getPosition();
+ return angle == 0.0F && this.xScale == 1.0F && this.yScale == 1.0F && this.zScale == 1.0F && pos.x == 0.0F && pos.y == 0.0F && pos.z == 0.0F
+ ? "[identity]"
+ : "[pos ("
+ + pos
+ + "), scale ("
+ + (this.xScale == this.yScale && this.yScale == this.zScale ? "" + this.xScale : this.xScale + "," + this.yScale + "," + this.zScale)
+ + "), rot ("
+ + axis
+ + "@"
+ + angle
+ + ")]";
+ }
+
+ @Override
+ public String toString() {
+ return this.getName() + this.toTransformSubstring();
+ }
+
+ public Transform printGuts() {
+ float[] arr = this.getGuts();
+
+ assert arr.length == 16;
+
+ String[] strs = new String[16];
+ int maxStr = 0;
+
+ for (int i = 0; i < 16; i++) {
+ strs[i] = Float.toString(arr[i]);
+ maxStr = Math.max(maxStr, strs[i].length());
+ }
+
+ for (int j = 0; j < 4; j++) {
+ for (int k = 0; k < 4; k++) {
+ String s = strs[j * 4 + k];
+ int pad = maxStr - s.length() + 1;
+ System.out.print(s);
+
+ while (pad-- != 0) {
+ System.out.print(" ");
+ }
+ }
+
+ System.out.println("");
+ }
+
+ return this;
+ }
+}
diff --git a/NET/worlds/scape/TransformEditorDialog.java b/NET/worlds/scape/TransformEditorDialog.java
new file mode 100644
index 0000000..d7b5a21
--- /dev/null
+++ b/NET/worlds/scape/TransformEditorDialog.java
@@ -0,0 +1,341 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.ConfirmDialog;
+import NET.worlds.console.Console;
+import NET.worlds.console.DialogReceiver;
+import NET.worlds.console.PolledDialog;
+import java.awt.Button;
+import java.awt.Component;
+import java.awt.Font;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Label;
+import java.awt.TextField;
+import java.text.MessageFormat;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+class TransformEditorDialog extends PolledDialog implements DialogReceiver {
+ Property property;
+ Transform transform;
+ int undoCount;
+ Button undoButton = new Button(Console.message("Undo"));
+ Button okButton = new Button(Console.message("OK"));
+ Button cancelButton = new Button(Console.message("Cancel"));
+ Button pitch = new MyButton(Console.message("Pitch-N"), 0, 1);
+ Button roll = new MyButton(Console.message("Roll-N"), 0, 1);
+ Button yaw = new MyButton(Console.message("Yaw-N"), 0, 1);
+ Button spin = new MyButton(Console.message("Spin-by-XYZN"), 3, 1);
+ Button spinTo = new MyButton(Console.message("Spin-to-XYZN"), 3, 1);
+ Button moveX = new MyButton(Console.message("Move-x-by-N"), 0, 1);
+ Button moveY = new MyButton(Console.message("Move-y-by-N"), 0, 1);
+ Button moveZ = new MyButton(Console.message("Move-z-by-N"), 0, 1);
+ Button moveBy = new MyButton(Console.message("Move-by-XYZ"), 3, 0);
+ Button moveTo = new MyButton(Console.message("Move-to-XYZ"), 3, 0);
+ Button scaleX = new MyButton(Console.message("Scale-x-by-N"), 0, 1);
+ Button scaleY = new MyButton(Console.message("Scale-y-by-N"), 0, 1);
+ Button scaleZ = new MyButton(Console.message("Scale-z-by-N"), 0, 1);
+ Button scaleBy = new MyButton(Console.message("Scale-by-N"), 0, 1);
+ Button scaleTo = new MyButton(Console.message("Scale-to-N"), 0, 1);
+ Label position = new Label();
+ Label rotation = new Label();
+ Label scale = new Label();
+ TextField editXYZ = new TextField();
+ TextField editN = new TextField();
+ GridBagLayout gbag = new GridBagLayout();
+ GridBagConstraints c = new GridBagConstraints();
+ Font normalFont;
+ Font selectedFont;
+ Button selectedButton;
+ TextField lastEdit;
+ EditTile parent;
+ Object queuedFunc;
+ private static Object lastPosAndSize;
+
+ TransformEditorDialog(EditTile parent, String title, Property property) {
+ super(Console.getFrame(), parent, title, false);
+ this.property = property;
+ this.parent = parent;
+ this.ready();
+ }
+
+ @Override
+ protected void build() {
+ this.transform = (Transform)this.property.get();
+ this.setLayout(this.gbag);
+ this.add2(new Label("(X,Y,Z):"), this.editXYZ);
+ this.add2(new Label("(N):"), this.editN);
+ this.add3(this.moveX, this.pitch, this.scaleX);
+ this.add3(this.moveY, this.roll, this.scaleY);
+ this.add3(this.moveZ, this.yaw, this.scaleZ);
+ this.add3(this.moveBy, this.spin, this.scaleBy);
+ this.add3(this.moveTo, this.spinTo, this.scaleTo);
+ this.add2(new Label(Console.message("Position")), this.position);
+ this.add2(new Label(Console.message("Rotation:")), this.rotation);
+ this.add2(new Label(Console.message("Scale:")), this.scale);
+ this.addButtons(this.undoButton, this.okButton, this.cancelButton);
+ this.normalFont = this.pitch.getFont();
+ this.selectedFont = new Font(this.normalFont.getName(), this.normalFont.isBold() ? 0 : 1, this.normalFont.getSize());
+ this.updateInfo();
+ }
+
+ private void add2(Component c1, Component c2) {
+ this.c.fill = 0;
+ this.c.anchor = 13;
+ this.c.gridheight = 1;
+ this.c.weightx = 1.0;
+ this.c.weighty = 1.0;
+ this.c.gridwidth = 1;
+ this.add(this.gbag, c1, this.c);
+ this.c.anchor = 17;
+ this.c.fill = 2;
+ this.c.gridwidth = 0;
+ this.add(this.gbag, c2, this.c);
+ }
+
+ private void add3(Component c1, Component c2, Component c3) {
+ this.c.fill = 2;
+ this.c.anchor = 17;
+ this.c.gridheight = 1;
+ this.c.gridwidth = 3;
+ this.c.weightx = 1.0;
+ this.c.weighty = 1.0;
+ this.add(this.gbag, c1, this.c);
+ this.c.weightx = 0.0;
+ this.c.weighty = 0.0;
+ this.add(this.gbag, c2, this.c);
+ this.c.gridwidth = 0;
+ this.add(this.gbag, c3, this.c);
+ }
+
+ private void addButtons(Component c1, Component c2, Component c3) {
+ this.c.fill = 0;
+ this.c.anchor = 13;
+ this.c.gridheight = 1;
+ this.c.gridwidth = 3;
+ this.c.weightx = 1.0;
+ this.c.weighty = 1.0;
+ this.add(this.gbag, c1, this.c);
+ this.c.anchor = 10;
+ this.add(this.gbag, c2, this.c);
+ this.c.anchor = 17;
+ this.add(this.gbag, c3, this.c);
+ }
+
+ private void selectButton(Button button) {
+ if (this.selectedButton != null) {
+ this.selectedButton.setFont(this.normalFont);
+ }
+
+ this.selectedButton = button;
+ this.selectedButton.setFont(this.selectedFont);
+ }
+
+ private void updateInfo() {
+ this.position.setText(this.transform.getPosition().toString());
+ this.scale.setText(this.transform.getScale().toString());
+ Point3Temp axis = Point3Temp.make();
+ float angle = this.transform.getSpin(axis);
+ Object[] arguments = new Object[]{new String("" + axis), new String("" + angle)};
+ this.rotation.setText(MessageFormat.format(Console.message("angle"), arguments));
+ this.undoButton.enable(this.undoCount != 0);
+ }
+
+ private void set(Transform t) {
+ this.parent.addUndoableSet(this.property, t);
+ this.undoCount++;
+ this.transform = (Transform)this.property.get();
+ }
+
+ @Override
+ protected synchronized void activeCallback() {
+ if (this.queuedFunc == this.undoButton) {
+ if (this.undoCount != 0) {
+ this.parent.undo();
+ this.undoCount--;
+ this.transform = (Transform)this.property.get();
+ this.updateInfo();
+ }
+ } else if (this.queuedFunc instanceof MyButton) {
+ this.apply((MyButton)this.queuedFunc);
+ }
+
+ this.queuedFunc = null;
+ }
+
+ public boolean undoAll() {
+ if (this.undoCount == 0) {
+ return this.done(false);
+ } else {
+ new ConfirmDialog(this, Console.message("Cancel-Transform"), Console.message("undo-changes"));
+ return true;
+ }
+ }
+
+ @Override
+ public synchronized void dialogDone(Object who, boolean confirmed) {
+ if (confirmed) {
+ while (this.undoCount != 0) {
+ this.parent.undo();
+ this.undoCount--;
+ }
+
+ this.done(false);
+ }
+ }
+
+ @Override
+ public synchronized boolean action(java.awt.Event event, Object what) {
+ Object target = event.target;
+ if (target == this.okButton) {
+ return this.done(true);
+ } else if (target == this.cancelButton) {
+ return this.undoAll();
+ } else if ((target == this.undoButton || target instanceof MyButton) && this.queuedFunc == null) {
+ this.queuedFunc = target;
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ private float[] parseNumbers(TextField edit) {
+ Vector vec = new Vector();
+ StringTokenizer e = new StringTokenizer(edit.getText().trim(), ", \t", false);
+
+ while (e.hasMoreElements()) {
+ try {
+ vec.addElement(Float.valueOf(e.nextToken()));
+ } catch (NumberFormatException var6) {
+ vec.removeAllElements();
+ break;
+ }
+ }
+
+ float[] ret = new float[vec.size()];
+
+ for (int i = 0; i < ret.length; i++) {
+ ret[i] = (Float)vec.elementAt(i);
+ }
+
+ return ret;
+ }
+
+ private boolean apply(MyButton func) {
+ float[] n = this.parseNumbers(this.editN);
+ float[] xyz = this.parseNumbers(this.editXYZ);
+ if (func.numParamsXYZ != 0 && func.numParamsXYZ != xyz.length) {
+ return this.setEdit(this.editXYZ);
+ } else if (func.numParamsN != 0 && func.numParamsN != n.length) {
+ return this.setEdit(this.editN);
+ } else {
+ if (func == this.pitch) {
+ this.transform.worldSpin(1.0F, 0.0F, 0.0F, n[0]);
+ } else if (func == this.roll) {
+ this.transform.worldSpin(0.0F, 1.0F, 0.0F, n[0]);
+ } else if (func == this.yaw) {
+ this.transform.worldSpin(0.0F, 0.0F, 1.0F, n[0]);
+ } else if (func == this.spin) {
+ this.transform.worldSpin(xyz[0], xyz[1], xyz[2], n[0]);
+ } else if (func == this.spinTo) {
+ Point3Temp scale = this.transform.getScale();
+ Point3Temp pos = this.transform.getPosition();
+ this.transform.makeIdentity();
+ this.transform.scale(scale);
+ this.transform.worldSpin(xyz[0], xyz[1], xyz[2], n[0]);
+ this.transform.moveTo(pos.x, pos.y, pos.z);
+ } else if (func == this.moveX) {
+ this.transform.moveBy(n[0], 0.0F, 0.0F);
+ } else if (func == this.moveY) {
+ this.transform.moveBy(0.0F, n[0], 0.0F);
+ } else if (func == this.moveZ) {
+ this.transform.moveBy(0.0F, 0.0F, n[0]);
+ } else if (func == this.moveBy) {
+ this.transform.moveBy(xyz[0], xyz[1], xyz[2]);
+ } else if (func == this.moveTo) {
+ this.transform.moveTo(xyz[0], xyz[1], xyz[2]);
+ } else if (func == this.scaleX && n[0] != 0.0F && this.checkScale(n[0], this.transform.getScaleX())) {
+ this.transform.scale(n[0], 1.0F, 1.0F);
+ } else if (func == this.scaleY && n[0] != 0.0F && this.checkScale(n[0], this.transform.getScaleY())) {
+ this.transform.scale(1.0F, n[0], 1.0F);
+ } else if (func == this.scaleZ && n[0] != 0.0F && this.checkScale(n[0], this.transform.getScaleZ())) {
+ this.transform.scale(1.0F, 1.0F, n[0]);
+ } else if (func == this.scaleBy
+ && n[0] != 0.0F
+ && this.checkScale(n[0], this.transform.getScaleX())
+ && this.checkScale(n[0], this.transform.getScaleY())
+ && this.checkScale(n[0], this.transform.getScaleZ())) {
+ this.transform.scale(n[0]);
+ } else {
+ if (func != this.scaleTo || n[0] == 0.0F) {
+ return true;
+ }
+
+ Point3Temp scale = this.transform.getScale();
+ this.transform.scale(n[0] / scale.x, n[0] / scale.y, n[0] / scale.z);
+ }
+
+ this.set(this.transform);
+ this.selectButton(func);
+ this.updateInfo();
+ return this.setEdit(this.lastEdit);
+ }
+ }
+
+ private boolean checkScale(float oldScale, float factor) {
+ double newScale = (double)oldScale * factor;
+ if (newScale < 2.938736052218037E-39) {
+ Console.println(Console.message("exceed-minimum"));
+ } else {
+ if (!(newScale > Float.MAX_VALUE)) {
+ return true;
+ }
+
+ Console.println(Console.message("exceed-maximum"));
+ }
+
+ return false;
+ }
+
+ private boolean toggleEdit() {
+ return this.lastEdit == this.editN ? this.setEdit(this.editXYZ) : this.setEdit(this.editN);
+ }
+
+ private boolean setEdit(TextField edit) {
+ edit.requestFocus();
+ edit.selectAll();
+ this.lastEdit = edit;
+ return true;
+ }
+
+ @Override
+ public boolean keyDown(java.awt.Event event, int key) {
+ if (event.target == this.editXYZ || event.target == this.editN) {
+ this.lastEdit = (TextField)event.target;
+ }
+
+ if (key == 27) {
+ return this.undoAll();
+ } else if (key == 10) {
+ return this.done(true);
+ } else {
+ return key == 9 ? this.toggleEdit() : super.keyDown(event, key);
+ }
+ }
+
+ @Override
+ public void show() {
+ super.show();
+ this.setEdit(this.editXYZ);
+ }
+
+ @Override
+ public void savePosAndSize(Object state) {
+ lastPosAndSize = state;
+ }
+
+ @Override
+ public Object restorePosAndSize() {
+ return lastPosAndSize;
+ }
+}
diff --git a/NET/worlds/scape/TransformPropertyEditor.java b/NET/worlds/scape/TransformPropertyEditor.java
new file mode 100644
index 0000000..22ec6ef
--- /dev/null
+++ b/NET/worlds/scape/TransformPropertyEditor.java
@@ -0,0 +1,19 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.PolledDialog;
+
+public class TransformPropertyEditor extends PropEditor {
+ private TransformPropertyEditor(Property property) {
+ super(property);
+ }
+
+ @Override
+ public PolledDialog edit(EditTile parent, String title) {
+ return new TransformEditorDialog(parent, title, this.property);
+ }
+
+ public static Property make(Property property) {
+ property.setPropertyType(9);
+ return property.setEditor(new TransformPropertyEditor(property));
+ }
+}
diff --git a/NET/worlds/scape/Trigger.java b/NET/worlds/scape/Trigger.java
new file mode 100644
index 0000000..a056535
--- /dev/null
+++ b/NET/worlds/scape/Trigger.java
@@ -0,0 +1,199 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import java.io.IOException;
+import java.text.MessageFormat;
+
+public class Trigger extends SwitchableBehavior implements FrameHandler, Persister, MouseDownHandler, BumpHandler {
+ public static TriggeredSwitchableBehavior[] TriggeredSwitchableBehaviorList = new TriggeredSwitchableBehavior[1000];
+ public static int TriggeredSwitchableBehaviorListCount = 0;
+ public String trigger = new String("none");
+ public String targetTriggerTag = new String("");
+ public String[][] targetTriggerTagArray = new String[20][10];
+ public int targetTriggerTagCount = 0;
+ public int[] finishedTriggerTagSequenceNo = new int[50];
+ public int[] finishedTriggerTagEventNo = new int[50];
+ public int finishedTriggerTagCount = 0;
+
+ private void addTargetTriggerTagArray(String[] sequentialTargetTriggerTagArray, String targetTriggerTag) {
+ int currentIndex = 1;
+ int currentSeparator = 0;
+ int nextSeparator = 0;
+ int lastSeparator = targetTriggerTag.lastIndexOf("+");
+ if (lastSeparator == -1 && targetTriggerTag.length() == 0) {
+ int var8 = 0;
+ sequentialTargetTriggerTagArray[0] = String.valueOf((int)var8);
+ } else if (lastSeparator == -1) {
+ sequentialTargetTriggerTagArray[currentIndex] = targetTriggerTag;
+ sequentialTargetTriggerTagArray[0] = String.valueOf(currentIndex);
+ } else {
+ nextSeparator = targetTriggerTag.indexOf("+");
+ sequentialTargetTriggerTagArray[currentIndex] = targetTriggerTag.substring(0, nextSeparator);
+ currentIndex++;
+
+ while (nextSeparator != lastSeparator) {
+ currentSeparator = nextSeparator;
+ nextSeparator = targetTriggerTag.indexOf("+", nextSeparator + 1);
+ sequentialTargetTriggerTagArray[currentIndex] = targetTriggerTag.substring(currentSeparator + 1, nextSeparator);
+ currentIndex++;
+ }
+
+ sequentialTargetTriggerTagArray[currentIndex] = targetTriggerTag.substring(nextSeparator + 1);
+ sequentialTargetTriggerTagArray[0] = String.valueOf(currentIndex);
+ }
+ }
+
+ public void preprocessTargetTriggerTag(String targetTriggerTag) {
+ int currentIndex = 1;
+ int currentSeparator = 0;
+ int nextSeparator = 0;
+ int lastSeparator = targetTriggerTag.lastIndexOf(" ");
+ if (lastSeparator != -1 || targetTriggerTag.length() != 0) {
+ if (lastSeparator == -1) {
+ this.addTargetTriggerTagArray(this.targetTriggerTagArray[currentIndex], targetTriggerTag);
+ this.targetTriggerTagCount = currentIndex;
+ } else {
+ nextSeparator = targetTriggerTag.indexOf(" ");
+ this.addTargetTriggerTagArray(this.targetTriggerTagArray[currentIndex], targetTriggerTag.substring(0, nextSeparator));
+ currentIndex++;
+
+ while (nextSeparator != lastSeparator) {
+ currentSeparator = nextSeparator;
+ nextSeparator = targetTriggerTag.indexOf(" ", nextSeparator + 1);
+ this.addTargetTriggerTagArray(this.targetTriggerTagArray[currentIndex], targetTriggerTag.substring(currentSeparator + 1, nextSeparator));
+ currentIndex++;
+ }
+
+ this.addTargetTriggerTagArray(this.targetTriggerTagArray[currentIndex], targetTriggerTag.substring(nextSeparator + 1));
+ this.targetTriggerTagCount = currentIndex;
+ }
+ }
+ }
+
+ public void activateTrigger() {
+ for (int j = 1; j <= this.targetTriggerTagCount; j++) {
+ boolean match = false;
+
+ for (int i = 0; !match && i < TriggeredSwitchableBehaviorListCount; i++) {
+ if (this.targetTriggerTagArray[j][1].equals(TriggeredSwitchableBehaviorList[i].externalTriggerTag) && TriggeredSwitchableBehaviorList[i] != null) {
+ TriggeredSwitchableBehaviorList[i].ExternalTrigger(this, j, 1);
+ }
+ }
+ }
+ }
+
+ public void activateSequenceTrigger() {
+ for (int j = this.finishedTriggerTagCount; j > 0; j--) {
+ int sequence_no = this.finishedTriggerTagSequenceNo[j];
+ int event_no = this.finishedTriggerTagEventNo[j];
+ if (Integer.valueOf(this.targetTriggerTagArray[sequence_no][0]) > event_no) {
+ boolean match = false;
+
+ for (int i = 0; !match && i < TriggeredSwitchableBehaviorListCount; i++) {
+ if (this.targetTriggerTagArray[sequence_no][event_no + 1].equals(TriggeredSwitchableBehaviorList[i].externalTriggerTag)
+ && TriggeredSwitchableBehaviorList[i] != null) {
+ TriggeredSwitchableBehaviorList[i].ExternalTrigger(this, sequence_no, event_no + 1);
+ }
+ }
+ }
+ }
+
+ this.finishedTriggerTagCount = 0;
+ }
+
+ public synchronized void registerFinishedTriggerTag(int sequence_no, int event_no) {
+ this.finishedTriggerTagCount++;
+ this.finishedTriggerTagSequenceNo[this.finishedTriggerTagCount] = sequence_no;
+ this.finishedTriggerTagEventNo[this.finishedTriggerTagCount] = event_no;
+ }
+
+ @Override
+ public boolean handle(FrameEvent e) {
+ if (this.enabled && this.finishedTriggerTagCount > 0) {
+ this.activateSequenceTrigger();
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean handle(MouseDownEvent e) {
+ if (this.enabled && this.trigger.equals("click")) {
+ this.activateTrigger();
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean handle(BumpEventTemp e) {
+ if (this.enabled && this.trigger.equals("bump")) {
+ this.activateTrigger();
+ }
+
+ return true;
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Trigger"));
+ } else if (mode == 1) {
+ ret = new String(this.trigger);
+ } else if (mode == 2) {
+ this.trigger = ((String)value).toString().trim();
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Target Trigger Tag"));
+ } else if (mode == 1) {
+ ret = new String(this.targetTriggerTag);
+ } else if (mode == 2) {
+ this.targetTriggerTag = ((String)value).toString().trim();
+ this.preprocessTargetTriggerTag(this.targetTriggerTag);
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 2, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + "[enabled " + this.enabled + ", trigger " + this.trigger + ", targetTriggerTag " + this.targetTriggerTag + "]";
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveString(this.trigger);
+ s.saveString(this.targetTriggerTag);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException {
+ this.trigger = r.restoreString();
+ this.targetTriggerTag = r.restoreString();
+ this.preprocessTargetTriggerTag(this.targetTriggerTag);
+ }
+
+ @Override
+ public void postRestore(int version) {
+ String name = this.getName();
+ String arg1 = name == null ? "<null>" : name;
+ SuperRoot owner = this.getOwner();
+ String oname = "";
+ if (owner != null) {
+ oname = owner.getName();
+ }
+
+ String arg2 = oname == null ? "<null>" : oname;
+ Object[] arguments = new Object[]{new String(arg1), new String(arg2)};
+ Console.println(MessageFormat.format(Console.message("Trigger-obs"), arguments));
+ }
+}
diff --git a/NET/worlds/scape/TriggeredSwitchableBehavior.java b/NET/worlds/scape/TriggeredSwitchableBehavior.java
new file mode 100644
index 0000000..07d73b8
--- /dev/null
+++ b/NET/worlds/scape/TriggeredSwitchableBehavior.java
@@ -0,0 +1,11 @@
+package NET.worlds.scape;
+
+public abstract class TriggeredSwitchableBehavior extends SwitchableBehavior {
+ public String trigger;
+ public String externalTriggerTag;
+ public int sequence_no;
+ public int event_no;
+ Trigger trigger_source = null;
+
+ public abstract void ExternalTrigger(Trigger var1, int var2, int var3);
+}
diff --git a/NET/worlds/scape/TwoWayPortal.java b/NET/worlds/scape/TwoWayPortal.java
new file mode 100644
index 0000000..c9c3b0c
--- /dev/null
+++ b/NET/worlds/scape/TwoWayPortal.java
@@ -0,0 +1,64 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+public class TwoWayPortal extends Portal {
+ private static Object classCookie = new Object();
+
+ public TwoWayPortal(String targetRoom, float llx, float lly, float llz, float urx, float ury, float urz) {
+ super(llx, lly, llz, urx, ury, urz);
+ this.setFarSideInfo(null, targetRoom, null);
+ }
+
+ public TwoWayPortal() {
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(0, classCookie);
+ super.saveState(s);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ int vers = r.restoreVersion(classCookie);
+ switch (vers) {
+ case 0:
+ super.restoreState(r);
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+
+ @Override
+ public void detach() throws ClassCastException {
+ super.detach();
+ Portal p = this.farSide();
+ if (p != null) {
+ p.detach();
+ }
+ }
+
+ @Override
+ public void reset(boolean showmessage) {
+ super.reset(showmessage);
+ if (this.farSideRoom() != null) {
+ Portal p = this.farSide();
+ if (p != null) {
+ if (p.isActive()) {
+ return;
+ }
+
+ p.detach();
+ this.bidisconnect();
+ }
+
+ Point3Temp left = this.getWorldPosition();
+ Point3Temp right = this.getFarCorner();
+ p = new Portal(right.x, right.y, left.z, left.x, left.y, right.z);
+ this.farSideRoom().add(p);
+ this.biconnect(p);
+ }
+ }
+}
diff --git a/NET/worlds/scape/URLEditorDialog.java b/NET/worlds/scape/URLEditorDialog.java
new file mode 100644
index 0000000..034ccdd
--- /dev/null
+++ b/NET/worlds/scape/URLEditorDialog.java
@@ -0,0 +1,54 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.network.URL;
+import java.net.MalformedURLException;
+import java.util.Vector;
+
+class URLEditorDialog extends FieldWithListEditorDialog {
+ Property property;
+ FileList extChecker;
+
+ URLEditorDialog(EditTile parent, String title, Property property, Vector files, FileList extChecker) {
+ super(parent, title + " dir: " + URL.getBestContainer((SuperRoot)property.getOwner()), files);
+ this.property = property;
+ this.extChecker = extChecker;
+ this.ready();
+ }
+
+ @Override
+ protected String getValue() {
+ SuperRoot context = (SuperRoot)this.property.getOwner();
+ if (context != null && this.property.getName().equals("Source URL")) {
+ context = context.getOwner();
+ }
+
+ String s = URL.getRelativeTo((URL)this.property.get(), context);
+ return s == null ? "" : s;
+ }
+
+ @Override
+ protected boolean setValue(String text) {
+ URL url = null;
+ if (text.length() == 0) {
+ if (!this.property.canSetNull()) {
+ return false;
+ }
+ } else {
+ if (this.extChecker != null && !this.extChecker.extMatches(text)) {
+ Console.println(Console.message("extension-match") + this.extChecker.getExtList());
+ return false;
+ }
+
+ try {
+ url = new URL((SuperRoot)this.property.getOwner(), text);
+ } catch (MalformedURLException var4) {
+ Console.println(Console.message("Illegal-URL") + var4);
+ return false;
+ }
+ }
+
+ this.parent.addUndoableSet(this.property, url);
+ return true;
+ }
+}
diff --git a/NET/worlds/scape/URLPropertyEditor.java b/NET/worlds/scape/URLPropertyEditor.java
new file mode 100644
index 0000000..2a346c1
--- /dev/null
+++ b/NET/worlds/scape/URLPropertyEditor.java
@@ -0,0 +1,73 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.PolledDialog;
+import NET.worlds.network.URL;
+import java.util.Enumeration;
+import java.util.Vector;
+
+public class URLPropertyEditor extends PropEditor {
+ private FileList files;
+ private Enumeration additions;
+ private boolean acceptAnyExt = false;
+ private boolean acceptDrops;
+
+ private URLPropertyEditor(Property property, String extList, Enumeration additions, boolean acceptDrops) {
+ super(property);
+ this.acceptDrops = acceptDrops;
+ URL dir = URL.getContainingOrCurDir((SuperRoot)property.getOwner());
+ if (extList == null) {
+ this.acceptAnyExt = true;
+ } else {
+ if (extList.startsWith("*")) {
+ extList = extList.substring(1);
+ this.acceptAnyExt = true;
+ }
+
+ this.files = new FileList(dir.unalias(), extList);
+ }
+
+ this.additions = additions;
+ }
+
+ @Override
+ public PolledDialog edit(EditTile parent, String title) {
+ Vector v = this.files == null ? new Vector() : this.files.getList();
+ if (this.additions != null) {
+ while (this.additions.hasMoreElements()) {
+ v.addElement(this.additions.nextElement().toString());
+ }
+ }
+
+ return new URLEditorDialog(parent, title, this.property, v, this.acceptAnyExt ? null : this.files);
+ }
+
+ public static Property make(Property property, String extList) {
+ return make(property, extList, null, true);
+ }
+
+ public static Property make(Property property, String extList, boolean acceptDrops) {
+ return make(property, extList, null, acceptDrops);
+ }
+
+ public static Property make(Property property, String extList, Enumeration additions) {
+ return make(property, extList, additions, true);
+ }
+
+ public static Property make(Property property, String extList, Enumeration additions, boolean acceptDrops) {
+ property.setPropertyType(10);
+ return property.setEditor(new URLPropertyEditor(property, extList, additions, acceptDrops));
+ }
+
+ @Override
+ public boolean libraryDrop(EditTile target, Object obj, boolean isPaste, boolean doDrop) {
+ if (!isPaste && this.acceptDrops && obj instanceof URL && (this.acceptAnyExt || this.files.extMatches(((URL)obj).getExt()))) {
+ if (doDrop) {
+ target.addUndoableSet(this.property, obj);
+ }
+
+ return true;
+ } else {
+ return false;
+ }
+ }
+}
diff --git a/NET/worlds/scape/URLSelf.java b/NET/worlds/scape/URLSelf.java
new file mode 100644
index 0000000..f4c8183
--- /dev/null
+++ b/NET/worlds/scape/URLSelf.java
@@ -0,0 +1,13 @@
+package NET.worlds.scape;
+
+import NET.worlds.network.URL;
+
+public interface URLSelf extends Persister {
+ void incRef();
+
+ void decRef();
+
+ URL getSourceURL();
+
+ void setSourceURL(URL var1);
+}
diff --git a/NET/worlds/scape/URLSelfLoader.java b/NET/worlds/scape/URLSelfLoader.java
new file mode 100644
index 0000000..6020fde
--- /dev/null
+++ b/NET/worlds/scape/URLSelfLoader.java
@@ -0,0 +1,182 @@
+package NET.worlds.scape;
+
+import NET.worlds.core.FastDataInput;
+import NET.worlds.network.URL;
+import java.io.IOException;
+import java.util.Hashtable;
+import java.util.Vector;
+
+public class URLSelfLoader implements BGLoaded {
+ private static Hashtable loaded = new Hashtable();
+ private static Hashtable loading = new Hashtable();
+ private URL url;
+ private Vector callbacks = new Vector();
+ private static final int INIT = 0;
+ private static final int DONE = -1;
+ private int state = 0;
+ private FastDataInput inFile;
+ private Restorer restorer;
+ private URLSelf loadedObj;
+ public Object otemp1;
+ public Object otemp2;
+ public int itemp1;
+ public int itemp2;
+
+ public static void load(URL url, LoadedURLSelf callback) {
+ load(url, callback, false);
+ }
+
+ public static void load(URL url, LoadedURLSelf callback, boolean isHighPriority) {
+ URLSelf o = (URLSelf)loaded.get(url);
+ if (o != null) {
+ o.incRef();
+ callback.loadedURLSelf(o, url, null);
+ } else {
+ URLSelfLoader cl = (URLSelfLoader)loading.get(url);
+ if (cl != null) {
+ cl.callbacks.addElement(callback);
+ } else {
+ new URLSelfLoader(url, callback, isHighPriority);
+ }
+ }
+ }
+
+ public static void unload(URLSelf self) {
+ loaded.remove(self.getSourceURL());
+ }
+
+ public static void immediateLoad(IncrementalRestorer o, Restorer r) throws IOException, TooNewException {
+ new URLSelfLoader(o, r);
+ }
+
+ private URLSelfLoader(IncrementalRestorer o, Restorer r) throws IOException, TooNewException {
+ this.url = null;
+
+ while (this.state != -1) {
+ try {
+ this.state = o.incRestore(this.state, r, this);
+ } catch (Exception var4) {
+ var4.printStackTrace(System.out);
+
+ assert false;
+ }
+ }
+ }
+
+ public URL getURL() {
+ return this.url;
+ }
+
+ private URLSelfLoader(URL url, LoadedURLSelf callback, boolean isHighPriority) {
+ loading.put(url, this);
+ this.url = url;
+ this.callbacks.addElement(callback);
+ BackgroundLoader.get(this, url, isHighPriority);
+ }
+
+ @Override
+ public Object asyncBackgroundLoad(String localName, URL remoteName) {
+ if (localName == null) {
+ return "Can't find file " + this.url;
+ } else {
+ try {
+ return new FastDataInput(localName);
+ } catch (IOException var4) {
+ return "Can't load file " + this.url;
+ }
+ }
+ }
+
+ @Override
+ public boolean syncBackgroundLoad(Object obj, URL remoteURL) {
+ if (obj instanceof String) {
+ this.doneLoading(null, (String)obj);
+ return false;
+ } else {
+ assert this.state != -1;
+
+ if (this.state == 0) {
+ this.inFile = (FastDataInput)obj;
+ Object o = null;
+
+ try {
+ this.restorer = new Restorer(this.inFile, this.url);
+ o = this.restorer.restore(false);
+ this.loadedObj = (URLSelf)o;
+ this.loadedObj.setSourceURL(this.getURL());
+ if (!(this.loadedObj instanceof IncrementalRestorer)) {
+ this.loadedObj.restoreState(this.restorer);
+ this.restorer.done();
+ return this.doneLoading(this.loadedObj, null);
+ }
+ } catch (Exception var7) {
+ var7.printStackTrace(System.out);
+ return this.doneLoading(null, "Can't restore from file " + this.url + ": " + var7.toString());
+ }
+ }
+
+ try {
+ this.state = ((IncrementalRestorer)this.loadedObj).incRestore(this.state, this.restorer, this);
+ } catch (Exception var6) {
+ var6.printStackTrace(System.out);
+ return this.doneLoading(null, var6.toString());
+ }
+
+ if (this.state == -1) {
+ try {
+ this.restorer.done();
+ } catch (IOException var5) {
+ var5.printStackTrace(System.out);
+ return this.doneLoading(null, var5.toString());
+ }
+
+ if (this.restorer.version() < 3 && this.loadedObj instanceof Camera) {
+ Camera cam = (Camera)this.loadedObj;
+ World w = cam.getWorld();
+ w.setSourceURL(cam.getSourceURL());
+ }
+
+ return this.doneLoading(this.loadedObj, null);
+ } else {
+ return true;
+ }
+ }
+ }
+
+ private boolean doneLoading(URLSelf o, String err) {
+ if (this.inFile != null) {
+ this.inFile.close();
+ this.inFile = null;
+ }
+
+ loading.remove(this.url);
+ if (o != null) {
+ if (this.restorer.version() < 4 && o instanceof Camera) {
+ Camera c = (Camera)o;
+ o = c.getWorld();
+ c.detach();
+ }
+
+ loaded.put(this.url, o);
+ }
+
+ int end = this.callbacks.size();
+
+ for (int i = 0; i < end; i++) {
+ LoadedURLSelf callback = (LoadedURLSelf)this.callbacks.elementAt(i);
+ if (o != null) {
+ o.incRef();
+ }
+
+ callback.loadedURLSelf(o, this.url, err);
+ }
+
+ this.state = -1;
+ return false;
+ }
+
+ @Override
+ public Room getBackgroundLoadRoom() {
+ return null;
+ }
+}
diff --git a/NET/worlds/scape/UndoStack.java b/NET/worlds/scape/UndoStack.java
new file mode 100644
index 0000000..5c325db
--- /dev/null
+++ b/NET/worlds/scape/UndoStack.java
@@ -0,0 +1,41 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+
+class UndoStack {
+ private Undoable[] stack = new Undoable[100];
+ private int stackPtr;
+
+ Undoable peek() {
+ return this.stackPtr - 1 >= 0 ? this.stack[this.stackPtr - 1] : this.stack[this.stack.length - 1];
+ }
+
+ void push(Undoable undo) {
+ while (true) {
+ try {
+ this.stack[this.stackPtr++] = undo;
+ return;
+ } catch (IndexOutOfBoundsException var3) {
+ this.stackPtr = 0;
+ }
+ }
+ }
+
+ boolean undo() {
+ while (true) {
+ try {
+ Undoable u = this.stack[--this.stackPtr];
+ if (u != null) {
+ u.undo();
+ this.stack[this.stackPtr] = null;
+ return true;
+ }
+
+ Console.println(Console.message("No-undo"));
+ return false;
+ } catch (IndexOutOfBoundsException var2) {
+ this.stackPtr = this.stack.length;
+ }
+ }
+ }
+}
diff --git a/NET/worlds/scape/UndoWidget.java b/NET/worlds/scape/UndoWidget.java
new file mode 100644
index 0000000..bb4d140
--- /dev/null
+++ b/NET/worlds/scape/UndoWidget.java
@@ -0,0 +1,14 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+
+class UndoWidget extends ClickWidget {
+ public UndoWidget(ToolBar toolbar) {
+ super(toolbar, "undo.gif", Console.message("Undo"));
+ }
+
+ @Override
+ public void perform() {
+ Console.getFrame().getEditTile().undo();
+ }
+}
diff --git a/NET/worlds/scape/UndoabCopy.java b/NET/worlds/scape/UndoabCopy.java
new file mode 100644
index 0000000..606a622
--- /dev/null
+++ b/NET/worlds/scape/UndoabCopy.java
@@ -0,0 +1,14 @@
+package NET.worlds.scape;
+
+class UndoabCopy implements Undoable {
+ private ClipboardEntry prevClipboard = EditTile.getClipboard();
+
+ UndoabCopy(ClipboardEntry newClipboard) {
+ EditTile.setClipboard(newClipboard);
+ }
+
+ @Override
+ public void undo() {
+ EditTile.setClipboard(this.prevClipboard);
+ }
+}
diff --git a/NET/worlds/scape/UndoablAdd.java b/NET/worlds/scape/UndoablAdd.java
new file mode 100644
index 0000000..6de4650
--- /dev/null
+++ b/NET/worlds/scape/UndoablAdd.java
@@ -0,0 +1,21 @@
+package NET.worlds.scape;
+
+class UndoablAdd implements Undoable {
+ protected VectorProperty prop;
+ protected Object obj;
+
+ UndoablAdd(VectorProperty prop, Object obj) {
+ this.prop = prop;
+ this.obj = obj;
+ prop.add(obj);
+ }
+
+ @Override
+ public void undo() {
+ this.prop.delete(this.obj);
+ }
+
+ public Object getObject() {
+ return this.obj;
+ }
+}
diff --git a/NET/worlds/scape/UndoablCut.java b/NET/worlds/scape/UndoablCut.java
new file mode 100644
index 0000000..1bf4ad2
--- /dev/null
+++ b/NET/worlds/scape/UndoablCut.java
@@ -0,0 +1,23 @@
+package NET.worlds.scape;
+
+class UndoablCut extends UndoablDelete {
+ private ClipboardEntry prevClipboard = EditTile.getClipboard();
+ private boolean clipValid;
+
+ UndoablCut(VectorProperty prop, int index) {
+ super(prop, index);
+ ClipboardEntry newEnt = new ClipboardEntry();
+ if (newEnt.cut((SuperRoot)this.obj)) {
+ EditTile.setClipboard(newEnt);
+ this.clipValid = true;
+ }
+ }
+
+ @Override
+ public void undo() {
+ super.undo();
+ if (this.clipValid) {
+ EditTile.setClipboard(this.prevClipboard);
+ }
+ }
+}
diff --git a/NET/worlds/scape/UndoablDelete.java b/NET/worlds/scape/UndoablDelete.java
new file mode 100644
index 0000000..64146b8
--- /dev/null
+++ b/NET/worlds/scape/UndoablDelete.java
@@ -0,0 +1,19 @@
+package NET.worlds.scape;
+
+import java.util.Vector;
+
+class UndoablDelete implements Undoable {
+ protected VectorProperty prop;
+ protected Object obj;
+
+ UndoablDelete(VectorProperty prop, int index) {
+ this.prop = prop;
+ this.obj = ((Vector)prop.get()).elementAt(index);
+ prop.delete(this.obj);
+ }
+
+ @Override
+ public void undo() {
+ this.prop.add(this.obj);
+ }
+}
diff --git a/NET/worlds/scape/UndoablPaste.java b/NET/worlds/scape/UndoablPaste.java
new file mode 100644
index 0000000..f4a1c54
--- /dev/null
+++ b/NET/worlds/scape/UndoablPaste.java
@@ -0,0 +1,16 @@
+package NET.worlds.scape;
+
+class UndoablPaste extends UndoablAdd {
+ private ClipboardEntry clipboard;
+
+ UndoablPaste(VectorProperty prop, ClipboardEntry clipboard, Object obj) {
+ super(prop, obj);
+ this.clipboard = clipboard;
+ }
+
+ @Override
+ public void undo() {
+ super.undo();
+ this.clipboard.unPaste((SuperRoot)this.obj);
+ }
+}
diff --git a/NET/worlds/scape/UndoablSet.java b/NET/worlds/scape/UndoablSet.java
new file mode 100644
index 0000000..424386f
--- /dev/null
+++ b/NET/worlds/scape/UndoablSet.java
@@ -0,0 +1,17 @@
+package NET.worlds.scape;
+
+class UndoablSet implements Undoable {
+ private Property prop;
+ private Object obj;
+
+ UndoablSet(Property prop, Object newObj) {
+ this.prop = prop;
+ this.obj = prop.get();
+ prop.set(newObj);
+ }
+
+ @Override
+ public void undo() {
+ this.prop.set(this.obj);
+ }
+}
diff --git a/NET/worlds/scape/UndoablTransform.java b/NET/worlds/scape/UndoablTransform.java
new file mode 100644
index 0000000..3e316d2
--- /dev/null
+++ b/NET/worlds/scape/UndoablTransform.java
@@ -0,0 +1,16 @@
+package NET.worlds.scape;
+
+class UndoablTransform implements Undoable {
+ private WObject wob;
+ private Transform transform;
+
+ UndoablTransform(WObject wob) {
+ this.wob = wob;
+ this.transform = wob.getTransform();
+ }
+
+ @Override
+ public void undo() {
+ this.wob.setTransform(this.transform);
+ }
+}
diff --git a/NET/worlds/scape/Undoable.java b/NET/worlds/scape/Undoable.java
new file mode 100644
index 0000000..b640035
--- /dev/null
+++ b/NET/worlds/scape/Undoable.java
@@ -0,0 +1,5 @@
+package NET.worlds.scape;
+
+public interface Undoable {
+ void undo();
+}
diff --git a/NET/worlds/scape/UniqueHasher.java b/NET/worlds/scape/UniqueHasher.java
new file mode 100644
index 0000000..193a145
--- /dev/null
+++ b/NET/worlds/scape/UniqueHasher.java
@@ -0,0 +1,31 @@
+package NET.worlds.scape;
+
+import java.util.Hashtable;
+
+public class UniqueHasher {
+ private int currentHash = 0;
+ private static UniqueHasher uh_;
+ private Hashtable ht = new Hashtable();
+
+ private UniqueHasher() {
+ }
+
+ public static UniqueHasher uh() {
+ if (uh_ == null) {
+ uh_ = new UniqueHasher();
+ }
+
+ return uh_;
+ }
+
+ public int hash(Object toHash) {
+ Integer value = (Integer)this.ht.get(toHash);
+ if (value == null) {
+ this.currentHash++;
+ value = new Integer(this.currentHash);
+ this.ht.put(toHash, value);
+ }
+
+ return value;
+ }
+}
diff --git a/NET/worlds/scape/UnitEnumeration.java b/NET/worlds/scape/UnitEnumeration.java
new file mode 100644
index 0000000..8702ebd
--- /dev/null
+++ b/NET/worlds/scape/UnitEnumeration.java
@@ -0,0 +1,23 @@
+package NET.worlds.scape;
+
+import java.util.Enumeration;
+
+public class UnitEnumeration implements Enumeration {
+ private Object o;
+
+ UnitEnumeration(Object o) {
+ this.o = o;
+ }
+
+ @Override
+ public boolean hasMoreElements() {
+ return this.o != null;
+ }
+
+ @Override
+ public Object nextElement() {
+ Object t = this.o;
+ this.o = null;
+ return t;
+ }
+}
diff --git a/NET/worlds/scape/UniverseHandler.java b/NET/worlds/scape/UniverseHandler.java
new file mode 100644
index 0000000..b0e05cf
--- /dev/null
+++ b/NET/worlds/scape/UniverseHandler.java
@@ -0,0 +1,66 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.DefaultConsole;
+import NET.worlds.console.UniversePanel;
+
+public class UniverseHandler {
+ public static boolean handle(MouseDeltaEvent e) {
+ if (e.dx != 0 || e.dy != 0) {
+ Console cons = Console.getActive();
+ UniversePanel universe = null;
+ if (cons instanceof DefaultConsole) {
+ universe = ((DefaultConsole)cons).getUniverse();
+ }
+
+ if (universe != null) {
+ universe.addOffset(-e.dx, -e.dy);
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public static boolean handle(KeyDownEvent e) {
+ Console cons = Console.getActive();
+ UniversePanel universe = null;
+ if (cons instanceof DefaultConsole) {
+ universe = ((DefaultConsole)cons).getUniverse();
+ }
+
+ if (universe != null) {
+ switch (e.key) {
+ case '\ue325':
+ universe.keyDown(null, 1006);
+ return true;
+ case '\ue326':
+ universe.keyDown(null, 1004);
+ return true;
+ case '\ue327':
+ universe.keyDown(null, 1007);
+ return true;
+ case '\ue328':
+ universe.keyDown(null, 1005);
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public static boolean handle(KeyUpEvent e) {
+ Console cons = Console.getActive();
+ UniversePanel universe = null;
+ if (cons instanceof DefaultConsole) {
+ universe = ((DefaultConsole)cons).getUniverse();
+ }
+
+ if (universe != null) {
+ universe.keyUp(null, 1004);
+ return true;
+ } else {
+ return false;
+ }
+ }
+}
diff --git a/NET/worlds/scape/UserEvent.java b/NET/worlds/scape/UserEvent.java
new file mode 100644
index 0000000..17f9759
--- /dev/null
+++ b/NET/worlds/scape/UserEvent.java
@@ -0,0 +1,12 @@
+package NET.worlds.scape;
+
+public class UserEvent extends Event {
+ public UserEvent(int time, Object source, WObject target) {
+ super(time, source, target);
+ }
+
+ @Override
+ public boolean deliver(Object o) {
+ return o instanceof UserHandler && ((UserHandler)o).handle(this);
+ }
+}
diff --git a/NET/worlds/scape/UserHandler.java b/NET/worlds/scape/UserHandler.java
new file mode 100644
index 0000000..96f2bf8
--- /dev/null
+++ b/NET/worlds/scape/UserHandler.java
@@ -0,0 +1,5 @@
+package NET.worlds.scape;
+
+public interface UserHandler {
+ boolean handle(UserEvent var1);
+}
diff --git a/NET/worlds/scape/VTransWidget.java b/NET/worlds/scape/VTransWidget.java
new file mode 100644
index 0000000..be35785
--- /dev/null
+++ b/NET/worlds/scape/VTransWidget.java
@@ -0,0 +1,19 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.SnapTool;
+
+class VTransWidget extends WidgetButton {
+ public VTransWidget(ToolBar toolbar) {
+ super(toolbar, "vtrans.gif", "Move vertically");
+ }
+
+ @Override
+ public String drag(boolean initialDrag, float deltax, float deltay) {
+ Transform t = Transform.make();
+ this.applyWorldTransform(
+ initialDrag, t.moveBy(SnapTool.snapTool().snapTo(this.getWorldAxis(1, 0, 0).times(deltax).plus(this.getWorldAxis(0, 0, 1).times(deltay))))
+ );
+ t.recycle();
+ return "" + this.getWObject().getPosition();
+ }
+}
diff --git a/NET/worlds/scape/ValueEvent.java b/NET/worlds/scape/ValueEvent.java
new file mode 100644
index 0000000..1b89c1e
--- /dev/null
+++ b/NET/worlds/scape/ValueEvent.java
@@ -0,0 +1,15 @@
+package NET.worlds.scape;
+
+public class ValueEvent extends Event {
+ public Object whoChanged;
+
+ public ValueEvent(int time, Object source, WObject target, Object whoChanged) {
+ super(time, source, target);
+ this.whoChanged = whoChanged;
+ }
+
+ @Override
+ public boolean deliver(Object o) {
+ return o instanceof ValueHandler && ((ValueHandler)o).handle(this);
+ }
+}
diff --git a/NET/worlds/scape/ValueHandler.java b/NET/worlds/scape/ValueHandler.java
new file mode 100644
index 0000000..637ce11
--- /dev/null
+++ b/NET/worlds/scape/ValueHandler.java
@@ -0,0 +1,5 @@
+package NET.worlds.scape;
+
+public interface ValueHandler {
+ boolean handle(ValueEvent var1);
+}
diff --git a/NET/worlds/scape/VectorProperty.java b/NET/worlds/scape/VectorProperty.java
new file mode 100644
index 0000000..cbd9573
--- /dev/null
+++ b/NET/worlds/scape/VectorProperty.java
@@ -0,0 +1,76 @@
+package NET.worlds.scape;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+public class VectorProperty extends Property {
+ private PropAdder adder;
+ private boolean allowSorting = true;
+
+ public VectorProperty(Properties owner, int index, String propName) {
+ super(owner, index, propName);
+ }
+
+ public static Vector toVector(Object[] arr) {
+ Vector v = new Vector(arr.length);
+
+ for (int i = 0; i < arr.length; i++) {
+ v.addElement(arr[i]);
+ }
+
+ return v;
+ }
+
+ public static Vector toVector(Hashtable hash) {
+ Vector v = new Vector(hash.size());
+ Enumeration e = hash.elements();
+
+ while (e.hasMoreElements()) {
+ v.addElement(e.nextElement());
+ }
+
+ return v;
+ }
+
+ public Object delete(Object obj) {
+ assert obj != null;
+
+ assert this.adder != null;
+
+ return this.operate(4, obj);
+ }
+
+ public Object add(Object obj) {
+ assert obj != null;
+
+ assert this.adder != null;
+
+ return this.operate(3, obj);
+ }
+
+ public boolean addTest(Object obj) {
+ assert obj != null;
+
+ assert this.adder != null;
+
+ return this.operate(5, obj) != null;
+ }
+
+ public VectorProperty setAdder(PropAdder adder) {
+ this.adder = adder;
+ return this;
+ }
+
+ public PropAdder getAdder() {
+ return this.adder;
+ }
+
+ public void allowSorting(boolean allow) {
+ this.allowSorting = allow;
+ }
+
+ public boolean shouldSort() {
+ return this.allowSorting;
+ }
+}
diff --git a/NET/worlds/scape/VehicleDriver.java b/NET/worlds/scape/VehicleDriver.java
new file mode 100644
index 0000000..10daf6c
--- /dev/null
+++ b/NET/worlds/scape/VehicleDriver.java
@@ -0,0 +1,653 @@
+package NET.worlds.scape;
+
+public class VehicleDriver extends SwitchableBehavior implements MouseDeltaHandler, KeyUpHandler, KeyDownHandler, MouseDownHandler, MouseUpHandler, FrameHandler {
+ protected VehicleShape vehicle;
+ static final boolean debug = true;
+ static final float gravity = 32.1F;
+ static final float densityOfAir = 0.0801F;
+ static final float dragCoefficient = 0.3F;
+ static final float feetToWorld = 30.48F;
+ static final float worldToFeet = 0.0328084F;
+ static final float epsilon = 0.001F;
+ static final float maxCamber = 0.4F;
+ static final float rotationalDampener = 0.5F;
+ static final int asphalt = 0;
+ static final int grass = 1;
+ static final int numTerrainTypes = 2;
+ float acceleratorDepression = 0.0F;
+ float brakesDepression = 0.0F;
+ int currentGear = 1;
+ float steeringWheelPosition = 0.0F;
+ boolean gasKeyDown = false;
+ boolean brakeKeyDown = false;
+ boolean leftKeyDown = false;
+ boolean rightKeyDown = false;
+ Point3 velocityVector = new Point3(0.0F, 0.0F, 0.0F);
+ Point3 velocityVectorCarFrame = new Point3(0.0F, 0.0F, 0.0F);
+ float velocity = 0.0F;
+ Point3 angularVelocity = new Point3(0.0F, 0.0F, 0.0F);
+ Point3 angularVelocityCarFrame = new Point3(0.0F, 0.0F, 0.0F);
+ Point3 worldCenterOfMass = new Point3(0.0F, 0.0F, 0.0F);
+ float engineRPM = 0.0F;
+ Point3 integratedForce = new Point3(0.0F, 0.0F, 0.0F);
+ Point3 integratedTorque = new Point3(0.0F, 0.0F, 0.0F);
+ boolean disabled = false;
+ float[] minRPMs;
+ VehicleDriver.Tire[] tires;
+ protected Room room;
+ protected Pilot pilot;
+ static float lastTime = 0.0F;
+ static final int lateralForceIncrements = 1000;
+ static float[][] muTable;
+ static boolean lateralForceTableInited = false;
+ static final int torqueIncrements = 500;
+ static final float maxRPM = 7000.0F;
+ static final float minRPM = 1500.0F;
+ static final float rpmInc = 500.0F;
+ static final int numRPMs = 12;
+ static float[] torqueTable;
+ static boolean torqueTableInited = false;
+ static float[] rawTorqueData = new float[]{80.0F, 82.0F, 91.0F, 92.0F, 89.0F, 90.0F, 98.0F, 93.0F, 94.0F, 78.0F, 83.0F, 75.0F};
+ static final float torqueMax = 98.0F;
+
+ public VehicleDriver(VehicleShape p_Vehicle) {
+ this.vehicle = p_Vehicle;
+ this.initLateralForceTable();
+ this.initTorqueTable();
+ this.initRPMTable();
+ this.tires = new VehicleDriver.Tire[4];
+
+ for (int tire = 0; tire < 4; tire++) {
+ this.tires[tire] = new VehicleDriver.Tire();
+ this.tires[tire].relativePos.copy(this.vehicle.tirePositions[tire]);
+ }
+ }
+
+ @Override
+ public boolean handle(MouseDeltaEvent e) {
+ return UniverseHandler.handle(e);
+ }
+
+ @Override
+ public boolean handle(KeyDownEvent e) {
+ if (UniverseHandler.handle(e)) {
+ return true;
+ } else {
+ switch (e.key) {
+ case '1':
+ if (this.vehicle.stickShift) {
+ this.currentGear = 1;
+ }
+ break;
+ case '2':
+ if (this.vehicle.stickShift) {
+ this.currentGear = 2;
+ }
+ break;
+ case '3':
+ if (this.vehicle.stickShift) {
+ this.currentGear = 3;
+ }
+ break;
+ case '4':
+ if (this.vehicle.stickShift) {
+ this.currentGear = 4;
+ }
+ break;
+ case '5':
+ if (this.vehicle.stickShift) {
+ this.currentGear = 5;
+ }
+ break;
+ case 'R':
+ case 'r':
+ this.currentGear = 0;
+ break;
+ case '\ue325':
+ this.leftKeyDown = true;
+ break;
+ case '\ue326':
+ this.gasKeyDown = true;
+ break;
+ case '\ue327':
+ this.rightKeyDown = true;
+ break;
+ case '\ue328':
+ this.brakeKeyDown = true;
+ }
+
+ return true;
+ }
+ }
+
+ @Override
+ public boolean handle(KeyUpEvent e) {
+ if (UniverseHandler.handle(e)) {
+ return true;
+ } else {
+ switch (e.key) {
+ case '\ue325':
+ this.leftKeyDown = false;
+ break;
+ case '\ue326':
+ this.gasKeyDown = false;
+ break;
+ case '\ue327':
+ this.rightKeyDown = false;
+ break;
+ case '\ue328':
+ this.brakeKeyDown = false;
+ }
+
+ return true;
+ }
+ }
+
+ @Override
+ public boolean handle(MouseDownEvent e) {
+ return false;
+ }
+
+ @Override
+ public boolean handle(MouseUpEvent e) {
+ return false;
+ }
+
+ @Override
+ public boolean handle(FrameEvent e) {
+ if (!(e.receiver instanceof Pilot)) {
+ return true;
+ } else {
+ this.pilot = (Pilot)e.receiver;
+ if (!this.pilot.isActive()) {
+ return true;
+ } else {
+ Point3Temp com = Point3Temp.make(this.vehicle.centerOfGravity);
+ com.times(30.48F);
+ com.times(this.pilot.getObjectToWorldMatrix());
+ com.times(0.0328084F);
+ this.worldCenterOfMass.set(com.x, com.y, com.z);
+ this.room = this.pilot.getRoom();
+ int now = e.time;
+ float dt = (now - lastTime) / 1000.0F;
+ lastTime = now;
+ if (dt <= 0.0F) {
+ return true;
+ } else {
+ if (dt > 0.33F) {
+ dt = 0.33F;
+ }
+
+ if (this.gasKeyDown) {
+ this.acceleratorDepression = (float)(this.acceleratorDepression + 1.2 * dt);
+ } else {
+ this.acceleratorDepression = 0.0F;
+ }
+
+ if (this.acceleratorDepression > 1.0) {
+ this.acceleratorDepression = 1.0F;
+ }
+
+ if (this.brakeKeyDown) {
+ this.brakesDepression = (float)(this.brakesDepression + 1.2 * dt);
+ } else {
+ this.brakesDepression = 0.0F;
+ }
+
+ if (this.brakesDepression > 1.0) {
+ this.brakesDepression = 1.0F;
+ }
+
+ float wheelDelta = 0.282F * dt;
+ if (Math.abs(this.velocityVectorCarFrame.y) < 10.0F) {
+ wheelDelta = (float)(wheelDelta * 0.5);
+ }
+
+ if (this.leftKeyDown) {
+ this.steeringWheelPosition -= wheelDelta;
+ } else if (this.rightKeyDown) {
+ this.steeringWheelPosition += wheelDelta;
+ } else {
+ this.steeringWheelPosition = 0.0F;
+ }
+
+ if (this.steeringWheelPosition > 0.5) {
+ this.steeringWheelPosition = 0.5F;
+ }
+
+ if (this.steeringWheelPosition < -0.5) {
+ this.steeringWheelPosition = -0.5F;
+ }
+
+ this.DoPhysics(dt);
+ return true;
+ }
+ }
+ }
+ }
+
+ protected void DoPhysics(float dt) {
+ System.out.println("-----------------------------");
+ float engineTorque = this.vehicle.maxEngineTorque * this.acceleratorDepression * this.getTorque(this.engineRPM);
+
+ assert this.vehicle.wheelDiameter != 0.0F;
+
+ float gearRatio = this.getGearRatio(this.currentGear);
+ float wheelForce = engineTorque * this.vehicle.rearEndRatio * gearRatio / (this.vehicle.wheelDiameter * 0.5F);
+ if (Math.abs(this.velocityVectorCarFrame.y) > 2.0) {
+ wheelForce -= this.brakesDepression * this.vehicle.mass * 100.0F;
+ } else if (this.brakesDepression > 0.0F) {
+ this.velocityVectorCarFrame.y = 0.0F;
+ }
+
+ if (gearRatio == 0.0F) {
+ wheelForce *= -1.0F;
+ }
+
+ if (this.disabled) {
+ wheelForce = 0.0F;
+ }
+
+ switch (this.vehicle.driveType) {
+ case 0:
+ wheelForce = (float)(wheelForce * 0.25);
+ this.tires[0].driveForce = this.tires[1].driveForce = wheelForce;
+ this.tires[2].driveForce = this.tires[3].driveForce = wheelForce;
+ break;
+ case 1:
+ wheelForce = (float)(wheelForce * 0.5);
+ this.tires[0].driveForce = this.tires[1].driveForce = wheelForce;
+ this.tires[2].driveForce = this.tires[3].driveForce = 0.0;
+ break;
+ case 2:
+ default:
+ wheelForce = (float)(wheelForce * 0.5);
+ this.tires[0].driveForce = this.tires[1].driveForce = 0.0;
+ this.tires[2].driveForce = this.tires[3].driveForce = wheelForce;
+ }
+
+ float wheelAngle = this.steeringWheelPosition * 1.57F;
+ this.tires[0].wheelAngle = this.tires[1].wheelAngle = -wheelAngle;
+ float wheelRPM = 60.0F * this.velocityVectorCarFrame.y / ((float) Math.PI * this.vehicle.wheelDiameter);
+ this.engineRPM = wheelRPM * this.vehicle.rearEndRatio * gearRatio;
+ if (this.engineRPM < this.vehicle.idleRPM) {
+ this.engineRPM = this.vehicle.idleRPM;
+ }
+
+ if (!this.vehicle.stickShift) {
+ if (this.engineRPM > this.vehicle.rpmTorquePeak && this.currentGear < 5) {
+ this.currentGear++;
+ }
+
+ if (this.engineRPM < this.minRPMs[this.currentGear] && this.currentGear > 1) {
+ this.currentGear--;
+ }
+ }
+
+ Point3Temp netForce = Point3Temp.make(0.0F, 0.0F, 0.0F);
+ Point3Temp netTorque = Point3Temp.make(0.0F, 0.0F, 0.0F);
+
+ for (int wheel = 0; wheel < 4; wheel++) {
+ this.calculateForces(this.tires[wheel]);
+ netForce.plus(this.tires[wheel].force);
+ netTorque.plus(this.tires[wheel].torque);
+ }
+
+ Point3Temp airFriction = Point3Temp.make(this.velocityVectorCarFrame);
+ airFriction.negate();
+ airFriction.normalize();
+ float drag = 0.15F * this.vehicle.frontalArea * 0.0801F * this.velocity * this.velocity / 32.1F;
+ airFriction.times(drag);
+ netForce.plus(airFriction);
+ netForce.vectorTimes(this.pilot.getObjectToWorldMatrix());
+ System.out.println("Net force " + netForce.x + " " + netForce.y + " " + netForce.z);
+ System.out.println("Net torque " + netTorque.x + " " + netTorque.y + " " + netTorque.z);
+ Point3Temp gravityForce = Point3Temp.make(0.0F, 0.0F, -this.vehicle.mass * 32.1F);
+ netForce.plus(gravityForce);
+ Point3Temp inertialDampener = Point3Temp.make(0.5F, 0.5F, 0.5F);
+ inertialDampener.times(this.angularVelocityCarFrame);
+ inertialDampener.times(this.vehicle.momentsOfInertia);
+ inertialDampener.times(1.0F / dt);
+ netTorque.minus(inertialDampener);
+ this.integratedForce.plus(netForce);
+ this.integratedForce.times(0.5F);
+ this.integratedTorque.plus(netTorque);
+ this.integratedTorque.times(0.5F);
+ inertialDampener = Point3Temp.make(this.integratedForce);
+ inertialDampener.times(1.0F / this.vehicle.mass);
+ Point3Temp dV = Point3Temp.make(inertialDampener);
+ dV.times(dt);
+ Point3Temp lastV = Point3Temp.make(this.velocityVector);
+ Point3Temp lastW = Point3Temp.make(this.angularVelocityCarFrame);
+ this.velocityVector.plus(dV);
+ this.velocityVector.plus(lastV);
+ this.velocityVector.times(0.5F);
+ this.velocity = this.velocityVector.length();
+ this.velocityVectorCarFrame.copy(this.velocityVector);
+ this.velocityVectorCarFrame.vectorTimes(this.pilot.getObjectToWorldMatrix().invert());
+ Point3Temp dw = Point3Temp.make(this.integratedTorque);
+ dw.times(dt);
+ dw.dividedBy(this.vehicle.momentsOfInertia);
+ this.angularVelocityCarFrame.plus(dw);
+ this.angularVelocityCarFrame.plus(lastW);
+ this.angularVelocityCarFrame.times(0.5F);
+ this.angularVelocity.copy(this.angularVelocityCarFrame);
+ this.angularVelocity.vectorTimes(this.pilot.getObjectToWorldMatrix());
+ Point3Temp dx = Point3Temp.make(this.velocityVector);
+ dx.times(dt);
+ float maxUnderground = 0.0F;
+
+ for (int tire = 0; tire < 4; tire++) {
+ float diff = -this.tires[tire].underGround;
+ if (diff > maxUnderground) {
+ maxUnderground = diff;
+ }
+ }
+
+ dx.z += maxUnderground;
+ dx.times(30.48F);
+ Point3Temp da = Point3Temp.make(this.angularVelocity);
+ da.times(dt);
+ this.pilot.premoveThrough(dx);
+ float convert = 180.0F / (float)Math.PI;
+ this.pilot.pitch(da.x * convert);
+ this.pilot.roll(da.y * convert);
+ this.pilot.yaw(da.z * convert);
+ System.out.println("dx " + dx.x + " " + dx.y + " " + dx.z);
+ System.out.println("da " + da.x + " " + da.y + " " + da.z);
+ System.out.println("pos" + this.pilot.getX() + " " + this.pilot.getY() + " " + this.pilot.getZ());
+ }
+
+ protected void calculateForces(VehicleDriver.Tire tire) {
+ tire.force.set(0.0F, 0.0F, 0.0F);
+ tire.torque.set(0.0F, 0.0F, 0.0F);
+ Transform o2w = this.pilot.getObjectToWorldMatrix();
+ Transform w2o = this.pilot.getObjectToWorldMatrix().invert();
+ Point3Temp worldPos = Point3Temp.make(tire.relativePos);
+ worldPos.plus(this.vehicle.centerOfGravity);
+ worldPos.times(30.48F);
+ worldPos.times(o2w);
+ double groundZ = this.room.floorHeight(worldPos.x, worldPos.y, worldPos.z);
+ Point3 N = this.room.surfaceNormal(worldPos.x, worldPos.y, worldPos.z);
+ groundZ *= 0.0328084F;
+ worldPos.times(0.0328084F);
+ tire.underGround = (float)(worldPos.z - groundZ);
+ if (!(tire.underGround > this.vehicle.shockLength)) {
+ Point3Temp R = Point3Temp.make(tire.relativePos);
+ R.vectorTimes(o2w);
+ Point3Temp w = Point3Temp.make(this.angularVelocity);
+ w.cross(R);
+ w.plus(this.velocityVector);
+ Point3Temp Vp = Point3Temp.make(w);
+ System.out.println("R " + R.x + " " + R.y + " " + R.z);
+ System.out.println("Vp " + Vp.x + " " + Vp.y + " " + Vp.z);
+ double normalSpeed = Vp.dot(N);
+ Point3Temp No = Point3Temp.make(N);
+ No.vectorTimes(w2o);
+ Point3Temp tmp = Point3Temp.make(No);
+ double scalarInertialMoment = tmp.dot(this.vehicle.momentsOfInertia);
+ scalarInertialMoment = Math.abs(scalarInertialMoment);
+ Point3Temp orthoNormal = Point3Temp.make(R);
+ orthoNormal.cross(N);
+ double r = orthoNormal.length();
+ double denominator = r * this.vehicle.mass + scalarInertialMoment;
+
+ assert denominator != 0.0;
+
+ double myMass = this.vehicle.mass * 0.25;
+ double weight = scalarInertialMoment * myMass / denominator;
+ if (weight < 0.0) {
+ weight = 0.0;
+ }
+
+ if (weight > this.vehicle.mass) {
+ weight = myMass;
+ }
+
+ assert this.vehicle.shockLength != 0.0F;
+
+ double k = weight * 32.1F / this.vehicle.shockLength;
+ double springLength = worldPos.z - (groundZ + this.vehicle.shockLength);
+ if (springLength < -this.vehicle.shockLength) {
+ springLength = -this.vehicle.shockLength;
+ }
+
+ if (springLength > this.vehicle.shockLength) {
+ springLength = this.vehicle.shockLength;
+ }
+
+ double groundForce = -k * springLength;
+ double term = k * weight;
+
+ assert term >= 0.0;
+
+ double damp = -Math.sqrt(term) * normalSpeed * this.vehicle.shockDampingCoeff;
+ groundForce += damp;
+ Point3Temp groundForceVector = Point3Temp.make(No);
+ groundForceVector.normalize();
+ groundForceVector.times((float)groundForce);
+ tire.force.plus(groundForceVector);
+ Point3Temp VpCarFrame = Point3Temp.make(Vp);
+ VpCarFrame.vectorTimes(w2o);
+ Point3Temp normalVelocity = Point3Temp.make(VpCarFrame);
+ normalVelocity.z = 0.0F;
+ Point3Temp intendedForce = Point3Temp.make(0.0F, 0.0F, 0.0F);
+ Transform wheelXform = Transform.make();
+ wheelXform.yaw(tire.wheelAngle * 229.1831F);
+ float mu;
+ if (normalVelocity.length() < 0.001F) {
+ mu = 0.0F;
+ } else if (Math.abs(No.x) > 0.4F) {
+ mu = 0.0F;
+ } else {
+ normalVelocity.normalize();
+ Point3Temp wheelDirection = Point3Temp.make(0.0F, 1.0F, 0.0F);
+ wheelDirection.vectorTimes(wheelXform);
+ wheelDirection.normalize();
+ float cosSlipAngle = normalVelocity.dot(wheelDirection);
+ System.out.println("wheel direction " + wheelDirection.x + " " + wheelDirection.y + " " + wheelDirection.z);
+ System.out.println("normal velocity " + normalVelocity.x + " " + normalVelocity.y + " " + normalVelocity.z);
+ System.out.println("cos of slip angle " + cosSlipAngle);
+ mu = this.getLateralForceCoef(cosSlipAngle, 0);
+ float crossZ = normalVelocity.x * wheelDirection.y - normalVelocity.y * wheelDirection.x;
+ if (crossZ > 0.0F) {
+ mu *= -1.0F;
+ }
+ }
+
+ intendedForce.x = mu * (float)groundForce;
+ intendedForce.y = (float)tire.driveForce;
+ System.out.println("Lateral forces " + intendedForce.x + ", " + intendedForce.y);
+ float forceMag = intendedForce.length();
+ float maxForce = (float)groundForce * this.vehicle.tireAdhesiveLimit;
+ if (forceMag > maxForce) {
+ intendedForce.normalize();
+ intendedForce.times(maxForce);
+ tire.slipping = true;
+ } else {
+ tire.slipping = false;
+ }
+
+ intendedForce.vectorTimes(wheelXform);
+ tire.force.plus(intendedForce);
+ Point3Temp rollingFriction = Point3Temp.make(0.0F, 0.0F, 0.0F);
+ float S = 1.0F;
+ float magV = Vp.length();
+ rollingFriction.y = (float)groundForce * 0.001F * (5.7F + 0.036F * magV * 0.6818182F) * S;
+ if (this.velocityVectorCarFrame.y > 0.0F) {
+ rollingFriction.y *= -1.0F;
+ }
+
+ rollingFriction.vectorTimes(wheelXform);
+ System.out.println("Rolling friction " + rollingFriction.x + " " + rollingFriction.y + " " + rollingFriction.z);
+ wheelXform.recycle();
+ Point3Temp rCopy = Point3Temp.make(tire.relativePos);
+ rCopy.negate();
+ tire.torque.copy(tire.force);
+ tire.torque.cross(rCopy);
+ System.out.println("Underground " + springLength + " damping " + damp);
+ System.out.println("Force " + tire.force.x + " " + tire.force.y + " " + tire.force.z);
+ System.out.println("Torque " + tire.torque.x + " " + tire.torque.y + " " + tire.torque.z);
+ System.out.println();
+ }
+ }
+
+ private float getGearRatio(int gearNumber) {
+ float gearRatio;
+ switch (gearNumber) {
+ case 0:
+ gearRatio = this.vehicle.gearRatio1;
+ break;
+ case 1:
+ gearRatio = this.vehicle.gearRatio1;
+ break;
+ case 2:
+ gearRatio = this.vehicle.gearRatio2;
+ break;
+ case 3:
+ gearRatio = this.vehicle.gearRatio3;
+ break;
+ case 4:
+ gearRatio = this.vehicle.gearRatio4;
+ break;
+ case 5:
+ gearRatio = this.vehicle.gearRatio5;
+ break;
+ default:
+ System.out.println("Illegal gear " + this.currentGear);
+ gearRatio = 1.0F;
+ }
+
+ return gearRatio;
+ }
+
+ protected float getLateralForceCoef(float cosSlipAngle, int terrainType) {
+ if (cosSlipAngle > 1.0) {
+ cosSlipAngle = 1.0F;
+ }
+
+ if (cosSlipAngle < -1.0) {
+ cosSlipAngle = -1.0F;
+ }
+
+ float index = (float)Math.ceil(Math.abs(cosSlipAngle) * 1000.0F / 1.0F);
+ return muTable[terrainType][(int)index];
+ }
+
+ protected void initLateralForceTable() {
+ if (!lateralForceTableInited) {
+ lateralForceTableInited = true;
+ muTable = new float[2][1001];
+
+ for (int type = 0; type < 2; type++) {
+ for (int i = 0; i <= 1000; i++) {
+ float degrees = (float)Math.acos(i / 1000.0F);
+ degrees = degrees * 360.0F / (float) (Math.PI * 2);
+ switch (type) {
+ case 0:
+ if (degrees > 45.0F) {
+ degrees = 45.0F;
+ }
+
+ muTable[type][i] = -0.084496F
+ + 0.1241739F * degrees
+ - 0.003676377F * (float)Math.pow(degrees, 2.0)
+ - 5.5137E-6F * (float)Math.pow(degrees, 3.0)
+ + 6.461E-7F * (float)Math.pow(degrees, 4.0);
+ break;
+ case 1:
+ muTable[type][i] = 0.055731F + 0.069871F * degrees - 0.002175398F * degrees * degrees;
+ }
+
+ if (muTable[type][i] < 0.0F) {
+ muTable[type][i] = 0.0F;
+ }
+ }
+ }
+ }
+ }
+
+ float getTorque(float rpm) {
+ if (rpm > 7000.0F) {
+ rpm = 7000.0F;
+ }
+
+ if (rpm < 1500.0F) {
+ rpm = 1500.0F;
+ }
+
+ int index = (int)(rpm / 7000.0F);
+ return torqueTable[index];
+ }
+
+ void initTorqueTable() {
+ if (!torqueTableInited) {
+ torqueTableInited = true;
+ torqueTable = new float[501];
+
+ for (int i = 0; i <= 500; i++) {
+ float rpm = i / 500.0F * 7000.0F;
+ if (rpm < 1500.0F) {
+ rpm = 1500.0F;
+ }
+
+ int closest = 0;
+
+ for (int j = 0; j < 12; j++) {
+ float thisRpm = j * 500.0F + 1500.0F;
+ if (thisRpm >= rpm) {
+ closest = j;
+ break;
+ }
+ }
+
+ if (closest == 0) {
+ torqueTable[i] = rawTorqueData[0] / 98.0F;
+ } else {
+ Point2 low = new Point2();
+ Point2 high = new Point2();
+ Point2 result = new Point2();
+ low.x = (closest - 1) * 500.0F + 1500.0F;
+ low.y = rawTorqueData[closest - 1];
+ high.x = low.x + 500.0F;
+ high.y = rawTorqueData[closest];
+ float alpha = (rpm - low.x) / 500.0F;
+ result.x = low.x * alpha + high.x * (1.0F - alpha);
+ result.y = low.y * alpha + high.y * (1.0F - alpha);
+ torqueTable[i] = result.y / 98.0F;
+ }
+ }
+ }
+ }
+
+ private void initRPMTable() {
+ this.minRPMs = new float[6];
+ float[] maxVel = new float[5];
+
+ for (int x = 0; x < 5; x++) {
+ maxVel[x] = this.vehicle.rpmTorquePeak * (float) Math.PI * this.vehicle.wheelDiameter / (60.0F * this.vehicle.rearEndRatio * this.getGearRatio(x));
+ }
+
+ this.minRPMs[0] = 0.0F;
+
+ for (int x = 1; x <= 5; x++) {
+ this.minRPMs[x] = 60.0F * maxVel[x - 1] * this.vehicle.rearEndRatio * this.getGearRatio(x) / ((float) Math.PI * this.vehicle.wheelDiameter);
+ }
+ }
+
+ protected class Tire {
+ Point3 force = new Point3();
+ Point3 torque = new Point3();
+ Point3 relativePos = new Point3();
+ float underGround;
+ double driveForce = 0.0;
+ float wheelAngle;
+ boolean slipping;
+
+ public Tire() {
+ this.underGround = 0.0F;
+ this.wheelAngle = 0.0F;
+ this.slipping = false;
+ }
+ }
+}
diff --git a/NET/worlds/scape/VehicleShape.java b/NET/worlds/scape/VehicleShape.java
new file mode 100644
index 0000000..2196448
--- /dev/null
+++ b/NET/worlds/scape/VehicleShape.java
@@ -0,0 +1,571 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.DialogReceiver;
+import NET.worlds.console.OkCancelDialog;
+import NET.worlds.core.IniFile;
+import NET.worlds.network.URL;
+import java.io.IOException;
+
+public class VehicleShape extends PosableShape implements MouseDownHandler, DialogReceiver {
+ static final int fourWheelDrive = 0;
+ static final int frontWheelDrive = 1;
+ static final int rearWheelDrive = 2;
+ private String promptString = "Take her for a spin?";
+ public float rearEndRatio = 3.07F;
+ public float frontalArea = 42.5F;
+ public float wheelDiameter = 2.167F;
+ public float coeffKineticFriction = 0.05F;
+ public float coeffStaticFriction = 0.2F;
+ public float mass = 100.0F;
+ public float gearRatio1 = 2.88F;
+ public float gearRatio2 = 1.91F;
+ public float gearRatio3 = 1.33F;
+ public float gearRatio4 = 1.0F;
+ public float gearRatio5 = 0.7F;
+ public float maxEngineTorque = 300.0F;
+ public float tireAdhesiveLimit = 1.1F;
+ public float shockDampingCoeff = 3.0F;
+ public float shockLength = 0.15F;
+ public float rpmTorquePeak = 4200.0F;
+ public float idleRPM = 1000.0F;
+ public boolean stickShift = false;
+ public float initialGas = -1.0F;
+ public float adjustCogX = 0.0F;
+ public float adjustCogY = 0.0F;
+ public float adjustCogZ = 0.0F;
+ public int driveType = 2;
+ public boolean fixedCamera = true;
+ public float camX = 0.0F;
+ public float camY = -80.0F;
+ public float camZ = -120.0F;
+ public float camRoll = -10.0F;
+ public float camPitch = 0.0F;
+ public float camYaw = 0.0F;
+ public float camAimX = 15.0F;
+ public float camAimY = 0.0F;
+ public float camAimZ = 10.0F;
+ public float eyeHeight = 150.0F;
+ public String lastURL = "";
+ public Point3 centerOfGravity;
+ public Point3 momentsOfInertia;
+ public Point3[] tirePositions;
+ private boolean avatarSwitchPending = false;
+ private static String[] vehicleShapeNames = new String[]{"dash"};
+ private static Object classCookie = new Object();
+
+ VehicleShape() {
+ }
+
+ VehicleShape(URL url) {
+ super(url);
+ }
+
+ public static boolean isVehicle(URL url) {
+ if (IniFile.gamma().getIniInt("enableVehicleShapes", 0) == 0) {
+ return false;
+ } else {
+ String s = url.toString();
+
+ for (int i = 0; i < vehicleShapeNames.length; i++) {
+ if (url.toString().indexOf(vehicleShapeNames[i]) != -1) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+ }
+
+ @Override
+ public boolean handle(MouseDownEvent event) {
+ if ((event.key & 1) == 1) {
+ new OkCancelDialog(Console.getFrame(), this, "Change Avatar", "No", "Yes", this.promptString, true);
+ }
+
+ return true;
+ }
+
+ @Override
+ public void dialogDone(Object who, boolean confirmed) {
+ if (who instanceof OkCancelDialog && confirmed) {
+ this.avatarSwitchPending = true;
+ boolean oldVIP = Console.getActive().getVIP();
+ Console.getActive().setVIP(true);
+ Console.getActive().setAvatar(this.url);
+ Console.getActive().setVIP(oldVIP);
+ }
+ }
+
+ protected native void nativeAnalyzeShape(int var1, float var2);
+
+ protected native float nativeGetTirePosX(int var1);
+
+ protected native float nativeGetTirePosY(int var1);
+
+ protected native float nativeGetTirePosZ(int var1);
+
+ protected native float nativeGetCogX();
+
+ protected native float nativeGetCogY();
+
+ protected native float nativeGetCogZ();
+
+ protected native float nativeGetMoiX();
+
+ protected native float nativeGetMoiY();
+
+ protected native float nativeGetMoiZ();
+
+ @Override
+ public void prerender(Camera cam) {
+ if (!this.lastURL.equals(this.url.toString()) || this.avatarSwitchPending) {
+ this.lastURL = new String(this.url.toString());
+ System.out.println("Analyze shape " + this.lastURL);
+ this.nativeAnalyzeShape(this.clumpID, this.mass);
+ this.tirePositions = new Point3[4];
+
+ for (int i = 0; i < 4; i++) {
+ this.tirePositions[i] = new Point3(this.nativeGetTirePosX(i), this.nativeGetTirePosY(i), this.nativeGetTirePosZ(i));
+ }
+
+ this.centerOfGravity = new Point3(this.nativeGetCogX(), this.nativeGetCogY(), this.nativeGetCogZ());
+ this.centerOfGravity.x = this.centerOfGravity.x + this.adjustCogX;
+ this.centerOfGravity.y = this.centerOfGravity.y + this.adjustCogY;
+ this.centerOfGravity.z = this.centerOfGravity.z + this.adjustCogZ;
+ this.momentsOfInertia = new Point3(this.nativeGetMoiX(), this.nativeGetMoiY(), this.nativeGetMoiZ());
+ if (this.avatarSwitchPending) {
+ Pilot p = Console.getActive().getPilot();
+ if (p instanceof HoloPilot) {
+ HoloPilot hp = (HoloPilot)p;
+ Drone d = hp.getInternalDrone();
+ if (d != null && d instanceof PosableDrone) {
+ PosableDrone pd = (PosableDrone)d;
+ PosableShape ps = pd.getInternalPosableShape();
+ if (ps != null && ps instanceof VehicleShape) {
+ VehicleShape vs = (VehicleShape)ps;
+ vs.fixedCamera = this.fixedCamera;
+ vs.camX = this.camX;
+ vs.camY = this.camY;
+ vs.camZ = this.camZ;
+ vs.camRoll = this.camRoll;
+ vs.camPitch = this.camPitch;
+ vs.camYaw = this.camYaw;
+ vs.camAimX = this.camAimX;
+ vs.camAimY = this.camAimY;
+ vs.camAimZ = this.camAimZ;
+ vs.eyeHeight = this.eyeHeight;
+ hp.setOutsideCameraMode(99, 4);
+ }
+ }
+ }
+
+ this.avatarSwitchPending = false;
+ }
+ }
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Prompt String"));
+ } else if (mode == 1) {
+ ret = new String(this.promptString);
+ } else if (mode == 2) {
+ this.promptString = new String((String)value);
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Rear End Ratio"));
+ } else if (mode == 1) {
+ ret = new Float(this.rearEndRatio);
+ } else if (mode == 2) {
+ this.rearEndRatio = (Float)value;
+ }
+ break;
+ case 2:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Frontal Area (sq.ft.)"));
+ } else if (mode == 1) {
+ ret = new Float(this.frontalArea);
+ } else if (mode == 2) {
+ this.frontalArea = (Float)value;
+ }
+ break;
+ case 3:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Wheel Diameter (ft.)"));
+ } else if (mode == 1) {
+ ret = new Float(this.wheelDiameter);
+ } else if (mode == 2) {
+ this.wheelDiameter = (Float)value;
+ }
+ break;
+ case 4:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Coefficient of Kinetic Friction"));
+ } else if (mode == 1) {
+ ret = new Float(this.coeffKineticFriction);
+ } else if (mode == 2) {
+ this.coeffKineticFriction = (Float)value;
+ }
+ break;
+ case 5:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Coefficient of Static Friction"));
+ } else if (mode == 1) {
+ ret = new Float(this.coeffStaticFriction);
+ } else if (mode == 2) {
+ this.coeffStaticFriction = (Float)value;
+ }
+ break;
+ case 6:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Mass (slugs)"));
+ } else if (mode == 1) {
+ ret = new Float(this.mass);
+ } else if (mode == 2) {
+ this.mass = (Float)value;
+ }
+ break;
+ case 7:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "1st Gear Ratio"));
+ } else if (mode == 1) {
+ ret = new Float(this.gearRatio1);
+ } else if (mode == 2) {
+ this.gearRatio1 = (Float)value;
+ }
+ break;
+ case 8:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "2nd Gear Ratio"));
+ } else if (mode == 1) {
+ ret = new Float(this.gearRatio2);
+ } else if (mode == 2) {
+ this.gearRatio2 = (Float)value;
+ }
+ break;
+ case 9:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "3rd Gear Ratio"));
+ } else if (mode == 1) {
+ ret = new Float(this.gearRatio3);
+ } else if (mode == 2) {
+ this.gearRatio3 = (Float)value;
+ }
+ break;
+ case 10:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "4th Gear Ratio"));
+ } else if (mode == 1) {
+ ret = new Float(this.gearRatio4);
+ } else if (mode == 2) {
+ this.gearRatio4 = (Float)value;
+ }
+ break;
+ case 11:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "5th Gear Ratio"));
+ } else if (mode == 1) {
+ ret = new Float(this.gearRatio5);
+ } else if (mode == 2) {
+ this.gearRatio5 = (Float)value;
+ }
+ break;
+ case 12:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Max. Engine Torque (ft-lbs)"));
+ } else if (mode == 1) {
+ ret = new Float(this.maxEngineTorque);
+ } else if (mode == 2) {
+ this.maxEngineTorque = (Float)value;
+ }
+ break;
+ case 13:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Tire Adhesive Limit"));
+ } else if (mode == 1) {
+ ret = new Float(this.tireAdhesiveLimit);
+ } else if (mode == 2) {
+ this.tireAdhesiveLimit = (Float)value;
+ }
+ break;
+ case 14:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Shocks Damping Coefficient"));
+ } else if (mode == 1) {
+ ret = new Float(this.shockDampingCoeff);
+ } else if (mode == 2) {
+ this.shockDampingCoeff = (Float)value;
+ }
+ break;
+ case 15:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Shock Length (ft)"));
+ } else if (mode == 1) {
+ ret = new Float(this.shockLength);
+ } else if (mode == 2) {
+ this.shockLength = (Float)value;
+ }
+ break;
+ case 16:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Torque Peak (RPM)"));
+ } else if (mode == 1) {
+ ret = new Float(this.rpmTorquePeak);
+ } else if (mode == 2) {
+ this.rpmTorquePeak = (Float)value;
+ }
+ break;
+ case 17:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Idle RPM"));
+ } else if (mode == 1) {
+ ret = new Float(this.idleRPM);
+ } else if (mode == 2) {
+ this.idleRPM = (Float)value;
+ }
+ break;
+ case 18:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Transmission Type"), "Automatic", "Manual");
+ } else if (mode == 1) {
+ ret = new Boolean(this.stickShift);
+ } else if (mode == 2) {
+ this.stickShift = (Boolean)value;
+ }
+ break;
+ case 19:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Gas (Gall., -1 for infinite)"));
+ } else if (mode == 1) {
+ ret = new Float(this.initialGas);
+ } else if (mode == 2) {
+ this.initialGas = (Float)value;
+ }
+ break;
+ case 20:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Center of gravity X adjust"));
+ } else if (mode == 1) {
+ ret = new Float(this.adjustCogX);
+ } else if (mode == 2) {
+ this.adjustCogX = (Float)value;
+ }
+ break;
+ case 21:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Center of gravity Y adjust"));
+ } else if (mode == 1) {
+ ret = new Float(this.adjustCogY);
+ } else if (mode == 2) {
+ this.adjustCogY = (Float)value;
+ }
+ break;
+ case 22:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Center of gravity Z adjust"));
+ } else if (mode == 1) {
+ ret = new Float(this.adjustCogZ);
+ } else if (mode == 2) {
+ this.adjustCogZ = (Float)value;
+ }
+ break;
+ case 23:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Use fixed camera"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(this.fixedCamera);
+ } else if (mode == 2) {
+ this.fixedCamera = (Boolean)value;
+ }
+ break;
+ case 24:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Camera X offset"));
+ } else if (mode == 1) {
+ ret = new Float(this.camX);
+ } else if (mode == 2) {
+ this.camX = (Float)value;
+ }
+ break;
+ case 25:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Camera Y offset"));
+ } else if (mode == 1) {
+ ret = new Float(this.camY);
+ } else if (mode == 2) {
+ this.camY = (Float)value;
+ }
+ break;
+ case 26:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Camera Z offset"));
+ } else if (mode == 1) {
+ ret = new Float(this.camZ);
+ } else if (mode == 2) {
+ this.camZ = (Float)value;
+ }
+ break;
+ case 27:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Camera Roll"));
+ } else if (mode == 1) {
+ ret = new Float(this.camRoll);
+ } else if (mode == 2) {
+ this.camRoll = (Float)value;
+ }
+ break;
+ case 28:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Camera Pitch"));
+ } else if (mode == 1) {
+ ret = new Float(this.camPitch);
+ } else if (mode == 2) {
+ this.camPitch = (Float)value;
+ }
+ break;
+ case 29:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Camera Yaw"));
+ } else if (mode == 1) {
+ ret = new Float(this.camYaw);
+ } else if (mode == 2) {
+ this.camYaw = (Float)value;
+ }
+ break;
+ case 30:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Camera Aim X"));
+ } else if (mode == 1) {
+ ret = new Float(this.camAimX);
+ } else if (mode == 2) {
+ this.camAimX = (Float)value;
+ }
+ break;
+ case 31:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Camera Aim Y"));
+ } else if (mode == 1) {
+ ret = new Float(this.camAimY);
+ } else if (mode == 2) {
+ this.camAimY = (Float)value;
+ }
+ break;
+ case 32:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Camera Aim Z"));
+ } else if (mode == 1) {
+ ret = new Float(this.camAimZ);
+ } else if (mode == 2) {
+ this.camAimZ = (Float)value;
+ }
+ break;
+ case 33:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Camera Eye Height"));
+ } else if (mode == 1) {
+ ret = new Float(this.eyeHeight);
+ } else if (mode == 2) {
+ this.eyeHeight = (Float)value;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 34, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(2, classCookie);
+ s.saveBoolean(this.fixedCamera);
+ s.saveFloat(this.camX);
+ s.saveFloat(this.camY);
+ s.saveFloat(this.camZ);
+ s.saveFloat(this.camRoll);
+ s.saveFloat(this.camPitch);
+ s.saveFloat(this.camYaw);
+ s.saveFloat(this.camAimX);
+ s.saveFloat(this.camAimY);
+ s.saveFloat(this.camAimZ);
+ s.saveFloat(this.eyeHeight);
+ s.saveString(this.promptString);
+ s.saveFloat(this.rearEndRatio);
+ s.saveFloat(this.frontalArea);
+ s.saveFloat(this.wheelDiameter);
+ s.saveFloat(this.coeffKineticFriction);
+ s.saveFloat(this.coeffStaticFriction);
+ s.saveFloat(this.mass);
+ s.saveFloat(this.gearRatio1);
+ s.saveFloat(this.gearRatio2);
+ s.saveFloat(this.gearRatio3);
+ s.saveFloat(this.gearRatio4);
+ s.saveFloat(this.gearRatio5);
+ s.saveFloat(this.maxEngineTorque);
+ s.saveFloat(this.tireAdhesiveLimit);
+ s.saveFloat(this.shockDampingCoeff);
+ s.saveFloat(this.shockLength);
+ s.saveFloat(this.rpmTorquePeak);
+ s.saveFloat(this.idleRPM);
+ s.saveBoolean(this.stickShift);
+ s.saveFloat(this.initialGas);
+ s.saveFloat(this.adjustCogX);
+ s.saveFloat(this.adjustCogY);
+ s.saveFloat(this.adjustCogZ);
+ super.saveState(s);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 2:
+ this.fixedCamera = r.restoreBoolean();
+ this.camX = r.restoreFloat();
+ this.camY = r.restoreFloat();
+ this.camZ = r.restoreFloat();
+ this.camRoll = r.restoreFloat();
+ this.camPitch = r.restoreFloat();
+ this.camYaw = r.restoreFloat();
+ this.camAimX = r.restoreFloat();
+ this.camAimY = r.restoreFloat();
+ this.camAimZ = r.restoreFloat();
+ this.eyeHeight = r.restoreFloat();
+ case 1:
+ this.promptString = r.restoreString();
+ this.rearEndRatio = r.restoreFloat();
+ this.frontalArea = r.restoreFloat();
+ this.wheelDiameter = r.restoreFloat();
+ this.coeffKineticFriction = r.restoreFloat();
+ this.coeffStaticFriction = r.restoreFloat();
+ this.mass = r.restoreFloat();
+ this.gearRatio1 = r.restoreFloat();
+ this.gearRatio2 = r.restoreFloat();
+ this.gearRatio3 = r.restoreFloat();
+ this.gearRatio4 = r.restoreFloat();
+ this.gearRatio5 = r.restoreFloat();
+ this.maxEngineTorque = r.restoreFloat();
+ this.tireAdhesiveLimit = r.restoreFloat();
+ this.shockDampingCoeff = r.restoreFloat();
+ this.shockLength = r.restoreFloat();
+ this.rpmTorquePeak = r.restoreFloat();
+ this.idleRPM = r.restoreFloat();
+ this.stickShift = r.restoreBoolean();
+ this.initialGas = r.restoreFloat();
+ this.adjustCogX = r.restoreFloat();
+ this.adjustCogY = r.restoreFloat();
+ this.adjustCogZ = r.restoreFloat();
+ case 0:
+ super.restoreState(r);
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/VelocityBehavior.java b/NET/worlds/scape/VelocityBehavior.java
new file mode 100644
index 0000000..9858355
--- /dev/null
+++ b/NET/worlds/scape/VelocityBehavior.java
@@ -0,0 +1,260 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+public class VelocityBehavior extends SwitchableBehavior implements FrameHandler, BumpHandler {
+ private RollingAttribute attr;
+ private long lastTime;
+ public float linearVel;
+ public float linearDamp;
+ protected Point3 dir;
+ public float angularVel;
+ public float angularDamp;
+ public Point3 axis;
+ private boolean bumplock = false;
+ private static Object classCookie = new Object();
+
+ public VelocityBehavior(
+ Point3Temp linearVectorPerSecond, float linearDampingPerSecond, Point3Temp angularAxis, float angularDegPerSecond, float angularDampingPerSecond
+ ) {
+ this.dir = new Point3();
+ this.linearVel = 0.0F;
+ this.linearDamp = linearDampingPerSecond;
+ this.addVelocity(linearVectorPerSecond);
+ this.axis = new Point3(angularAxis);
+ this.axis.normalize();
+ this.angularVel = angularDegPerSecond;
+ this.angularDamp = angularDampingPerSecond;
+ }
+
+ public VelocityBehavior() {
+ this(Point3Temp.make(0.0F, 0.0F, 0.0F));
+ }
+
+ public VelocityBehavior(Point3Temp vel) {
+ this(vel, 0.0F, Point3Temp.make(0.0F, 0.0F, 1.0F), 0.0F, 0.0F);
+ }
+
+ public void setDir(Point3Temp d) {
+ double len = Math.sqrt(d.x * d.x + d.y * d.y + d.z * d.z);
+ if (len == 0.0) {
+ this.dir.x = 0.0F;
+ this.dir.y = 0.0F;
+ this.dir.z = 0.0F;
+ } else {
+ this.dir.x = (float)(d.x / len);
+ this.dir.y = (float)(d.y / len);
+ this.dir.z = (float)(d.z / len);
+ }
+ }
+
+ public VelocityBehavior addVelocity(Point3Temp vector) {
+ this.dir.times(this.linearVel).plus(vector);
+ float len = this.dir.length();
+ if (len > 0.0F) {
+ this.dir.dividedBy(len);
+ }
+
+ this.linearVel = len;
+ return this;
+ }
+
+ public void setNotifyAttribute(RollingAttribute attr) {
+ this.attr = attr;
+ }
+
+ @Override
+ public boolean handle(FrameEvent e) {
+ this.bumplock = false;
+ WObject o = e.receiver;
+ float dT = (float)(e.time - this.lastTime) / 1000.0F;
+ if (this.lastTime == 0L) {
+ this.lastTime = e.time;
+ return true;
+ } else {
+ this.lastTime = e.time;
+ if (this.linearVel != 0.0F) {
+ Point3Temp dist = Point3Temp.make(this.dir).times(dT * this.linearVel);
+ o.moveThrough(dist);
+ if (this.linearDamp != 0.0F) {
+ this.linearVel = (float)(this.linearVel * Math.exp(-this.linearDamp * dT));
+ if (Math.abs(this.linearVel) < this.linearDamp * 16.0F) {
+ this.linearVel = 0.0F;
+ if (this.attr != null) {
+ this.attr.notifyStopped();
+ }
+ }
+ }
+ }
+
+ if (this.angularVel != 0.0F) {
+ o.spin(this.axis.x, this.axis.y, this.axis.z, this.angularVel * dT);
+ if (this.angularDamp != 0.0F) {
+ this.angularVel = (float)(this.angularVel * Math.exp(-this.angularDamp * dT));
+ if (Math.abs(this.angularVel) < this.angularDamp * 0.6F) {
+ this.angularVel = 0.0F;
+ }
+ }
+ }
+
+ return true;
+ }
+ }
+
+ @Override
+ public boolean handle(BumpEventTemp b) {
+ if (this.bumplock) {
+ return true;
+ } else {
+ if (this.attr != null) {
+ this.attr.handle(b);
+ } else {
+ this.processBumpEvent(b);
+ }
+
+ this.bumplock = true;
+ return true;
+ }
+ }
+
+ public void processBumpEvent(BumpEventTemp b) {
+ b.postBumpPath.minus(b.postBumpPath);
+ if (this.dir.x != 0.0F || this.dir.y != 0.0F || this.dir.z != 0.0F) {
+ WObject bumper = b.receiver == b.target ? (WObject)b.source : b.target;
+ Point3Temp norm;
+ if (!(bumper instanceof Camera) && !(bumper instanceof Hologram)) {
+ norm = Point3Temp.make(b.bumpNormal);
+ } else {
+ float orientation = (float)((360.0F - bumper.getYaw() + 90.0F) * Math.PI / 180.0);
+ norm = Point3Temp.make((float)Math.cos(orientation), (float)Math.sin(orientation), 0.0F);
+ }
+
+ float lb = (float)Math.sqrt(norm.x * norm.x + norm.y * norm.y + norm.z * norm.z);
+ norm.x /= lb;
+ norm.y /= lb;
+ norm.z /= lb;
+ float projection = Math.abs(this.dir.x * norm.x + this.dir.y * norm.y + this.dir.z * norm.z);
+ this.dir.x = this.dir.x + norm.x * 2.0F * projection;
+ this.dir.y = this.dir.y + norm.y * 2.0F * projection;
+ this.dir.z = this.dir.z + norm.z * 2.0F * projection;
+ double n = Math.sqrt(this.dir.x * this.dir.x + this.dir.y * this.dir.y + this.dir.z * this.dir.z);
+ if (n != 0.0) {
+ this.dir.x = (float)(this.dir.x / n);
+ this.dir.y = (float)(this.dir.y / n);
+ this.dir.z = (float)(this.dir.z / n);
+ }
+ }
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Linear Velocity"));
+ } else if (mode == 1) {
+ ret = new Float(this.linearVel);
+ } else if (mode == 2) {
+ this.linearVel = (Float)value;
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Linear Damping"));
+ } else if (mode == 1) {
+ ret = new Float(this.linearDamp);
+ } else if (mode == 2) {
+ this.linearDamp = (Float)value;
+ }
+ break;
+ case 2:
+ if (mode == 0) {
+ ret = Point3PropertyEditor.make(new Property(this, index, "Direction"));
+ } else if (mode == 1) {
+ ret = new Point3(this.dir);
+ } else if (mode == 2) {
+ this.dir = (Point3)value;
+ }
+ break;
+ case 3:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Angular Velocity"));
+ } else if (mode == 1) {
+ ret = new Float(this.angularVel);
+ } else if (mode == 2) {
+ this.angularVel = (Float)value;
+ }
+ break;
+ case 4:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Angular Damping"));
+ } else if (mode == 1) {
+ ret = new Float(this.angularDamp);
+ } else if (mode == 2) {
+ this.angularDamp = (Float)value;
+ }
+ break;
+ case 5:
+ if (mode == 0) {
+ ret = Point3PropertyEditor.make(new Property(this, index, "Axis"));
+ } else if (mode == 1) {
+ ret = new Point3(this.axis);
+ } else if (mode == 2) {
+ this.axis = (Point3)value;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 6, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public String toString() {
+ return super.toString()
+ + "[lin. velocity "
+ + this.linearVel
+ + ", lin. damp "
+ + this.linearDamp
+ + ", direction "
+ + this.dir
+ + ", ang. vel "
+ + this.angularVel
+ + ", ang. damp "
+ + this.angularDamp
+ + ", axis "
+ + this.axis
+ + "]";
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(0, classCookie);
+ super.saveState(s);
+ s.saveFloat(this.linearVel);
+ s.saveFloat(this.linearDamp);
+ s.save(this.dir);
+ s.saveFloat(this.angularVel);
+ s.saveFloat(this.angularDamp);
+ s.save(this.axis);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ this.linearVel = r.restoreFloat();
+ this.linearDamp = r.restoreFloat();
+ this.dir = (Point3)r.restore();
+ this.angularVel = r.restoreFloat();
+ this.angularDamp = r.restoreFloat();
+ this.axis = (Point3)r.restore();
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/VideoControlAction.java b/NET/worlds/scape/VideoControlAction.java
new file mode 100644
index 0000000..e0e79f3
--- /dev/null
+++ b/NET/worlds/scape/VideoControlAction.java
@@ -0,0 +1,115 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+public class VideoControlAction extends Action {
+ private final int play = 1;
+ private final int stop = 2;
+ private int mode = 1;
+ private int repeat = 1;
+ private VideoTexture videoTexture = null;
+ private VideoWall videoWall = null;
+ private static Object classCookie = new Object();
+
+ VideoControlAction() {
+ }
+
+ @Override
+ public Persister trigger(Event e, Persister seqID) {
+ if (!this.getVideoTexture()) {
+ System.out.println("ERROR! Tried to attach VideoControlAction to something other than a Rect with a VideoTexture. or a VideoWall object.");
+ return null;
+ } else {
+ switch (this.mode) {
+ case 1:
+ if (this.videoTexture == null) {
+ this.videoWall.getVideoSurface().play(this.repeat);
+ } else {
+ this.videoTexture.getDirectShow().nPlay(this.repeat);
+ }
+ break;
+ case 2:
+ if (this.videoTexture == null) {
+ this.videoWall.getVideoSurface().stop();
+ } else {
+ this.videoTexture.getDirectShow().nStop();
+ }
+ }
+
+ return null;
+ }
+ }
+
+ private boolean getVideoTexture() {
+ if (this.videoTexture != null) {
+ return true;
+ } else {
+ Object owner = this.getOwner();
+ if (owner != null && owner instanceof Rect) {
+ Rect r = (Rect)owner;
+ this.videoTexture = r.getVideoAttribute();
+ if (this.videoTexture != null) {
+ return true;
+ } else if (owner instanceof VideoWall) {
+ this.videoWall = (VideoWall)owner;
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(1, classCookie);
+ super.saveState(s);
+ s.saveInt(this.mode);
+ s.saveInt(this.repeat);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ this.mode = r.restoreInt();
+ break;
+ case 1:
+ super.restoreState(r);
+ this.mode = r.restoreInt();
+ this.repeat = r.restoreInt();
+ }
+ }
+
+ @Override
+ public Object properties(int index, int offset, int pmode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (pmode == 0) {
+ ret = IntegerPropertyEditor.make(new Property(this, index, "1=Play, 2=Stop"));
+ } else if (pmode == 1) {
+ ret = new Integer(this.mode);
+ } else if (pmode == 2) {
+ this.mode = (Integer)value;
+ }
+ break;
+ case 1:
+ if (pmode == 0) {
+ ret = IntegerPropertyEditor.make(new Property(this, index, "Repeat count (-1 for infinite)"));
+ } else if (pmode == 1) {
+ ret = new Integer(this.repeat);
+ } else if (pmode == 2) {
+ this.repeat = (Integer)value;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 2, pmode, value);
+ }
+
+ return ret;
+ }
+}
diff --git a/NET/worlds/scape/VideoManager.java b/NET/worlds/scape/VideoManager.java
new file mode 100644
index 0000000..b69cfc4
--- /dev/null
+++ b/NET/worlds/scape/VideoManager.java
@@ -0,0 +1,29 @@
+package NET.worlds.scape;
+
+import java.util.Hashtable;
+
+public class VideoManager {
+ static Hashtable streams = new Hashtable();
+
+ public static VideoSurface get(String url, int rows, int w, int h) {
+ Object ob = streams.get(url);
+ VideoSurface stream;
+ if (ob == null) {
+ stream = new VideoSurface(null, rows, w, h);
+ streams.put(url, stream);
+ } else {
+ stream = (VideoSurface)ob;
+ }
+
+ stream.incReferenceCount();
+ stream.open(url);
+ return stream;
+ }
+
+ public static void release(VideoSurface stream) {
+ stream.decReferenceCount();
+ if (stream.getReferenceCount() == 0) {
+ streams.remove(stream.getVideoUrl());
+ }
+ }
+}
diff --git a/NET/worlds/scape/VideoSurface.java b/NET/worlds/scape/VideoSurface.java
new file mode 100644
index 0000000..0bf2528
--- /dev/null
+++ b/NET/worlds/scape/VideoSurface.java
@@ -0,0 +1,53 @@
+package NET.worlds.scape;
+
+public class VideoSurface extends TextureSurface {
+ protected DirectShow _ds;
+ protected String _currentURL;
+ protected int referenceCount = 0;
+
+ public VideoSurface(Texture[] texList, int rows, int w, int h) {
+ super(texList, rows, w, h);
+ this._ds = new DirectShow(this.getHwnd());
+ }
+
+ public void incReferenceCount() {
+ this.referenceCount++;
+ }
+
+ public void decReferenceCount() {
+ this.referenceCount--;
+ }
+
+ public int getReferenceCount() {
+ return this.referenceCount;
+ }
+
+ public int tick() {
+ return this._ds.nTick();
+ }
+
+ public String getVideoUrl() {
+ return this._currentURL;
+ }
+
+ public void open(String url) {
+ if (this._currentURL == null || !this._currentURL.equals(url)) {
+ this._ds.nStop();
+ this._ds.nOpen(url);
+ this._currentURL = url;
+ }
+ }
+
+ public void stop() {
+ this._ds.nStop();
+ }
+
+ public void play(int repeat) {
+ this._ds.nPlay(repeat);
+ }
+
+ public synchronized void draw(Texture[] texList, int rows) {
+ this.setTextures(texList, rows);
+ this.draw(this._ds);
+ }
+}
diff --git a/NET/worlds/scape/VideoTexture.java b/NET/worlds/scape/VideoTexture.java
new file mode 100644
index 0000000..cfa07f9
--- /dev/null
+++ b/NET/worlds/scape/VideoTexture.java
@@ -0,0 +1,232 @@
+package NET.worlds.scape;
+
+import NET.worlds.core.IniFile;
+import NET.worlds.network.URL;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class VideoTexture extends Attribute {
+ DirectShow _ds = null;
+ TextureSurface _surface;
+ Texture[] _textures;
+ Material _material = null;
+ String _textureURL = "http://dev.worlds.net/rr-worlds/video/eminem.asf";
+ String _defTextureURL = IniFile.override().getIniString("defaultAd", "adworlds.cmp");
+ int _xSurface = 128;
+ int _ySurface = 128;
+ boolean _autoPlay = true;
+ int _rows = 1;
+ private static Object classCookie = new Object();
+
+ public VideoTexture(int attrID) {
+ super(attrID);
+ }
+
+ public VideoTexture() {
+ }
+
+ @Override
+ protected void noteAddingTo(SuperRoot owner) {
+ Rect s = (Rect)((Sharer)owner).getOwner();
+ s._videoAttribute = this;
+ this.assignMaterial(s);
+ }
+
+ private void assignMaterial(Rect s) {
+ int xTex = this._xSurface / 128;
+ if (xTex < 1) {
+ xTex = 1;
+ }
+
+ int yTex = this._ySurface / 128;
+ if (yTex < 1) {
+ yTex = 1;
+ }
+
+ this._surface = null;
+ this._ds = null;
+ this._rows = yTex;
+ this._material = new Material(URL.make(this._defTextureURL), xTex, yTex);
+ s.setMaterial(this._material);
+ this._textures = this._material.getTextures();
+ this._surface = new TextureSurface(this._textures, yTex, this._xSurface, this._ySurface);
+ this._ds = new DirectShow(this._surface.getHwnd());
+ this._ds.nOpen(this._textureURL);
+ if (this._autoPlay) {
+ this._ds.nPlay(1);
+ }
+ }
+
+ private void setTexture() {
+ Sharer sh = (Sharer)this.getOwner();
+ if (sh != null) {
+ Rect s = (Rect)sh.getOwner();
+ this.assignMaterial(s);
+ }
+ }
+
+ @Override
+ public void detach() {
+ Rect s = (Rect)((Sharer)this.getOwner()).getOwner();
+ s._videoAttribute = null;
+ if (this._ds != null) {
+ this._ds.nStop();
+ this._ds = null;
+ }
+
+ super.detach();
+ }
+
+ @Override
+ public void finalize() {
+ this.releaseAuxilaryData();
+ super.finalize();
+ }
+
+ public DirectShow getDirectShow() {
+ return this._ds;
+ }
+
+ public void videoFrame(FrameEvent f) {
+ this.draw();
+ }
+
+ @Override
+ public final void noteChange() {
+ }
+
+ public synchronized void draw() {
+ if (this._surface != null && this._ds != null) {
+ this._surface.setTextures(this._material.getTextures(), this._rows);
+ this._surface.draw(this._ds);
+ }
+ }
+
+ @Override
+ public void generateNetData(DataOutputStream s) throws IOException {
+ s.writeUTF(this._textureURL);
+ s.writeInt(this._xSurface);
+ s.writeInt(this._ySurface);
+ }
+
+ @Override
+ public void setFromNetData(DataInputStream ds, int len) throws IOException {
+ this._textureURL = ds.readUTF();
+ this._xSurface = ds.readInt();
+ this._ySurface = ds.readInt();
+ this.noteChange();
+ this.setTexture();
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Texture URL"));
+ } else if (mode == 1) {
+ ret = this._textureURL;
+ } else if (mode == 2) {
+ this._textureURL = (String)value;
+ this.setTexture();
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = IntegerPropertyEditor.make(new Property(this, index, "Texture Width"), 0, 1024);
+ } else if (mode == 1) {
+ ret = new Integer(this._xSurface);
+ } else if (mode == 2) {
+ this._xSurface = (Integer)value;
+ this.setTexture();
+ }
+ break;
+ case 2:
+ if (mode == 0) {
+ ret = IntegerPropertyEditor.make(new Property(this, index, "Texture Height"), 0, 1024);
+ } else if (mode == 1) {
+ ret = new Integer(this._ySurface);
+ } else if (mode == 2) {
+ this._ySurface = (Integer)value;
+ this.setTexture();
+ }
+ break;
+ case 3:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Auto-play?"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(this._autoPlay);
+ } else if (mode == 2) {
+ this._autoPlay = (Boolean)value;
+ this.setTexture();
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 4, mode, value);
+ }
+
+ if (mode == 2) {
+ this.noteChange();
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(1, classCookie);
+ super.saveState(s);
+ s.saveString(this._textureURL);
+ s.saveInt(this._xSurface);
+ s.saveInt(this._ySurface);
+ s.saveBoolean(this._autoPlay);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ this._textureURL = r.restoreString();
+ this._xSurface = r.restoreInt();
+ this._ySurface = r.restoreInt();
+ this.noteChange();
+ break;
+ case 1:
+ super.restoreState(r);
+ this._textureURL = r.restoreString();
+ this._xSurface = r.restoreInt();
+ this._ySurface = r.restoreInt();
+ this._autoPlay = r.restoreBoolean();
+ this.noteChange();
+ break;
+ default:
+ throw new TooNewException();
+ }
+
+ this.setTexture();
+ }
+
+ @Override
+ public void releaseAuxilaryData() {
+ if (this._ds != null) {
+ this._ds.nStop();
+ this._ds = null;
+ }
+
+ if (this._surface != null) {
+ this._surface.finalize();
+ this._surface = null;
+ }
+
+ if (this._material != null) {
+ this._material.detach();
+ this._material.finalize();
+ this._material = null;
+ }
+
+ this._textures = null;
+ }
+}
diff --git a/NET/worlds/scape/VideoWall.java b/NET/worlds/scape/VideoWall.java
new file mode 100644
index 0000000..9969c71
--- /dev/null
+++ b/NET/worlds/scape/VideoWall.java
@@ -0,0 +1,191 @@
+package NET.worlds.scape;
+
+import NET.worlds.core.IniFile;
+import NET.worlds.network.URL;
+import java.io.IOException;
+
+public class VideoWall extends Rect {
+ VideoSurface _surface = null;
+ Texture[] _textures;
+ Material _material = null;
+ String _textureURL = "http://dev.worlds.net/rr-worlds/video/fatboy.asf";
+ String _defTextureURL = IniFile.override().getIniString("defaultAd", "adworlds.cmp");
+ int _xSurface = 140;
+ int _ySurface = 104;
+ boolean _autoPlay = true;
+ int _autoPlayRepeats = 1;
+ int _rows = 1;
+ private static Object classCookie = new Object();
+
+ private void rebuild() {
+ this.unbuild();
+ int xTex = this._xSurface / 128 + 1;
+ int yTex = this._ySurface / 128 + 1;
+ this._surface = null;
+ this._rows = yTex;
+ this._material = new Material(URL.make(this._defTextureURL), xTex, yTex);
+ this.setMaterial(this._material);
+ this._textures = this._material.getTextures();
+ this._surface = VideoManager.get(this._textureURL, yTex, this._xSurface, this._ySurface);
+ if (this._autoPlay) {
+ this._surface.play(1);
+ }
+ }
+
+ @Override
+ public void finalize() {
+ this.unbuild();
+ super.finalize();
+ }
+
+ @Override
+ public void detach() {
+ this.unbuild();
+ super.detach();
+ }
+
+ private void unbuild() {
+ if (this._surface != null) {
+ this._surface.stop();
+ VideoManager.release(this._surface);
+ this._surface = null;
+ }
+ }
+
+ public void changeURL(String newURL, int width, int height) {
+ this._textureURL = new String(newURL);
+ this._xSurface = width;
+ this._ySurface = height;
+ this.rebuild();
+ }
+
+ @Override
+ public boolean handle(FrameEvent f) {
+ this.getState();
+ if (this.visible) {
+ this.draw();
+ }
+
+ return false;
+ }
+
+ @Override
+ public void prerender(Camera cam) {
+ Point3Temp p = this.inCamSpace(cam);
+ boolean v = p != null && p.z > 1.0F && p.x < p.z && -p.x < p.z;
+ if (v) {
+ this.visible = true;
+ }
+ }
+
+ public VideoSurface getVideoSurface() {
+ return this._surface;
+ }
+
+ public synchronized void draw() {
+ if (this._surface != null) {
+ this._surface.draw(this._material.getTextures(), this._rows);
+ }
+ }
+
+ public int getState() {
+ return this._surface != null ? this._surface.tick() : 0;
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Video URL"));
+ } else if (mode == 1) {
+ ret = this._textureURL;
+ } else if (mode == 2) {
+ this._textureURL = (String)value;
+ this.rebuild();
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = IntegerPropertyEditor.make(new Property(this, index, "Video Width (pixels)"), 0, 1024);
+ } else if (mode == 1) {
+ ret = new Integer(this._xSurface);
+ } else if (mode == 2) {
+ this._xSurface = (Integer)value;
+ this.rebuild();
+ }
+ break;
+ case 2:
+ if (mode == 0) {
+ ret = IntegerPropertyEditor.make(new Property(this, index, "Video Height (pixels)"), 0, 1024);
+ } else if (mode == 1) {
+ ret = new Integer(this._ySurface);
+ } else if (mode == 2) {
+ this._ySurface = (Integer)value;
+ this.rebuild();
+ }
+ break;
+ case 3:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Auto-play?"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(this._autoPlay);
+ } else if (mode == 2) {
+ this._autoPlay = (Boolean)value;
+ this.rebuild();
+ }
+ break;
+ case 4:
+ if (mode == 0) {
+ ret = IntegerPropertyEditor.make(new Property(this, index, "Repeats for Autoplay (-1 = infinite)"), -1, 1024);
+ } else if (mode == 1) {
+ ret = new Integer(this._autoPlayRepeats);
+ } else if (mode == 2) {
+ this._autoPlayRepeats = (Integer)value;
+ this.rebuild();
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 5, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(1, classCookie);
+ super.saveState(s);
+ s.saveString(this._textureURL);
+ s.saveInt(this._xSurface);
+ s.saveInt(this._ySurface);
+ s.saveBoolean(this._autoPlay);
+ s.saveInt(this._autoPlayRepeats);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ this._textureURL = r.restoreString();
+ this._xSurface = r.restoreInt();
+ this._ySurface = r.restoreInt();
+ this._autoPlay = r.restoreBoolean();
+ break;
+ case 1:
+ super.restoreState(r);
+ this._textureURL = r.restoreString();
+ this._xSurface = r.restoreInt();
+ this._ySurface = r.restoreInt();
+ this._autoPlay = r.restoreBoolean();
+ this._autoPlayRepeats = r.restoreInt();
+ break;
+ default:
+ throw new TooNewException();
+ }
+
+ this.rebuild();
+ }
+}
diff --git a/NET/worlds/scape/VisiAttribute.java b/NET/worlds/scape/VisiAttribute.java
new file mode 100644
index 0000000..60c9fdb
--- /dev/null
+++ b/NET/worlds/scape/VisiAttribute.java
@@ -0,0 +1,56 @@
+package NET.worlds.scape;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class VisiAttribute extends Attribute {
+ private static Object classCookie = new Object();
+
+ public VisiAttribute(int attrID) {
+ super(attrID);
+ }
+
+ public VisiAttribute() {
+ }
+
+ @Override
+ protected void noteAddingTo(SuperRoot owner) {
+ WObject w = (WObject)((Sharer)owner).getOwner();
+ w._visibilityAttribute = this;
+ }
+
+ @Override
+ public void detach() {
+ WObject w = (WObject)((Sharer)this.getOwner()).getOwner();
+ w._visibilityAttribute = null;
+ super.detach();
+ }
+
+ @Override
+ public void generateNetData(DataOutputStream s) throws IOException {
+ s.writeBoolean(((WObject)this.getOwner().getOwner()).getVisible());
+ }
+
+ @Override
+ public void setFromNetData(DataInputStream ds, int len) throws IOException {
+ ((WObject)this.getOwner().getOwner()).setVisible(ds.readBoolean());
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(0, classCookie);
+ super.saveState(s);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/WMPSoundPlayer.java b/NET/worlds/scape/WMPSoundPlayer.java
new file mode 100644
index 0000000..9f5fadf
--- /dev/null
+++ b/NET/worlds/scape/WMPSoundPlayer.java
@@ -0,0 +1,65 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.WebControlImp;
+import NET.worlds.network.URL;
+
+public class WMPSoundPlayer extends SoundPlayer {
+ protected DirectShow ds;
+ protected boolean disabled;
+ static int activeCount = 0;
+ boolean playing = false;
+
+ public WMPSoundPlayer(Sound owner) {
+ super(owner);
+ this.ds = new DirectShow();
+ }
+
+ public static boolean isActive() {
+ return activeCount > 0;
+ }
+
+ @Override
+ public boolean open(float volume, float stopDist, boolean atten, boolean pan) {
+ return true;
+ }
+
+ @Override
+ public void start(int repeat) {
+ String megaURL = this.owner.getURL().toString();
+ megaURL = WebControlImp.processURL(megaURL);
+ this.ds.nOpen(URL.make(megaURL).unalias());
+ activeCount++;
+ this.ds.nPlay(repeat);
+ this.playing = true;
+ }
+
+ @Override
+ public boolean position(Point3Temp cam, Point3Temp obj, Point3Temp out, Point3Temp up) {
+ return true;
+ }
+
+ @Override
+ public int getState() {
+ int nativeState = this.ds.nTick();
+ return nativeState == 3 ? 0 : 1;
+ }
+
+ @Override
+ public void stop() {
+ this.ds.nStop();
+ activeCount--;
+ this.playing = false;
+ }
+
+ @Override
+ public void close() {
+ if (this.playing) {
+ this.stop();
+ }
+ }
+
+ @Override
+ public boolean setVolume(float v) {
+ return true;
+ }
+}
diff --git a/NET/worlds/scape/WObject.java b/NET/worlds/scape/WObject.java
new file mode 100644
index 0000000..dd2d26f
--- /dev/null
+++ b/NET/worlds/scape/WObject.java
@@ -0,0 +1,1450 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.Gamma;
+import NET.worlds.console.RightMenu;
+import NET.worlds.core.IniFile;
+import NET.worlds.core.Std;
+import NET.worlds.network.NetworkObject;
+import NET.worlds.network.URL;
+import NET.worlds.network.WorldServer;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Vector;
+
+public class WObject extends Transform implements Prerenderable {
+ private boolean mouseOver = false;
+ private String _toolTipText;
+ private Vector<WObject> contents = null;
+ private Shadow shadow;
+ public static boolean shadowsOn = IniFile.gamma().getIniInt("shadows", 0) != 0;
+ protected boolean discarded = false;
+ protected int clumpID;
+ protected int highlightID = 0;
+ protected static final int isVisibleMask = 1;
+ protected static final int isBumpableMask = 2;
+ protected static final int isHologramRoughCutMask = 4;
+ protected static final int isMirrored = 4;
+ protected static final int isOptimizableMask = 8;
+ protected static final int isDrawFirstOnIntersectionMask = 16;
+ protected static final int isDrawOrderUnimportantMask = 32;
+ protected static final int isMaterialVisible = 64;
+ protected static final int isHighlitMask = 128;
+ protected static final int isAutoGapMask = 256;
+ protected static final int isAutoGapFromLocalMask = 512;
+ protected static final int isDisablePixelDoublingMask = 1024;
+ protected static final int isSharerMode0 = 2048;
+ protected static final int isSharerMode1 = 4096;
+ protected static final int isSharerMode2 = 8192;
+ protected static final int duringRestore = 16384;
+ protected static final int isShadowedLocally = 32768;
+ protected static final int isShadowed = 65536;
+ protected static final int isAutobuiltMask = 131072;
+ protected static final int isHologramViewplaneAlignedMask = 262144;
+ protected static final int isDontConnect = 262144;
+ protected static final int isSurfaceUFlippedMask = 524288;
+ protected static final int isSurfaceVFlippedMask = 1048576;
+ protected static final int isReclumpingMask = 2097152;
+ protected static final int isHologramAutosize = 4194304;
+ protected int flags = 3;
+ Vector<Object> eventHandlers;
+ protected Vector<Action> actions = null;
+ protected BumpCalc bumpCalc = null;
+ static BumpCalc standardBoxBumpCalc = new BoxBumpCalc();
+ private static Object classCookie = new Object();
+ public static boolean replaceWithMontyDoor = IniFile.gamma().getIniInt("replaceWithMontyDoor", 0) != 0;
+ private Sharer _sharer = null;
+ public VisiAttribute _visibilityAttribute;
+ public TransAttribute _transformAttribute;
+ public BumpAttribute _bumpableAttribute;
+
+ static {
+ nativeInit();
+ standardBoxBumpCalc.setName("defaultBoxBumpCalc");
+ }
+
+ public static native void nativeInit();
+
+ public boolean getMouseOver() {
+ if (this.mouseOver) {
+ return true;
+ } else {
+ WObject obj;
+ try {
+ obj = (WObject)this.getOwner();
+ } catch (ClassCastException var3) {
+ return false;
+ }
+
+ return obj == null ? false : obj.getMouseOver();
+ }
+ }
+
+ public void setMouseOver(boolean m) {
+ this.mouseOver = m;
+ }
+
+ public String getToolTipText() {
+ if (this._toolTipText != null) {
+ return this._toolTipText;
+ } else {
+ WObject obj;
+ try {
+ obj = (WObject)this.getOwner();
+ } catch (ClassCastException var3) {
+ return null;
+ }
+
+ return obj == null ? null : obj.getToolTipText();
+ }
+ }
+
+ public void setToolTipText(String newText) {
+ this._toolTipText = newText;
+ }
+
+ @Override
+ public void setName(String v) {
+ super.setName(this.getBangName(v));
+ }
+
+ private String getBangName(String s) {
+ boolean hasBang = s.startsWith("!");
+ if (hasBang != this.isDynamic()) {
+ return hasBang ? s.substring(1) : "!" + s;
+ } else {
+ return s;
+ }
+ }
+
+ @Override
+ public void markEdited() {
+ if (!this.isDynamic()) {
+ super.markEdited();
+ }
+ }
+
+ @Override
+ public void getChildren(DeepEnumeration d) {
+ if (this.contents != null) {
+ d.addChildVector(this.contents);
+ }
+
+ if (this.eventHandlers != null) {
+ d.addChildVector(this.eventHandlers);
+ }
+
+ if (this.actions != null) {
+ d.addChildVectorAction(this.actions);
+ }
+
+ if (this._sharer != null) {
+ d.addChildElement(this._sharer);
+ }
+ }
+
+ public void add(WObject child) {
+ super.add(child);
+ if (this.hasClump()) {
+ child.recursiveAddRwChildren(this);
+ }
+
+ if (child._sharer != null) {
+ child._sharer.adjustShare();
+ }
+
+ if (this.contents == null) {
+ this.contents = new Vector<WObject>();
+ }
+
+ this.contents.addElement(child);
+ }
+
+ public Enumeration<?> getContents() {
+ return this.contents == null ? new Vector().elements() : this.contents.elements();
+ }
+
+ public boolean hasContents() {
+ return this.contents != null;
+ }
+
+ public boolean contentsContain(WObject w) {
+ return this.contents == null ? false : this.contents.contains(w);
+ }
+
+ @Override
+ protected void noteUnadding(SuperRoot child) {
+ if (this.contents != null && this.contents.removeElement(child) && this.contents.size() == 0) {
+ this.contents = null;
+ }
+ }
+
+ public void makeShadow() {
+ assert this.shadow == null;
+
+ this.shadow = new DiskShadow(this);
+ }
+
+ @Override
+ public void detach() {
+ if (this.clumpID != 0) {
+ this.markVoid();
+ }
+
+ super.detach();
+ if (this._sharer != null) {
+ this._sharer.adjustShare();
+ }
+
+ if (this.shadow != null) {
+ this.shadow.adjustShadow(this);
+ this.shadow = null;
+ }
+ }
+
+ @Override
+ public void discard() {
+ super.discard();
+ this.discarded = true;
+ if (this.contents != null) {
+ int i = this.contents.size();
+
+ while (--i >= 0) {
+ this.contents.elementAt(i).discard();
+ }
+ }
+
+ if (this.eventHandlers != null) {
+ int i = this.eventHandlers.size();
+
+ while (--i >= 0) {
+ this.removeHandler((SuperRoot)this.eventHandlers.elementAt(i));
+ }
+ }
+
+ if (this.actions != null) {
+ int i = this.actions.size();
+
+ while (--i >= 0) {
+ this.removeAction(this.actions.elementAt(i));
+ }
+ }
+
+ this.releaseAuxilaryData();
+ }
+
+ @Override
+ protected void finalize() {
+ if (!this.discarded) {
+ this.releaseAuxilaryData();
+ }
+
+ super.finalize();
+ }
+
+ public void reclump() {
+ if (this.clumpID != 0) {
+ assert (this.flags & 2097152) == 0;
+
+ this.flags |= 2097152;
+ this.markVoid();
+ this.recursiveAddRwChildren((WObject)this.getOwner());
+
+ assert (this.flags & 2097152) != 0;
+
+ this.flags &= -2097153;
+ }
+ }
+
+ public boolean isReclumping() {
+ return (this.flags & 2097152) != 0;
+ }
+
+ @Override
+ protected void noteTransformChange() {
+ this.setClumpMatrix();
+ this.updateHighlight();
+ if (this.shadow != null) {
+ this.shadow.adjustShadow(this);
+ }
+
+ if (this._transformAttribute != null) {
+ this._transformAttribute.noteChange();
+ }
+ }
+
+ protected void markVoid() {
+ if (this.contents != null) {
+ int i = this.contents.size();
+
+ while (--i >= 0) {
+ this.contents.elementAt(i).markVoid();
+ }
+ }
+
+ Room r = this.getRoomFromClump();
+ if (this instanceof FrameHandler) {
+ r.removeFrameHandler((FrameHandler)this, this);
+ }
+
+ if (this.eventHandlers != null) {
+ int i = this.eventHandlers.size();
+
+ while (--i >= 0) {
+ Object f = this.eventHandlers.elementAt(i);
+ if (f instanceof FrameHandler) {
+ r.removeFrameHandler((FrameHandler)f, this);
+ }
+ }
+ }
+
+ this.voidClump();
+ if (this.shadow != null) {
+ this.shadow.adjustShadow(this);
+ }
+ }
+
+ protected void addRwChildren(WObject parent) {
+ this.addNewRwChild(parent);
+ }
+
+ public void recursiveAddRwChildren(WObject parent) {
+ this.addRwChildren(parent);
+ if (this.contents != null) {
+ int end = this.contents.size();
+
+ for (int i = 0; i < end; i++) {
+ this.contents.elementAt(i).recursiveAddRwChildren(this);
+ }
+ }
+ }
+
+ protected final void addNewRwChild(WObject container) {
+ assert this.clumpID == 0;
+
+ this.createClump();
+ this.newRwClumpChildHelper(container);
+ }
+
+ protected void newRwClumpChildHelper(WObject container) {
+ assert container != null;
+
+ this.addChildToClump(container);
+ this.newRwChildHelper();
+ if (!this.getVisible()) {
+ this.updateVisible();
+ }
+
+ if (this.shadow != null) {
+ this.shadow.adjustShadow(this);
+ } else {
+ if (this.getShadowedLocally() ? !this.getLocalShadowed() : !shadowsOn) {
+ return;
+ }
+
+ if (this.inRoomContents() && this.getOwner() instanceof Room) {
+ this.makeShadow();
+ }
+ }
+ }
+
+ protected void newRwChildHelper() {
+ this.initClumpData();
+ this.setClumpMatrix();
+ Room r = this.getRoom();
+ if (this instanceof FrameHandler) {
+ r.addFrameHandler((FrameHandler)this, this);
+ }
+
+ if (this.eventHandlers != null) {
+ for (int i = 0; i < this.eventHandlers.size(); i++) {
+ Object f = this.eventHandlers.elementAt(i);
+ if (f instanceof FrameHandler) {
+ r.addFrameHandler((FrameHandler)f, this);
+ }
+ }
+ }
+ }
+
+ native void createClump();
+
+ public final boolean hasClump() {
+ return this.clumpID != 0;
+ }
+
+ public final int getID() {
+ return this.clumpID;
+ }
+
+ public native boolean nativeInCamSpace(Camera var1, Point3Temp var2);
+
+ public Point3Temp inCamSpace(Camera cam) {
+ Point3Temp p = Point3Temp.make();
+ return this.nativeInCamSpace(cam, p) ? p : null;
+ }
+
+ protected native void voidClump();
+
+ protected native int extractClump();
+
+ native void addChildToClump(WObject var1);
+
+ native void setClumpMatrix();
+
+ private native void initClumpData();
+
+ native void doneWithEditing();
+
+ native int getNumVerts();
+
+ @Override
+ public Transform getObjectToWorldMatrix() {
+ if (this.hasClump()) {
+ return this.getObjectToWorldMatrix(Transform.make());
+ } else {
+ Transform t = this.getTransform();
+ SuperRoot o = this.getOwner();
+ if (o instanceof WObject) {
+ Transform ot = ((WObject)o).getObjectToWorldMatrix();
+ t.post(ot);
+ ot.recycle();
+ }
+
+ return t;
+ }
+ }
+
+ private native Transform getObjectToWorldMatrix(Transform var1);
+
+ protected native Transform getJointedObjectToWorldMatrix(Transform var1);
+
+ public Point3Temp getWorldPosition() {
+ Transform t = this.getObjectToWorldMatrix();
+ Point3Temp ret = t.getPosition();
+ t.recycle();
+ return ret;
+ }
+
+ public native void updateHighlight();
+
+ public native void getClumpBBox(Point3Temp var1, Point3Temp var2);
+
+ public BoundBoxTemp getClumpBBox() {
+ Point3Temp start = Point3Temp.make();
+ Point3Temp right = Point3Temp.make();
+ this.getClumpBBox(start, right);
+ return BoundBoxTemp.make(start, right);
+ }
+
+ public WObject setHighlit(boolean b) {
+ if (b) {
+ this.flags |= 128;
+ } else {
+ this.flags &= -129;
+ }
+
+ this.updateHighlight();
+ return this;
+ }
+
+ public final boolean getHighlit() {
+ return (this.flags & 128) != 0;
+ }
+
+ public void setAutobuilt(boolean b) {
+ if (b) {
+ this.flags |= 131072;
+ } else {
+ this.flags &= -131073;
+ }
+ }
+
+ public final boolean getAutobuilt() {
+ return (this.flags & 131072) != 0;
+ }
+
+ public WObject setOptimizable(boolean b) {
+ if (b) {
+ this.flags |= 8;
+ } else {
+ this.flags &= -9;
+ }
+
+ return this;
+ }
+
+ public final boolean getOptimizable() {
+ return (this.flags & 8) != 0;
+ }
+
+ final void setSharerMode(int mode) {
+ assert mode >= 0 && mode < 8;
+
+ this.flags &= -14337;
+ this.flags |= mode << 11;
+ this.setName(this.getName());
+ }
+
+ final int getSharerMode() {
+ return this.flags >>> 11 & 7;
+ }
+
+ public final boolean isDynamic() {
+ return (this.getSharerMode() & 4) != 0;
+ }
+
+ public WObject setLocalAutoGap(boolean b) {
+ if (b) {
+ this.flags |= 256;
+ } else {
+ this.flags &= -257;
+ }
+
+ if (this instanceof Room) {
+ Enumeration<Object> e = this.getDeepOwned();
+
+ while (e.hasMoreElements()) {
+ Object o = e.nextElement();
+ if (o instanceof WObject) {
+ ((WObject)o).noteTransformChange();
+ }
+ }
+ }
+
+ return this;
+ }
+
+ public final boolean getLocalAutoGap() {
+ return (this.flags & 256) != 0;
+ }
+
+ public WObject setAutoGapFromRoom(boolean b) {
+ if (b) {
+ this.flags &= -513;
+ } else {
+ this.flags |= 512;
+ }
+
+ this.noteTransformChange();
+ return this;
+ }
+
+ public final boolean getAutoGapFromRoom() {
+ return (this.flags & 512) == 0;
+ }
+
+ public boolean getAutoGap() {
+ return ((WObject)(this.getAutoGapFromRoom() ? this.getRoom() : this)).getLocalAutoGap();
+ }
+
+ public void setVisible(boolean b) {
+ if (b != this.getVisible()) {
+ if (b) {
+ this.flags |= 1;
+ } else {
+ this.flags &= -2;
+ }
+
+ this.updateVisible();
+ if (this.shadow != null) {
+ this.shadow.adjustShadow(this);
+ }
+
+ if (this._visibilityAttribute != null) {
+ this._visibilityAttribute.noteChange();
+ }
+ }
+ }
+
+ public boolean getLocalShadowed() {
+ return (this.flags & 65536) != 0;
+ }
+
+ public void setLocalShadowed(boolean b) {
+ if (b) {
+ this.flags |= 65536;
+ } else {
+ this.flags &= -65537;
+ }
+ }
+
+ public boolean getShadowedLocally() {
+ return (this.flags & 32768) != 0;
+ }
+
+ public void setShadowedLocally(boolean b) {
+ if (b) {
+ this.flags |= 32768;
+ } else {
+ this.flags &= -32769;
+ }
+ }
+
+ protected native void updateVisible();
+
+ public final boolean getVisible() {
+ return (this.flags & 1) != 0;
+ }
+
+ public WObject setBumpable(boolean b) {
+ if (b) {
+ this.flags |= 2;
+ } else {
+ this.flags &= -3;
+ }
+
+ if (this._bumpableAttribute != null) {
+ this._bumpableAttribute.noteChange();
+ }
+
+ return this;
+ }
+
+ public final boolean getBumpable() {
+ return (this.flags & 2) != 0;
+ }
+
+ public boolean deliver(Event event) {
+ event.receiver = this;
+ boolean delivered = event.deliver(this);
+ if (this.eventHandlers != null) {
+ Enumeration<Object> e = this.eventHandlers.elements();
+
+ while (e.hasMoreElements()) {
+ event.receiver = this;
+ if (event.deliver(e.nextElement())) {
+ delivered = true;
+ }
+ }
+ }
+
+ if (delivered) {
+ return true;
+ } else {
+ if (event instanceof UserEvent) {
+ Object o = this.getOwner();
+ if (o instanceof WObject) {
+ return ((WObject)o).deliver(event);
+ }
+ }
+
+ return false;
+ }
+ }
+
+ public Enumeration<Object> getHandlers() {
+ return this.eventHandlers == null ? new Vector<Object>().elements() : this.eventHandlers.elements();
+ }
+
+ public boolean hasHandler(SuperRoot h) {
+ return this.eventHandlers != null && this.eventHandlers.indexOf(h) != -1;
+ }
+
+ public WObject addHandler(SuperRoot h) {
+ if (this.eventHandlers == null) {
+ this.eventHandlers = new Vector<Object>();
+ }
+
+ this.eventHandlers.addElement(h);
+ if (this.clumpID != 0 && h instanceof FrameHandler) {
+ this.getRoomFromClump().addFrameHandler((FrameHandler)h, this);
+ }
+
+ super.add(h);
+ return this;
+ }
+
+ @Override
+ public Room getRoom() {
+ return this.clumpID != 0 ? this.getRoomFromClump() : this.getRoomNotFromClump();
+ }
+
+ public Room getRoomNotFromClump() {
+ SuperRoot o = this.getOwner();
+ return o instanceof WObject ? ((WObject)o).getRoomNotFromClump() : null;
+ }
+
+ public native Room getRoomFromClump();
+
+ public native boolean inRoomContents();
+
+ @Override
+ public World getWorld() {
+ if (this.clumpID != 0) {
+ return this.getRoomFromClump().getWorld();
+ } else {
+ Room r = this.getRoomNotFromClump();
+ return r == null ? null : r.getWorld();
+ }
+ }
+
+ @Override
+ public boolean isActive() {
+ return this.clumpID != 0 ? true : super.isActive();
+ }
+
+ public void removeHandler(SuperRoot h) {
+ if (this.eventHandlers.contains(h)) {
+ h.detach();
+ this.eventHandlers.removeElement(h);
+ if (this.eventHandlers.size() == 0) {
+ this.eventHandlers = null;
+ }
+
+ if (this.clumpID != 0 && h instanceof FrameHandler) {
+ this.getRoomFromClump().removeFrameHandler((FrameHandler)h, this);
+ }
+ }
+ }
+
+ public Enumeration<Action> getActions() {
+ return this.actions == null ? new Vector<Action>().elements() : this.actions.elements();
+ }
+
+ public boolean hasActions() {
+ return this.actions != null;
+ }
+
+ public WObject addAction(Action a) {
+ if (this.actions == null) {
+ this.actions = new Vector<Action>();
+ }
+
+ this.actions.addElement(a);
+ super.add(a);
+ return this;
+ }
+
+ public void removeAction(Action a) {
+ assert a.getOwner() == this;
+
+ a.detach();
+ this.actions.removeElement(a);
+ if (this.actions.size() == 0) {
+ this.actions = null;
+ }
+ }
+
+ public void rightMenu() {
+ new RightMenu(this, this.getActions());
+ }
+
+ public void doAction(String actionLabel, Event evt) {
+ if (actionLabel != null && !actionLabel.equals("")) {
+ if (Gamma.getShaper() != null && actionLabel.equals("Edit Properties...")) {
+ Console.getFrame().getEditTile().viewProperties(this);
+ } else if (this.actions != null) {
+ int i = 0;
+
+ while (i < this.actions.size()) {
+ Action candidate = this.actions.elementAt(i);
+ i++;
+ if (actionLabel.equals(candidate.rightMenuLabel)) {
+ RunningActionHandler.trigger(candidate, this.getWorld(), evt);
+ }
+ }
+ }
+ }
+ }
+
+ public WObject setBumpCalc(BumpCalc b) {
+ if (this.bumpCalc != null) {
+ this.bumpCalc.detach();
+ }
+
+ this.bumpCalc = b;
+ if (this.bumpCalc != null) {
+ super.add(this.bumpCalc);
+ }
+
+ return this;
+ }
+
+ public BumpCalc getBumpCalc(BumpEventTemp b) {
+ return this.bumpCalc == null ? standardBoxBumpCalc : this.bumpCalc;
+ }
+
+ public Point3Temp getPlaneExtent() {
+ return Point3Temp.make();
+ }
+
+ public BoundBoxTemp getBoundBox() {
+ if (this.getVisible()) {
+ return this.getClumpBBox();
+ } else {
+ Transform xfrm = this.getObjectToWorldMatrix();
+ BoundBoxTemp ret = BoundBoxTemp.make(xfrm.getPosition(), this.getPlaneExtent().times(xfrm));
+ xfrm.recycle();
+ return ret;
+ }
+ }
+
+ public float getMinXYExtent() {
+ if (this.getVisible()) {
+ return this.getClumpMinXYExtent();
+ } else {
+ BoundBoxTemp box = this.getBoundBox();
+ float x = box.hi.x - box.lo.x;
+ float y = box.hi.y - box.lo.y;
+ return x < y ? x : y;
+ }
+ }
+
+ public native float getClumpMinXYExtent();
+
+ public void detectBump(BumpEventTemp b) {
+ BoundBoxTemp box = this.getBoundBox();
+ if (!box.isEmpty() && b.bound.overlaps(box)) {
+ this.getBumpCalc(b).detectBump(b, this);
+ }
+
+ if (this.contents != null) {
+ int i = this.contents.size();
+
+ while (--i >= 0) {
+ WObject w = this.contents.elementAt(i);
+ if (w.getBumpable() && b.source != w) {
+ w.detectBump(b);
+ }
+ }
+ }
+ }
+
+ public void premoveThrough(Point3Temp motion) {
+ Point3Temp pos = this.getPosition();
+ this.moveThrough(Point3Temp.make(motion).times(this).minus(pos));
+ }
+
+ public void moveThrough(Point3Temp motion) {
+ if (this.getRoom() == null || !this.getBumpable()) {
+ this.moveBy(motion);
+ } else if (this.getRoom().hasClump()) {
+ int now = Std.getRealTime();
+ WObject me = this;
+
+ for (int loopCount = 4; loopCount > 0; loopCount--) {
+ BumpEventTemp be = BumpEventTemp.make(now, me, motion);
+
+ try {
+ if (be.target == null) {
+ me.moveBy(be.fullPath);
+ break;
+ }
+
+ be.postBumpRoom = me.getRoom();
+ be.postBumpPosition = me.getObjectToWorldMatrix().moveBy(be.path);
+ be.postBumpPath = Point3Temp.make(be.fullPath).times(1.0F - be.fraction);
+ Transform t = me.getTransform();
+
+ try {
+ Room r = this.getRoom();
+ be.target.deliver(be);
+ me.deliver(be);
+ if (!me.isTransformEqual(t) || r != this.getRoom()) {
+ break;
+ }
+ } finally {
+ t.recycle();
+ }
+
+ Transform invPos = be.postBumpRoom.getObjectToWorldMatrix();
+ invPos.invert();
+ if (me.getRoom() != be.postBumpRoom) {
+ invPos.pre(be.postBumpPosition);
+ me = me.changeRoom(be.postBumpRoom, invPos);
+ if (me == null) {
+ break;
+ }
+ } else {
+ me.makeIdentity();
+ me.pre(invPos);
+ me.pre(be.postBumpPosition);
+ }
+
+ be.postBumpPosition.recycle();
+ be.postBumpPosition = null;
+ invPos.recycle();
+ motion = be.postBumpPath;
+ } finally {
+ be.recycle();
+ }
+ }
+ }
+ }
+
+ protected WObject changeRoom(Room newRoom, Transform invPos) {
+ this.detach();
+ newRoom.add(this);
+ this.makeIdentity();
+ this.pre(invPos);
+ return this;
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = PropAdder.make(new VectorProperty(this, index, "Contents"));
+ } else if (mode == 1) {
+ if (this.contents != null) {
+ ret = this.contents.clone();
+ }
+ } else if (mode == 4) {
+ ((WObject)value).detach();
+ } else if (mode == 3) {
+ this.add((WObject)value);
+ } else if (mode == 5 && value instanceof WObject && !(value instanceof Room)) {
+ ret = value;
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = PropAdder.make(new VectorProperty(this, index, "Event Handlers"));
+ } else if (mode == 1) {
+ if (this.eventHandlers != null) {
+ ret = this.eventHandlers.clone();
+ }
+ } else if (mode == 4) {
+ this.removeHandler((SuperRoot)value);
+ } else if (mode == 3) {
+ this.addHandler((SuperRoot)value);
+ } else if (mode == 5 && (value instanceof SwitchableBehavior || value instanceof Sensor)) {
+ ret = value;
+ }
+ break;
+ case 2:
+ if (mode == 0) {
+ ret = PropAdder.make(new VectorProperty(this, index, "Actions"));
+ } else if (mode == 1) {
+ if (this.actions != null) {
+ ret = this.actions.clone();
+ }
+ } else if (mode == 4) {
+ this.removeAction((Action)value);
+ } else if (mode == 3) {
+ this.addAction((Action)value);
+ } else if (mode == 5 && value instanceof Action) {
+ ret = value;
+ }
+ break;
+ case 3:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Bumpable"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(this.getBumpable());
+ } else if (mode == 2) {
+ this.setBumpable((Boolean)value);
+ }
+ break;
+ case 4:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Visible"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(this.getVisible());
+ } else if (mode == 2) {
+ this.setVisible((Boolean)value);
+ }
+ break;
+ case 5:
+ if (mode == 0) {
+ ret = IntegerPropertyEditor.make(new Property(this, index, "Sharing Mode (100 for help)", true));
+ } else if (mode == 1) {
+ ret = new Integer(this.getSharerMode());
+ } else if (mode == 2) {
+ int val = (Integer)value;
+ if (this instanceof Room && val >= 0 && val <= 5) {
+ Console.println("A Room's sharing mode\nmust be 2, and is\nautomatically set by the shaper.");
+ } else if (val != 0 && val != 3 && val != 5) {
+ Console.println("0 = default (chooses 2 or 3 for you)");
+ Console.println("2 = static (stored in .world)");
+ Console.println("3 = forwarded static");
+ Console.println("4 = dynamic (stored only on server)");
+ Console.println("5 = forwarded dynamic");
+ Console.println("Modes 2, and 4, are not generally\nsupported, except that mode 2\nis required for Rooms");
+ } else if (val == 5 && this.getSourceURL() == null) {
+ Console.println("Only WObjects read from files may be forwarded dynamic.");
+ } else {
+ this.getSharer().setMode(val);
+ }
+ }
+ break;
+ case 6:
+ if (mode == 0) {
+ ret = PropAdder.make(new VectorProperty(this, index, "Shared Attributes"));
+ } else if (mode == 1) {
+ if (this._sharer != null) {
+ ret = this._sharer.getAttributesList();
+ } else {
+ ret = new Vector();
+ }
+ } else if (mode == 4) {
+ this.removeShareableAttribute((Attribute)value);
+ } else if (mode == 3) {
+ this.addShareableAttribute((Attribute)value);
+ } else if (mode == 5 && value instanceof Attribute) {
+ ret = value;
+ }
+ break;
+ case 7:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Tool Tip Text"));
+ } else if (mode == 1) {
+ ret = this.getToolTipText();
+ } else if (mode == 2) {
+ this.setToolTipText((String)value);
+ }
+ break;
+ case 8:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Mouse Change"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(this.getMouseOver());
+ } else if (mode == 2) {
+ this.setMouseOver((Boolean)value);
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 9, mode, value);
+ }
+
+ return ret;
+ }
+
+ public static void saveUnsharedWObjects(Saver s, Vector<WObject> v) throws IOException {
+ int length = 0;
+ Enumeration<WObject> en = v.elements();
+
+ while (en.hasMoreElements()) {
+ WObject w = en.nextElement();
+ if (w instanceof Persister && !(w instanceof NonPersister) && !w.isDynamic()) {
+ length++;
+ }
+ }
+
+ s.saveInt(length);
+ en = v.elements();
+
+ while (en.hasMoreElements()) {
+ WObject w = en.nextElement();
+ if (w instanceof Persister && !(w instanceof NonPersister) && !w.isDynamic()) {
+ s.save(w);
+ }
+ }
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(10, classCookie);
+ super.saveState(s);
+ s.saveInt(this.flags & -129);
+ if (this.contents == null) {
+ s.saveBoolean(false);
+ } else {
+ s.saveBoolean(true);
+ saveUnsharedWObjects(s, this.contents);
+ }
+
+ s.saveVectorMaybeNull(this.eventHandlers);
+ s.saveVectorMaybeNull(this.actions);
+ s.saveMaybeNull(this.bumpCalc);
+ if (this._sharer != null && this._sharer.isEmpty()) {
+ s.saveMaybeNull(null);
+ } else {
+ s.saveMaybeNull(this._sharer);
+ }
+
+ s.saveString(this.getToolTipText());
+ s.saveBoolean(this.getMouseOver());
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ this.restoreWObjectState(r);
+ }
+
+ public void restoreWObjectState(Restorer r) throws IOException, TooNewException {
+ Vector<Object> newContents = null;
+ Vector<Object> newActions = null;
+ Vector<Object> newHandlers = null;
+ int vers = r.restoreVersion(classCookie);
+ switch (vers) {
+ case 0:
+ r.setOldFlag();
+ super.restoreState(r);
+ this.flags = r.restoreInt();
+ r.restoreMaybeNull();
+ this.flags |= 16384;
+ newContents = r.restoreVectorMaybeNull();
+ newHandlers = r.restoreVectorMaybeNull();
+ newActions = new Vector<Object>();
+ break;
+ case 1:
+ r.setOldFlag();
+ super.restoreState(r);
+ this.flags = r.restoreInt();
+ r.restoreMaybeNull();
+ this.flags |= 16384;
+ newContents = r.restoreVectorMaybeNull();
+ newHandlers = r.restoreVectorMaybeNull();
+ newActions = r.restoreVectorMaybeNull();
+ break;
+ case 2:
+ r.setOldFlag();
+ super.restoreState(r);
+ this.flags = r.restoreInt() | 16384;
+ newContents = r.restoreVectorMaybeNull();
+ newHandlers = r.restoreVectorMaybeNull();
+ newActions = r.restoreVectorMaybeNull();
+ break;
+ case 3:
+ super.restoreState(r);
+ this.flags = r.restoreInt() | 16384;
+ newContents = r.restoreVectorMaybeNull();
+ newHandlers = r.restoreVectorMaybeNull();
+ newActions = r.restoreVectorMaybeNull();
+ r.restore();
+ break;
+ case 4:
+ super.restoreState(r);
+ this.flags = r.restoreInt() | 16384;
+ newContents = r.restoreVectorMaybeNull();
+ newHandlers = r.restoreVectorMaybeNull();
+ newActions = r.restoreVectorMaybeNull();
+ r.restore();
+ this._sharer = (Sharer)r.restoreMaybeNull();
+ break;
+ case 5:
+ case 7:
+ case 8:
+ super.restoreState(r);
+ this.flags = r.restoreInt() | 16384;
+ newContents = r.restoreVectorMaybeNull();
+ newHandlers = r.restoreVectorMaybeNull();
+ newActions = r.restoreVectorMaybeNull();
+ this.setBumpCalc((BumpCalc)r.restoreMaybeNull());
+ this._sharer = (Sharer)r.restoreMaybeNull();
+ break;
+ case 6:
+ super.restoreState(r);
+ this.flags = r.restoreInt() | 16384;
+ newContents = r.restoreVectorMaybeNull();
+ newHandlers = r.restoreVectorMaybeNull();
+ newActions = r.restoreVectorMaybeNull();
+ this.setBumpCalc((BumpCalc)r.restoreMaybeNull());
+ this._sharer = (Sharer)r.restoreMaybeNull();
+ r.restoreString();
+ break;
+ case 9:
+ super.restoreState(r);
+ this.flags = r.restoreInt() | 16384;
+ newContents = r.restoreVectorMaybeNull();
+ newHandlers = r.restoreVectorMaybeNull();
+ newActions = r.restoreVectorMaybeNull();
+ this.setBumpCalc((BumpCalc)r.restoreMaybeNull());
+ this._sharer = (Sharer)r.restoreMaybeNull();
+ this.setToolTipText(r.restoreString());
+ break;
+ case 10:
+ super.restoreState(r);
+ this.flags = r.restoreInt() | 16384;
+ newContents = r.restoreVectorMaybeNull();
+ newHandlers = r.restoreVectorMaybeNull();
+ newActions = r.restoreVectorMaybeNull();
+ this.setBumpCalc((BumpCalc)r.restoreMaybeNull());
+ this._sharer = (Sharer)r.restoreMaybeNull();
+ this.setToolTipText(r.restoreString());
+ this.setMouseOver(r.restoreBoolean());
+ break;
+ default:
+ throw new TooNewException();
+ }
+
+ if (vers < 8) {
+ this.flags &= -65;
+ }
+
+ if (newContents != null) {
+ for (int i = 0; i < newContents.size(); i++) {
+ this.add((WObject)newContents.elementAt(i));
+ }
+ }
+
+ if (newActions != null) {
+ for (int i = 0; i < newActions.size(); i++) {
+ this.addAction((Action)newActions.elementAt(i));
+ }
+ }
+
+ if (newHandlers != null) {
+ for (int i = 0; i < newHandlers.size(); i++) {
+ this.addHandler((SuperRoot)newHandlers.elementAt(i));
+ }
+ }
+
+ if (this._sharer != null) {
+ super.add(this._sharer);
+ }
+ }
+
+ @Override
+ public void postRestore(int version) {
+ super.postRestore(version);
+ if (version < 7) {
+ Enumeration<Object> en = this.getHandlers();
+
+ while (en.hasMoreElements()) {
+ SuperRoot h = (SuperRoot)en.nextElement();
+ if (h.getOwner() != this) {
+ SuperRoot newH = (SuperRoot)h.clone();
+ this.eventHandlers.removeElement(h);
+ if (this.eventHandlers.size() == 0) {
+ this.eventHandlers = null;
+ }
+
+ if (this.clumpID != 0 && h instanceof FrameHandler) {
+ this.getRoomFromClump().removeFrameHandler((FrameHandler)h, this);
+ }
+
+ this.addHandler(newH);
+ }
+ }
+ }
+
+ if (replaceWithMontyDoor && this.getClass() == WObject.class) {
+ this.replaceMonty();
+ }
+
+ if (this._sharer != null) {
+ this._sharer.ownerPostRestore();
+ }
+
+ this.flags &= -16385;
+ if (this.isDynamic()) {
+ this.getSharer();
+ }
+ }
+
+ private void replaceMonty() {
+ if (this.actions != null && this.actions.size() == 3 && this.getOwner() instanceof WObject) {
+ int stage = 0;
+
+ try {
+ if (this.actions.elementAt(0) instanceof SetURLAction) {
+ SetURLAction sua = (SetURLAction)this.actions.elementAt(0);
+ if (sua._propName.equals("File") && sua._roomName != null) {
+ stage = 1;
+ Object db = this.actions.elementAt(1);
+ Object cancel = this.actions.elementAt(2);
+ if (db instanceof DialogAction && cancel.getClass() == db.getClass() && ((DialogAction)cancel).cancelOnly != ((DialogAction)db).cancelOnly) {
+ if (((DialogAction)db).cancelOnly) {
+ db = cancel;
+ }
+
+ stage = 2;
+ if (this.actions.elementAt(0) instanceof SetURLAction) {
+ stage = 3;
+ if (this.contents != null
+ && this.contents.size() >= 2
+ && this.contents.size() <= 3
+ && this.contents.elementAt(0).getClass() == Rect.class
+ && this.contents.elementAt(1).getClass() == Portal.class) {
+ stage = 4;
+ boolean isTwoPart = this.contents.size() == 3;
+ Rect top = (Rect)this.contents.elementAt(0);
+ Portal port = (Portal)this.contents.elementAt(1);
+ Rect bottom = null;
+ if (isTwoPart) {
+ if (this.contents.elementAt(2).getClass() != Rect.class) {
+ return;
+ }
+
+ bottom = (Rect)this.contents.elementAt(2);
+ }
+
+ stage = 5;
+ if (top.eventHandlers != null && top.eventHandlers.size() == 1 && top.eventHandlers.elementAt(0).getClass() == ClickSensor.class) {
+ stage = 6;
+ ClickSensor cs = (ClickSensor)top.eventHandlers.elementAt(0);
+ if (cs.countActions() == 1) {
+ stage = 7;
+ if (top.actions != null && top.actions.size() == 3 && top.actions.elementAt(2).getClass() == SequenceAction.class) {
+ stage = 8;
+ SequenceAction seq = (SequenceAction)top.actions.elementAt(2);
+ if (seq.actions != null && seq.actions.size() == (isTwoPart ? 9 : 7)) {
+ stage = 9;
+ if (port.actions != null && port.actions.size() == 2 && port._farSideRoomName != null && port._farSidePortalName != null
+ )
+ {
+ stage = 10;
+ URL texture = (isTwoPart ? bottom : top).getMaterial().textureName;
+ if (texture != null) {
+ stage = 11;
+ MontyDoor md = new MontyDoor();
+ md.setsAvatar = db instanceof SelectAvatarAction;
+ if (!md.setsAvatar) {
+ if (!(db instanceof SendURLAction)) {
+ return;
+ }
+
+ md.description = ((SendURLAction)db).description;
+ md.url = ((SendURLAction)db).destination;
+ } else {
+ md.url = ((SelectAvatarAction)db).url;
+ }
+
+ stage = 12;
+ md.viewURL = sua._value;
+ md.viewName = sua._targetName;
+ md.setFarSideInfo(null, sua._roomName, port._farSidePortalName);
+ md.post(port);
+ md.post(this);
+ String texName = texture.getInternal();
+ if (isTwoPart) {
+ if (!texName.endsWith("b.cmp")) {
+ Console.println("Texture: " + texName);
+ return;
+ }
+
+ int len = texName.length();
+ texName = texName.substring(0, len - 5) + "m2v*.mov";
+ }
+
+ stage = 13;
+ md.setMaterial(new Material(URL.make(texName)));
+ ((WObject)this.getOwner()).add(md);
+ this.detach();
+ port.detach();
+ md.reset();
+ stage = 100;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ } finally {
+ if (stage != 100) {
+ Console.println("Failed MontyDoor conversion of " + this.getName() + " in stage " + stage + ".\n");
+ }
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ String base = this.getName();
+ if (!this.isActive()) {
+ base = base + "(inactive)";
+ }
+
+ base = base + this.toTransformSubstring();
+ return this.contents == null ? base : base + this.contents.toString();
+ }
+
+ public static String getSaveExtension() {
+ return "wob";
+ }
+
+ public WObject getServed() {
+ int mode = this.getSharerMode();
+ if (mode == 0) {
+ Sharer s = this.getSharer();
+ if (s != null) {
+ mode = s.getMode();
+ }
+ }
+
+ if ((mode & 1) == 0) {
+ return this;
+ } else {
+ SuperRoot r = this.getOwner();
+ return r != null && r instanceof WObject ? ((WObject)r).getServed() : null;
+ }
+ }
+
+ @Override
+ public void prerender(Camera cam) {
+ WorldScriptManager.getInstance().onPrerender(this, cam);
+ }
+
+ public WorldServer getServer() {
+ WObject wo = this.getServed();
+ NetworkObject no;
+ if (wo instanceof Room) {
+ no = ((Room)wo).getNetworkRoom();
+ } else {
+ no = (NetworkObject)wo;
+ }
+
+ if (no == null) {
+ return null;
+ } else {
+ assert no != this;
+
+ return no.getServer();
+ }
+ }
+
+ public Enumeration<Attribute> getAttributes() {
+ return this.getSharer().getAttributes();
+ }
+
+ public Sharer getSharer() {
+ if (this._sharer == null) {
+ assert (this.flags & 16384) == 0;
+
+ this._sharer = new Sharer();
+ super.add(this._sharer);
+ }
+
+ return this._sharer;
+ }
+
+ public boolean hasSharer() {
+ return this._sharer != null;
+ }
+
+ public Attribute getAttribute(int attrID) {
+ return this.getSharer().getAttribute(attrID);
+ }
+
+ public int addAttribute(Attribute a) {
+ return this.getSharer().addAttribute(a);
+ }
+
+ public int addShareableAttribute(Attribute a) {
+ return this.addAttribute(a);
+ }
+
+ public void removeAttribute(Attribute a) {
+ this.getSharer().removeAttribute(a);
+ }
+
+ public void removeShareableAttribute(Attribute a) {
+ this.removeAttribute(a);
+ }
+
+ public boolean isShared() {
+ return this._sharer != null;
+ }
+
+ public void notifyRegister(int wid) {
+ }
+
+ public boolean acceptsLeftClicks() {
+ return this.getMouseOver();
+ }
+
+ public void releaseAuxilaryData() {
+ if (this._sharer != null) {
+ this._sharer.releaseAuxilaryData();
+ }
+ }
+}
diff --git a/NET/worlds/scape/WObjectHighlighter.java b/NET/worlds/scape/WObjectHighlighter.java
new file mode 100644
index 0000000..8a94f02
--- /dev/null
+++ b/NET/worlds/scape/WObjectHighlighter.java
@@ -0,0 +1,52 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Main;
+import NET.worlds.console.MainCallback;
+
+class WObjectHighlighter implements MainCallback {
+ private WObject target;
+ private Room room;
+ private boolean newState;
+ private boolean registered;
+
+ public WObjectHighlighter(WObject target) {
+ this.target = target;
+ this.start();
+ }
+
+ @Override
+ public synchronized void mainCallback() {
+ if (this.newState != this.target.getHighlit()) {
+ this.target.setHighlit(this.newState);
+ if (this.newState) {
+ this.room = this.target.getRoom();
+ if (this.room != null) {
+ this.room.highlightTarget = this.target;
+ }
+ } else if (this.room != null) {
+ this.room.highlightTarget = null;
+ this.room = null;
+ }
+ }
+
+ Main.unregister(this);
+ this.registered = false;
+ }
+
+ public synchronized void start() {
+ this.newState = true;
+ this.registerMe();
+ }
+
+ public synchronized void stop() {
+ this.newState = false;
+ this.registerMe();
+ }
+
+ private synchronized void registerMe() {
+ if (!this.registered) {
+ Main.register(this);
+ this.registered = true;
+ }
+ }
+}
diff --git a/NET/worlds/scape/WaitAction.java b/NET/worlds/scape/WaitAction.java
new file mode 100644
index 0000000..376c36f
--- /dev/null
+++ b/NET/worlds/scape/WaitAction.java
@@ -0,0 +1,91 @@
+package NET.worlds.scape;
+
+import NET.worlds.core.Std;
+import java.io.IOException;
+
+public class WaitAction extends Action {
+ float duration = 1.0F;
+ private static Object classCookie = new Object();
+
+ public WaitAction() {
+ }
+
+ public WaitAction(float duration) {
+ this.duration = duration;
+ }
+
+ @Override
+ public Persister trigger(Event evt, Persister seqID) {
+ long evttime = 0L;
+ if (evt == null) {
+ evttime = Std.getFastTime();
+ } else {
+ evttime = evt.time;
+ }
+
+ if (seqID == null) {
+ seqID = new WaitActionState(evttime + (long)(1000.0F * this.duration));
+ }
+
+ if (!((WaitActionState)seqID).run(evttime)) {
+ seqID = null;
+ }
+
+ return seqID;
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Duration (s)"));
+ } else if (mode == 1) {
+ ret = new Float(this.duration);
+ } else if (mode == 2) {
+ this.duration = (Float)value;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 1, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(2, classCookie);
+ super.saveState(s);
+ s.saveFloat(this.duration);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ r.setOldFlag();
+ super.restoreState(r);
+ this.duration = r.restoreInt();
+ break;
+ case 1:
+ r.setOldFlag();
+ super.restoreState(r);
+ this.duration = r.restoreFloat();
+ r.restoreLong();
+ break;
+ case 2:
+ super.restoreState(r);
+ this.duration = r.restoreFloat();
+ break;
+ default:
+ throw new TooNewException();
+ }
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + "[" + this.duration + " s]";
+ }
+}
diff --git a/NET/worlds/scape/WaitActionState.java b/NET/worlds/scape/WaitActionState.java
new file mode 100644
index 0000000..70d6d7f
--- /dev/null
+++ b/NET/worlds/scape/WaitActionState.java
@@ -0,0 +1,41 @@
+package NET.worlds.scape;
+
+import NET.worlds.core.Std;
+import java.io.IOException;
+
+class WaitActionState implements Persister {
+ long endTime;
+ private static Object classCookie = new Object();
+
+ WaitActionState() {
+ }
+
+ WaitActionState(long endTime) {
+ this.endTime = endTime;
+ }
+
+ public boolean run(long time) {
+ return time < this.endTime;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(0, classCookie);
+ s.saveLong(this.endTime - Std.getFastTime());
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ this.endTime = r.restoreLong() + Std.getFastTime();
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+
+ @Override
+ public void postRestore(int version) {
+ }
+}
diff --git a/NET/worlds/scape/WavSoundPlayer.java b/NET/worlds/scape/WavSoundPlayer.java
new file mode 100644
index 0000000..c1bff8a
--- /dev/null
+++ b/NET/worlds/scape/WavSoundPlayer.java
@@ -0,0 +1,275 @@
+package NET.worlds.scape;
+
+import NET.worlds.core.IniFile;
+import NET.worlds.network.URL;
+import java.util.Vector;
+
+public class WavSoundPlayer extends SoundPlayer implements Runnable {
+ float ang;
+ float dist;
+ float vol;
+ private String playingSoundFile = "";
+ private URL url;
+ private static Vector soundStack = new Vector();
+ private static Thread activeThread;
+ int repeatsLeft;
+ private static int playingThreads;
+ private static int systemPaused;
+ static boolean ignoreVolumeChanges = IniFile.gamma().getIniInt("ignoreVolumeChanges", 1) != 0;
+ private static WavSoundTerminator terminator = new WavSoundTerminator();
+ private static float lastLeftVol;
+ private static float lastRightVol;
+
+ static {
+ nativeInit();
+ }
+
+ public WavSoundPlayer(Sound owner) {
+ super(owner);
+ }
+
+ public static native void nativeInit();
+
+ @Override
+ public boolean open(float volume, float stopDist, boolean atten, boolean pan) {
+ return true;
+ }
+
+ @Override
+ public void close() {
+ this.stop();
+ }
+
+ @Override
+ public boolean position(Point3Temp cam, Point3Temp obj, Point3Temp out, Point3Temp up) {
+ Point3Temp toObj = Point3Temp.make(obj).minus(cam);
+ Point3Temp right = Point3Temp.make(out).cross(up);
+ float y = toObj.dot(out);
+ float x = toObj.dot(right);
+ this.ang = (float)(Math.atan2(y, x) / Math.PI);
+ this.dist = toObj.length();
+ return this.setVolume(this.vol);
+ }
+
+ @Override
+ public boolean setVolume(float v) {
+ this.vol = v;
+ float leftFrac = 0.5F;
+ if (this.owner != null && this.owner.getPanning()) {
+ leftFrac = Math.abs(this.ang);
+ if (this.ang < 0.0F) {
+ v = this.vol * (float)(0.5 + Math.abs(0.5 + this.ang));
+ }
+ }
+
+ if (this.owner != null && this.owner.getAttenuate()) {
+ float stopDist = this.owner.getStopDistance();
+ if (this.dist > stopDist) {
+ this.volume(0.0F, 0.0F);
+ return false;
+ }
+
+ v *= (stopDist - this.dist) / stopDist;
+ }
+
+ this.volume(v * leftFrac, v * (1.0F - leftFrac));
+ return true;
+ }
+
+ @Override
+ public int getState() {
+ return soundStack.contains(this) ? 0 : 1;
+ }
+
+ public void start(URL u) {
+ this.url = u;
+ this.start(1);
+ }
+
+ private static WavSoundPlayer getActive() {
+ return !soundStack.isEmpty() ? (WavSoundPlayer)soundStack.lastElement() : null;
+ }
+
+ public static boolean isActive() {
+ return !soundStack.isEmpty();
+ }
+
+ private void play(int repeatCount, boolean reuseLoop) {
+ this.playingSoundFile = this.url.unalias();
+ soundStack.removeElement(this);
+ soundStack.addElement(this);
+ this.repeatsLeft = repeatCount;
+ if (this.repeatsLeft < 0) {
+ if (!reuseLoop && systemPaused == 0) {
+ this.nativePlay(true);
+ }
+
+ activeThread = null;
+ } else {
+ activeThread = new Thread(this);
+ activeThread.start();
+ }
+ }
+
+ @Override
+ public void start(int repeatCount) {
+ synchronized (soundStack) {
+ WavSoundPlayer active = getActive();
+
+ assert this.repeatsLeft == 0 && active != this;
+
+ if (this.owner != null) {
+ this.url = this.owner.getURL();
+ }
+
+ boolean activeWasLoop = activeThread == null;
+ boolean reuseLoop = active != null && activeWasLoop && repeatCount < 0 && active.playingSoundFile.equals(this.url.unalias());
+ if (active != null) {
+ active.stop(reuseLoop);
+ if (activeWasLoop) {
+ soundStack.addElement(active);
+ }
+ }
+
+ this.play(repeatCount, reuseLoop);
+ }
+ }
+
+ @Override
+ public void run() {
+ synchronized (soundStack) {
+ if (systemPaused > 0) {
+ this.repeatsLeft = 0;
+ return;
+ }
+
+ playingThreads++;
+ }
+
+ while (this.repeatsLeft > 0) {
+ synchronized (soundStack) {
+ if (activeThread != Thread.currentThread()) {
+ break;
+ }
+
+ if (this.repeatsLeft > 0) {
+ this.repeatsLeft--;
+ }
+ }
+
+ this.nativePlay(false);
+ }
+
+ synchronized (soundStack) {
+ if (activeThread == Thread.currentThread()) {
+ assert getActive() == this;
+
+ soundStack.removeElement(this);
+ activeThread = null;
+ WavSoundPlayer active = getActive();
+ if (active != null) {
+ active.play(-1, false);
+ }
+ }
+
+ playingThreads--;
+ soundStack.notifyAll();
+ }
+ }
+
+ private void stop(boolean leaveLoopRunning) {
+ if (getActive() == this) {
+ boolean isLoop = activeThread == null;
+
+ assert this.repeatsLeft < 0 && isLoop || !leaveLoopRunning;
+
+ this.repeatsLeft = 0;
+ if (!leaveLoopRunning && isLoop && systemPaused == 0) {
+ this.nativeStop();
+ }
+
+ activeThread = null;
+ }
+
+ soundStack.removeElement(this);
+ }
+
+ @Override
+ public void stop() {
+ synchronized (soundStack) {
+ if (getActive() == this) {
+ this.stop(false);
+ WavSoundPlayer active = getActive();
+ if (active != null) {
+ active.play(-1, false);
+ }
+ } else {
+ soundStack.removeElement(this);
+ }
+ }
+ }
+
+ public static void pauseSystem() {
+ pauseSystemExceptASF();
+ }
+
+ public static void pauseSystemExceptASF() {
+ synchronized (soundStack) {
+ WavSoundPlayer active = getActive();
+ boolean isLoop = activeThread == null;
+ if (active != null) {
+ if (isLoop) {
+ active.nativeStop();
+ } else {
+ active.stop(false);
+ }
+ }
+
+ systemPaused++;
+ if (active != null) {
+ active.play(-1, false);
+ }
+
+ while (playingThreads > 0) {
+ try {
+ soundStack.wait();
+ } catch (InterruptedException var4) {
+ }
+ }
+ }
+ }
+
+ public static void resumeSystem() {
+ resumeSystemExceptASF();
+ }
+
+ public static void resumeSystemExceptASF() {
+ synchronized (soundStack) {
+ if (systemPaused > 0) {
+ systemPaused = 0;
+ WavSoundPlayer active = getActive();
+ if (active != null && activeThread == null) {
+ active.play(-1, false);
+ }
+ }
+ }
+ }
+
+ public void volume(float left, float right) {
+ if (!ignoreVolumeChanges) {
+ synchronized (soundStack) {
+ if (getActive() == this && (lastLeftVol != left || lastRightVol != right)) {
+ lastLeftVol = left;
+ lastRightVol = right;
+ this.nativeVolume(left, right);
+ }
+ }
+ }
+ }
+
+ private native void nativePlay(boolean var1);
+
+ private native void nativeVolume(float var1, float var2);
+
+ private native void nativeStop();
+}
diff --git a/NET/worlds/scape/WavSoundTerminator.java b/NET/worlds/scape/WavSoundTerminator.java
new file mode 100644
index 0000000..2335fb5
--- /dev/null
+++ b/NET/worlds/scape/WavSoundTerminator.java
@@ -0,0 +1,21 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Main;
+import NET.worlds.console.MainCallback;
+import NET.worlds.console.MainTerminalCallback;
+
+class WavSoundTerminator implements MainCallback, MainTerminalCallback {
+ public WavSoundTerminator() {
+ Main.register(this);
+ }
+
+ @Override
+ public void mainCallback() {
+ }
+
+ @Override
+ public void terminalCallback() {
+ WavSoundPlayer.pauseSystem();
+ Main.unregister(this);
+ }
+}
diff --git a/NET/worlds/scape/WearAction.java b/NET/worlds/scape/WearAction.java
new file mode 100644
index 0000000..18e6aa7
--- /dev/null
+++ b/NET/worlds/scape/WearAction.java
@@ -0,0 +1,339 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.network.URL;
+import java.io.IOException;
+
+public class WearAction extends Action {
+ char limb = 'B';
+ String val = "";
+ private static String allowedLimbChars = "PBLMORUVIJKXYZabcdefHQE";
+ private static Object classCookie = new Object();
+
+ @Override
+ public Persister trigger(Event e, Persister seqID) {
+ Object owner = this.getOwner();
+ if (owner != null) {
+ setAvLimb(this.limb, this.val);
+ }
+
+ return null;
+ }
+
+ public static void setAvLimb(char limb, String v) {
+ String str = PosableShape.getCurrentAvCustomizable();
+ if (str != null) {
+ int pos = str.indexOf(".", 7);
+ String bodyType = str.substring(7, pos).toLowerCase();
+ int matStart;
+ int matEnd;
+ if (limb == 'H' || limb == 'E') {
+ int head = str.lastIndexOf("NS");
+ if (head < 0) {
+ return;
+ }
+
+ if (v == null) {
+ v = bodyType;
+ if (limb == 'E') {
+ limb = 'H';
+ if (head >= 0 && str.charAt(head + 5) == 'G') {
+ v = PosableShape.readName(str, head + 6).toLowerCase();
+ }
+ }
+ }
+
+ int face = str.lastIndexOf("DgT");
+ int faceEnd = -1;
+ if (face < head) {
+ if (limb == 'E') {
+ Console.println("Can't change the face of this type of head.");
+ return;
+ }
+
+ face = -1;
+ } else {
+ faceEnd = face + 2;
+
+ int i;
+ while ((i = PosableShape.skipMat(str, faceEnd)) != faceEnd) {
+ faceEnd = i;
+ }
+ }
+
+ URL urlVal = PosableShape.getAvURL(v);
+ if (urlVal == null) {
+ return;
+ }
+
+ String val = urlVal.getAbsolute();
+ if (val == null) {
+ return;
+ }
+
+ if (limb == 'H') {
+ int newHead = val.lastIndexOf("NS");
+ if (newHead < 0) {
+ return;
+ }
+
+ String geom = "";
+ pos = str.indexOf(".0E", 7);
+ if (!v.equalsIgnoreCase(str.substring(7, pos))) {
+ geom = "G" + PosableShape.getBodyType(v);
+ }
+
+ matStart = head + 5;
+ matEnd = str.length();
+ v = geom + val.substring(newHead + 5);
+ } else {
+ int newFace = val.lastIndexOf("Dg");
+ if (newFace < 0) {
+ return;
+ }
+
+ int newEnd = newFace + 2;
+
+ int i;
+ while ((i = PosableShape.skipMat(val, newEnd)) != newEnd) {
+ newEnd = i;
+ }
+
+ matStart = face;
+ matEnd = faceEnd;
+ v = val.substring(newFace, newEnd);
+ }
+ } else if (limb == 'Q') {
+ int sInd = str.lastIndexOf("NS");
+ if (sInd < 0) {
+ Console.println("Can't customize this avatar.");
+ return;
+ }
+
+ matStart = sInd + 2;
+ matEnd = sInd + 5;
+ if (v == null) {
+ v = "000";
+ }
+ } else if (limb == 'f') {
+ int facex = str.lastIndexOf("Dg");
+ if (facex > 0) {
+ int end = facex + 2;
+
+ int i;
+ while ((i = PosableShape.skipMat(str, end)) != end) {
+ end = i;
+ }
+
+ int len = str.length() - 4;
+ String valx = "";
+
+ while (i < len) {
+ char c = str.charAt(i);
+ if (c == 'Q') {
+ valx = valx + c;
+ i++;
+ } else if (c >= '0' && c <= '9') {
+ valx = valx + c;
+ i++;
+ } else {
+ int j = PosableShape.skipMat(str, i);
+ if (i != j) {
+ valx = valx + "f";
+ i = j;
+ } else {
+ i++;
+ }
+ }
+ }
+
+ if (v != null) {
+ str = str.substring(0, end) + valx + ".rwg";
+ } else {
+ URL origURL = PosableShape.getAvURL(bodyType);
+ String origStr = "";
+ if (origURL != null) {
+ origStr = origURL.getInternal();
+ }
+
+ int origFace = origStr.lastIndexOf("Dg");
+ if (origFace > 0) {
+ int origEnd = origFace + 2;
+
+ int k;
+ while ((k = PosableShape.skipMat(origStr, origEnd)) != origEnd) {
+ origEnd = k;
+ }
+
+ str = str.substring(0, end) + origStr.substring(origEnd);
+ }
+ }
+ }
+
+ matStart = PosableShape.getMatPosition(str, limb);
+ if (matStart < 0) {
+ return;
+ }
+
+ matEnd = PosableShape.skipMat(str, matStart);
+ if (v == null) {
+ URL origURLx = PosableShape.getAvURL(bodyType);
+ if (origURLx == null) {
+ return;
+ }
+
+ String origStrx = origURLx.getInternal();
+ int origMat = PosableShape.getMatPosition(origStrx, limb);
+ if (origMat < 0) {
+ return;
+ }
+
+ int origMatEnd = PosableShape.skipMat(origStrx, origMat);
+ v = origStrx.substring(origMat, origMatEnd);
+ }
+ } else {
+ matStart = PosableShape.getMatPosition(str, limb);
+ if (matStart < 0) {
+ return;
+ }
+
+ matEnd = PosableShape.skipMat(str, matStart);
+ if (v == null) {
+ URL origURLxx = PosableShape.getAvURL(bodyType);
+ if (origURLxx == null) {
+ return;
+ }
+
+ String origStrx = origURLxx.getInternal();
+ int origMat = PosableShape.getMatPosition(origStrx, limb);
+ if (origMat < 0) {
+ return;
+ }
+
+ int origMatEnd = PosableShape.skipMat(origStrx, origMat);
+ v = origStrx.substring(origMat, origMatEnd);
+ }
+ }
+
+ Console co = Console.getActive();
+ if (co != null) {
+ co.setAvatar(URL.make(str.substring(0, matStart) + v + str.substring(matEnd)));
+ }
+ }
+ }
+
+ public static String makeMatString(int r, int g, int b) {
+ StringBuffer sb = new StringBuffer("C");
+ sb.append(toBase64(r));
+ sb.append(toBase64(g));
+ sb.append(toBase64(b));
+ return sb.toString();
+ }
+
+ public static char toBase64(int i) {
+ return PosableShape.base64.charAt(i);
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Limb"));
+ } else if (mode == 1) {
+ ret = new String("" + this.limb);
+ } else if (mode == 2) {
+ String s = (String)value;
+ if (s.length() == 1 && allowedLimbChars.indexOf(s.charAt(0)) >= 0) {
+ this.limb = s.charAt(0);
+ this.val = null;
+ } else {
+ Console.println("Limb must one of " + allowedLimbChars);
+ }
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Value").allowSetNull());
+ } else if (mode == 1) {
+ ret = this.val;
+ } else if (mode == 2) {
+ String v = (String)value;
+ if (v != null) {
+ if (this.limb != 'H' && this.limb != 'E') {
+ if (this.limb == 'Q') {
+ if (v.length() != 3) {
+ Console.println("Head size must be three letters, usually all the same.");
+ return ret;
+ }
+
+ for (int i = 0; i < 3; i++) {
+ char c = v.charAt(i);
+ if (c != '0' && (c < 'a' || c > 'z') && (c < 'A' || c > 'Z')) {
+ Console.println("Head size letters must each be one of z-a9A-Z.");
+ return ret;
+ }
+ }
+ } else if (v.length() < 1) {
+ v = null;
+ } else if (v.charAt(0) != 'C' && v.charAt(0) != 'T') {
+ Console.println("Material must be C_X, CXYZ, or Ttexname.");
+ return ret;
+ }
+ } else if (PosableShape.readName(v, 0).length() != v.length()) {
+ Console.println("Head and face must be set to all-lowercase name of body type.");
+ return ret;
+ }
+ }
+
+ this.val = v;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 2, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(1, classCookie);
+ super.saveState(s);
+ s.saveString(this.val);
+ s.saveString("" + this.limb);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ int red = r.restoreInt();
+ int green = r.restoreInt();
+ int blue = r.restoreInt();
+ String v = r.restoreString();
+ if (v == null) {
+ this.val = makeMatString(red, green, blue);
+ } else {
+ char c;
+ if (v.length() == 1 && (c = v.charAt(0)) >= 'A' && c <= 'Z') {
+ this.val = "C_" + v;
+ } else {
+ this.val = "T" + v;
+ }
+ }
+
+ this.limb = r.restoreString().charAt(0);
+ break;
+ case 1:
+ super.restoreState(r);
+ this.val = r.restoreString();
+ this.limb = r.restoreString().charAt(0);
+ break;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/WearWall.java b/NET/worlds/scape/WearWall.java
new file mode 100644
index 0000000..ff8ca02
--- /dev/null
+++ b/NET/worlds/scape/WearWall.java
@@ -0,0 +1,223 @@
+package NET.worlds.scape;
+
+import NET.worlds.network.URL;
+import java.io.IOException;
+import java.util.StringTokenizer;
+
+public class WearWall extends Rect {
+ char limb = ' ';
+ String tileList = "";
+ WObject[] subs;
+ private static Object classCookie = new Object();
+
+ WearWall() {
+ }
+
+ public void rebuild() {
+ this.unbuild();
+ if (this.limb != ' ') {
+ int count = 0;
+ StringTokenizer st = new StringTokenizer(this.tileList);
+
+ while (st.hasMoreTokens()) {
+ count++;
+ st.nextToken();
+ }
+
+ if (count != 0) {
+ float width = this.getScaleX();
+ float height = this.getScaleZ();
+ int wNum = 1;
+ int hNum = 1;
+
+ while (wNum * hNum < count) {
+ if (height * (wNum + 1) > width * (hNum + 1)) {
+ hNum++;
+ } else {
+ wNum++;
+ }
+ }
+
+ this.subs = new WObject[count];
+ float tw = 1.0F / wNum;
+ float th = 1.0F / hNum;
+ float wHalfSide = tw * this.getScaleX();
+ float hHalfSide = th * this.getScaleZ();
+ float sideLen = wHalfSide < hHalfSide ? wHalfSide : hHalfSide;
+ wHalfSide = (sideLen - 6.0F) / this.getScaleX() / 2.0F;
+ hHalfSide = (sideLen - 6.0F) / this.getScaleZ() / 2.0F;
+ st = new StringTokenizer(this.tileList);
+ float y = -1.0F / this.getScaleY();
+ float z = 1.0F - th / 2.0F;
+ int i = 0;
+
+ for (int row = 0; row < hNum; z -= th) {
+ float x = tw / 2.0F;
+
+ for (int col = 0; col < wNum; x += tw) {
+ if (!st.hasMoreTokens()) {
+ return;
+ }
+
+ Material m = null;
+ String s = st.nextToken();
+ String bodyType = null;
+
+ label91: {
+ try {
+ char c = s.charAt(0);
+ if (c != 'C' && c != 'T') {
+ String name = PosableShape.readName(s, 0);
+ if (this.limb == 'H') {
+ bodyType = name;
+ } else {
+ if (this.limb != 'E') {
+ break label91;
+ }
+
+ name = PosableShape.getFace(name);
+ m = PosableShape.readTexture(name, 0);
+ }
+ } else {
+ if (this.limb == 'H' || this.limb == 'E') {
+ break label91;
+ }
+
+ if (c == 'C') {
+ m = PosableShape.readColor(s, 1);
+ } else {
+ m = PosableShape.readTexture(s, 1);
+ }
+ }
+ } catch (StringIndexOutOfBoundsException var25) {
+ break label91;
+ }
+
+ if (bodyType != null) {
+ s = PosableShape.getAvURL(bodyType).getAbsolute();
+ int start;
+ if (s != null && (start = s.indexOf(".0E")) >= 0) {
+ start = PosableShape.skipLimb(s, start + 3);
+ if (start >= 0) {
+ int headIndex = s.lastIndexOf("NS");
+ if (headIndex >= 0) {
+ PosableShape p = new PosableShape(
+ URL.make(s.substring(0, start) + "PGNG" + PosableShape.getBodyType(bodyType) + "Q" + s.substring(headIndex + 1)), false
+ );
+ p.scale(750.0F / this.getScaleX(), 750.0F / this.getScaleY(), 750.0F / this.getScaleZ());
+ p.spin(0.0F, 1.0F, 1.0F, 180.0F);
+ p.spin(0.0F, 1.0F, 0.0F, 180.0F);
+ p.moveTo(x, y * 10.0F, z - hHalfSide / 2.0F);
+ WearAction action = new WearAction();
+ action.limb = this.limb;
+ action.val = bodyType;
+ p.addAction(action);
+ p.addHandler(new ClickSensor(action, 1));
+ this.add(p);
+ this.subs[i] = p;
+ }
+ }
+ }
+ } else if (m != null) {
+ m.setAmbient(0.75F);
+ m.setDiffuse(0.0F);
+ Rect r = new Rect(x - wHalfSide, y, z - hHalfSide, x + wHalfSide, y, z + hHalfSide, m);
+ WearAction action = new WearAction();
+ action.limb = this.limb;
+ action.val = s;
+ r.addAction(action);
+ r.addHandler(new ClickSensor(action, 1));
+ this.add(r);
+ this.subs[i] = r;
+ }
+ }
+
+ col++;
+ i++;
+ }
+
+ row++;
+ }
+ }
+ }
+ }
+
+ private void unbuild() {
+ if (this.subs != null) {
+ int i = this.subs.length;
+
+ while (--i >= 0) {
+ if (this.subs[i] != null) {
+ this.subs[i].detach();
+ }
+ }
+ }
+
+ this.subs = null;
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Limb"));
+ } else if (mode == 1) {
+ ret = new String("" + this.limb);
+ } else if (mode == 2) {
+ String s = (String)value;
+ if (s.length() >= 1) {
+ this.limb = s.charAt(0);
+ this.rebuild();
+ }
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Tile List"));
+ } else if (mode == 1) {
+ ret = new String(this.tileList);
+ } else if (mode == 2) {
+ this.tileList = (String)value;
+ this.rebuild();
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 2, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ this.unbuild();
+ s.saveVersion(2, classCookie);
+ super.saveState(s);
+ this.rebuild();
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ int vers = r.restoreVersion(classCookie);
+ switch (vers) {
+ case 0:
+ super.restoreState(r);
+ r.restoreString();
+ r.restoreString();
+ break;
+ case 1:
+ super.restoreState(r);
+ r.restoreString();
+ break;
+ case 2:
+ super.restoreState(r);
+ break;
+ default:
+ throw new TooNewException();
+ }
+
+ this.rebuild();
+ }
+}
diff --git a/NET/worlds/scape/WebPageWall.java b/NET/worlds/scape/WebPageWall.java
new file mode 100644
index 0000000..1dbe843
--- /dev/null
+++ b/NET/worlds/scape/WebPageWall.java
@@ -0,0 +1,408 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.DefaultConsole;
+import NET.worlds.console.NoWebControlException;
+import NET.worlds.console.WebControl;
+import NET.worlds.console.WebControlFactory;
+import NET.worlds.console.WebControlImp;
+import NET.worlds.console.WebControlListener;
+import NET.worlds.core.IniFile;
+import NET.worlds.network.URL;
+import java.io.IOException;
+
+public class WebPageWall extends Rect implements WebControlListener {
+ WebControlImp _wci = null;
+ TextureSurface _surface;
+ Texture[] _textures;
+ Material _material = null;
+ String _textureURL = "$SCRIPTSERVERgetad.pl?u=$USERNAME";
+ String _postTextureData = null;
+ String _adURL = "http://www.worlds.com/";
+ String _postAdData = null;
+ String _defTextureURL = IniFile.override().getIniString("defaultAd", "adworlds.cmp");
+ int _xPercent = 100;
+ int _yPercent = 100;
+ int _xSurface = 468;
+ int _ySurface = 60;
+ boolean _hasToolbar = true;
+ boolean _isFixed = false;
+ int _rows = 1;
+ int _refresh = 5;
+ boolean _passClicks = true;
+ boolean _isAdBanner = true;
+ boolean _retryURL = false;
+ int frameCnt = -1;
+ private static Object classCookie = new Object();
+
+ WebPageWall() {
+ }
+
+ public boolean getIsAdBanner() {
+ return this._isAdBanner;
+ }
+
+ public void rebuild() {
+ this.unbuild();
+ this.assignMaterial();
+ }
+
+ public void unbuild() {
+ if (this._wci != null) {
+ this._wci.detach();
+ this._wci = null;
+ }
+ }
+
+ @Override
+ public void detach() {
+ this.unbuild();
+ super.detach();
+ }
+
+ @Override
+ public void finalize() {
+ this.unbuild();
+ super.finalize();
+ }
+
+ @Override
+ public boolean handle(MouseDownEvent event) {
+ if ((event.key & 1) == 1) {
+ Point2 pt = this.deproject();
+ if (this._passClicks) {
+ double realX = (double)pt.x * this._surface.getWidth();
+ double realY = (double)pt.y * this._surface.getHeight();
+ realY = this._surface.getHeight() - realY;
+ this._surface.sendLeftClick((int)realX, (int)realY);
+ return false;
+ }
+
+ Console c = Console.getActive();
+ if (c != null && c instanceof DefaultConsole) {
+ DefaultConsole dc = (DefaultConsole)c;
+
+ try {
+ WebControl wc = new WebControl(dc.getRender(), this._xPercent, this._yPercent, this._hasToolbar, this._isFixed, false);
+ wc.activate();
+ wc.setURL(this._adURL, this._postAdData);
+ } catch (NoWebControlException var7) {
+ new SendURLAction(this._adURL).doIt();
+ }
+ }
+ }
+
+ return false;
+ }
+
+ @Override
+ public void prerender(Camera cam) {
+ Point3Temp p = this.inCamSpace(cam);
+ boolean v = p != null && p.z > 1.0F && p.x < p.z && -p.x < p.z;
+ if (v) {
+ this.visible = true;
+ }
+ }
+
+ @Override
+ public boolean handle(FrameEvent f) {
+ if (this.visible) {
+ if (this._retryURL && this._wci != null) {
+ if (!this._wci.setURL(this._textureURL, this._postTextureData)) {
+ return false;
+ }
+
+ this._retryURL = false;
+ }
+
+ if (this._surface != null) {
+ if (this.frameCnt <= this._refresh && this.frameCnt != -1) {
+ this.frameCnt++;
+ } else {
+ if (this.frameCnt != -1 && this._refresh == -1) {
+ return false;
+ }
+
+ this.frameCnt = 0;
+ this.draw();
+ }
+ }
+ }
+
+ return false;
+ }
+
+ public WebControlImp getWebControlImp() {
+ return this._wci;
+ }
+
+ private void assignMaterial() {
+ int xTex = this._xSurface / 128;
+ if (xTex < 1) {
+ xTex = 1;
+ }
+
+ int yTex = this._ySurface / 128;
+ if (yTex < 1) {
+ yTex = 1;
+ }
+
+ this._surface = null;
+ if (this._wci != null) {
+ this._wci.detach();
+ }
+
+ this._wci = null;
+ this._rows = yTex;
+ this._material = new Material(URL.make(this._defTextureURL), xTex, yTex);
+ this.setMaterial(this._material);
+ this._textures = this._material.getTextures();
+ this._surface = new TextureSurface(this._textures, yTex, this._xSurface, this._ySurface);
+
+ try {
+ this._wci = WebControlFactory.createWebControlImp(this._surface.getHwnd(), false, this._isAdBanner);
+ } catch (NoWebControlException var4) {
+ System.out.println("Could not create MSIE control for billboard.");
+ this._wci = null;
+ return;
+ }
+
+ if (!this._wci.setURL(this._textureURL, this._postTextureData)) {
+ this._retryURL = true;
+ }
+
+ this._wci.addListener(this);
+ }
+
+ public synchronized void draw() {
+ if (this._surface != null && this._wci != null) {
+ this._surface.setTextures(this._material.getTextures(), this._rows);
+ this._surface.draw(this._wci);
+ }
+ }
+
+ @Override
+ public void webControlEvent(int eventID) {
+ if (eventID == 1 && this._refresh == -1) {
+ this.draw();
+ }
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Wall's URL"));
+ } else if (mode == 1) {
+ ret = this._textureURL;
+ } else if (mode == 2) {
+ this._textureURL = (String)value;
+ this.rebuild();
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Wall's POST data"));
+ } else if (mode == 1) {
+ ret = this._postTextureData;
+ } else if (mode == 2) {
+ this._postTextureData = (String)value;
+ this.rebuild();
+ }
+ break;
+ case 2:
+ if (mode == 0) {
+ ret = IntegerPropertyEditor.make(new Property(this, index, "Wall Page Width (pixels)"), 0, 1024);
+ } else if (mode == 1) {
+ ret = new Integer(this._xSurface);
+ } else if (mode == 2) {
+ this._xSurface = (Integer)value;
+ this.rebuild();
+ }
+ break;
+ case 3:
+ if (mode == 0) {
+ ret = IntegerPropertyEditor.make(new Property(this, index, "Wall Page Height (pixels)"), 0, 1024);
+ } else if (mode == 1) {
+ ret = new Integer(this._ySurface);
+ } else if (mode == 2) {
+ this._ySurface = (Integer)value;
+ this.rebuild();
+ }
+ break;
+ case 4:
+ if (mode == 0) {
+ ret = IntegerPropertyEditor.make(new Property(this, index, "Wall Refresh Rate (frames)"), -1, 1024);
+ } else if (mode == 1) {
+ ret = new Integer(this._refresh);
+ } else if (mode == 2) {
+ this._refresh = (Integer)value;
+ }
+ break;
+ case 5:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Use Scrollbars"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(!this._isAdBanner);
+ } else if (mode == 2) {
+ this._isAdBanner = !(Boolean)value;
+ }
+ break;
+ case 6:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(
+ new Property(this, index, "Pass clicks"), "No - Click launches target page", "Yes - Mouse events passed through to wall page"
+ );
+ } else if (mode == 1) {
+ ret = new Boolean(this._passClicks);
+ } else if (mode == 2) {
+ this._passClicks = (Boolean)value;
+ }
+ break;
+ case 7:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Target URL for click"));
+ } else if (mode == 1) {
+ ret = this._adURL;
+ } else if (mode == 2) {
+ this._adURL = (String)value;
+ }
+ break;
+ case 8:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Target's POST data"));
+ } else if (mode == 1) {
+ ret = this._postAdData;
+ } else if (mode == 2) {
+ this._postAdData = (String)value;
+ this.rebuild();
+ }
+ break;
+ case 9:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Target Page Size Units"), "Percentage", "Pixels");
+ } else if (mode == 1) {
+ ret = new Boolean(this._isFixed);
+ } else if (mode == 2) {
+ this._isFixed = (Boolean)value;
+ }
+ break;
+ case 10:
+ if (mode == 0) {
+ ret = IntegerPropertyEditor.make(new Property(this, index, "Target X Overlay % or Width"), 0, 1024);
+ } else if (mode == 1) {
+ ret = new Integer(this._xPercent);
+ } else if (mode == 2) {
+ this._xPercent = (Integer)value;
+ }
+ break;
+ case 11:
+ if (mode == 0) {
+ ret = IntegerPropertyEditor.make(new Property(this, index, "Target Y Overlay % or Height"), 0, 1024);
+ } else if (mode == 1) {
+ ret = new Integer(this._yPercent);
+ } else if (mode == 2) {
+ this._yPercent = (Integer)value;
+ }
+ break;
+ case 12:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Target Page Has Toolbar"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(this._hasToolbar);
+ } else if (mode == 2) {
+ this._hasToolbar = (Boolean)value;
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 13, mode, value);
+ }
+
+ if (mode == 2) {
+ this.rebuild();
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(3, classCookie);
+ super.saveState(s);
+ s.saveString(this._adURL);
+ s.saveString(this._textureURL);
+ s.saveInt(this._xPercent);
+ s.saveInt(this._yPercent);
+ s.saveBoolean(this._hasToolbar);
+ s.saveBoolean(this._isFixed);
+ s.saveInt(this._xSurface);
+ s.saveInt(this._ySurface);
+ s.saveInt(this._refresh);
+ s.saveBoolean(this._passClicks);
+ s.saveBoolean(this._isAdBanner);
+ s.saveString(this._postTextureData);
+ s.saveString(this._postAdData);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 1:
+ super.restoreState(r);
+ this._adURL = r.restoreString();
+ this._textureURL = r.restoreString();
+ this._xPercent = r.restoreInt();
+ this._yPercent = r.restoreInt();
+ this._hasToolbar = r.restoreBoolean();
+ this._isFixed = r.restoreBoolean();
+ this._xSurface = r.restoreInt();
+ this._ySurface = r.restoreInt();
+ this._refresh = r.restoreInt();
+ this._passClicks = r.restoreBoolean();
+ this._isAdBanner = r.restoreBoolean();
+ break;
+ case 2:
+ super.restoreState(r);
+ this._adURL = r.restoreString();
+ this._textureURL = r.restoreString();
+ this._xPercent = r.restoreInt();
+ this._yPercent = r.restoreInt();
+ this._hasToolbar = r.restoreBoolean();
+ this._isFixed = r.restoreBoolean();
+ this._xSurface = r.restoreInt();
+ this._ySurface = r.restoreInt();
+ this._refresh = r.restoreInt();
+ this._passClicks = r.restoreBoolean();
+ this._isAdBanner = r.restoreBoolean();
+ this._postTextureData = r.restoreString();
+ break;
+ case 3:
+ super.restoreState(r);
+ this._adURL = r.restoreString();
+ this._textureURL = r.restoreString();
+ this._xPercent = r.restoreInt();
+ this._yPercent = r.restoreInt();
+ this._hasToolbar = r.restoreBoolean();
+ this._isFixed = r.restoreBoolean();
+ this._xSurface = r.restoreInt();
+ this._ySurface = r.restoreInt();
+ this._refresh = r.restoreInt();
+ this._passClicks = r.restoreBoolean();
+ this._isAdBanner = r.restoreBoolean();
+ this._postTextureData = r.restoreString();
+ this._postAdData = r.restoreString();
+ break;
+ default:
+ throw new TooNewException();
+ }
+
+ this.rebuild();
+ }
+
+ @Override
+ public boolean acceptsLeftClicks() {
+ return this.getIsAdBanner() ? true : this.getMouseOver();
+ }
+}
diff --git a/NET/worlds/scape/WebWallControlAction.java b/NET/worlds/scape/WebWallControlAction.java
new file mode 100644
index 0000000..7420f51
--- /dev/null
+++ b/NET/worlds/scape/WebWallControlAction.java
@@ -0,0 +1,128 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+public class WebWallControlAction extends Action {
+ private final int reload = 1;
+ private final int setURL = 2;
+ private final int refresh = 3;
+ private final int back = 4;
+ private final int forward = 5;
+ private final int stop = 6;
+ private final int home = 7;
+ private int mode = 1;
+ private String url;
+ private String postData;
+ private WebPageWall webWall = null;
+ private static Object classCookie = new Object();
+
+ WebWallControlAction() {
+ this.postData = null;
+ this.url = "http://www.worlds.com/";
+ }
+
+ @Override
+ public Persister trigger(Event e, Persister seqID) {
+ if (!this.getWebWall()) {
+ System.out.println("ERROR! Tried to attach WebWallControlAction to something other than a WebWall object.");
+ return null;
+ } else {
+ switch (this.mode) {
+ case 1:
+ this.webWall.rebuild();
+ break;
+ case 2:
+ this.webWall.getWebControlImp().setURL(this.url, this.postData);
+ break;
+ case 3:
+ this.webWall.getWebControlImp().refresh();
+ break;
+ case 4:
+ this.webWall.getWebControlImp().goBack();
+ break;
+ case 5:
+ this.webWall.getWebControlImp().goForward();
+ break;
+ case 6:
+ this.webWall.getWebControlImp().stop();
+ break;
+ case 7:
+ this.webWall.getWebControlImp().home();
+ }
+
+ return null;
+ }
+ }
+
+ private boolean getWebWall() {
+ if (this.webWall != null) {
+ return true;
+ } else {
+ Object owner = this.getOwner();
+ if (owner != null && owner instanceof WebPageWall) {
+ this.webWall = (WebPageWall)owner;
+ return this.webWall == null ? false : this.webWall.getWebControlImp() != null;
+ } else {
+ return false;
+ }
+ }
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(0, classCookie);
+ super.saveState(s);
+ s.saveInt(this.mode);
+ s.saveString(this.url);
+ s.saveString(this.postData);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ this.mode = r.restoreInt();
+ this.url = r.restoreString();
+ this.postData = r.restoreString();
+ }
+ }
+
+ @Override
+ public Object properties(int index, int offset, int pmode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (pmode == 0) {
+ ret = IntegerPropertyEditor.make(new Property(this, index, "1=Reload, 2=SetURL, 3=Refresh, 4=Back, 5=Fwd, 6=Stop, 7=Home"));
+ } else if (pmode == 1) {
+ ret = new Integer(this.mode);
+ } else if (pmode == 2) {
+ this.mode = (Integer)value;
+ }
+ break;
+ case 1:
+ if (pmode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "URL for mode 2"));
+ } else if (pmode == 1) {
+ ret = this.url;
+ } else if (pmode == 2) {
+ this.url = ((String)value).trim();
+ }
+ break;
+ case 2:
+ if (pmode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "POST data for mode 2"));
+ } else if (pmode == 1) {
+ ret = this.postData;
+ } else if (pmode == 2) {
+ this.postData = ((String)value).trim();
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 3, pmode, value);
+ }
+
+ return ret;
+ }
+}
diff --git a/NET/worlds/scape/Whiteboard.java b/NET/worlds/scape/Whiteboard.java
new file mode 100644
index 0000000..5fadb07
--- /dev/null
+++ b/NET/worlds/scape/Whiteboard.java
@@ -0,0 +1,96 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import java.awt.Color;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class Whiteboard extends Attribute {
+ String _line = "default text";
+ private static Object classCookie = new Object();
+
+ public Whiteboard(int attrID) {
+ super(attrID);
+ }
+
+ public Whiteboard() {
+ }
+
+ @Override
+ protected void noteAddingTo(SuperRoot owner) {
+ this.nada((Surface)((Sharer)owner).getOwner());
+ this.setOwnerText();
+ }
+
+ public void set(String s) {
+ this._line = s;
+ this.setOwnerText();
+ this.noteChange();
+ }
+
+ protected void nada(Surface s) {
+ }
+
+ private void setOwnerText() {
+ Sharer sh = (Sharer)this.getOwner();
+ if (sh != null) {
+ Surface surf = (Surface)sh.getOwner();
+ surf.setMaterial(new Material(new StringTexture(this._line, Console.message("MaterialFont"), 20, Color.black, Color.white)));
+ }
+ }
+
+ public String get() {
+ return this._line;
+ }
+
+ @Override
+ public void generateNetData(DataOutputStream s) throws IOException {
+ s.writeUTF(this._line);
+ }
+
+ @Override
+ public void setFromNetData(DataInputStream ds, int len) throws IOException {
+ this.set(ds.readUTF());
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Whiteboard text"));
+ } else if (mode == 1) {
+ ret = this._line;
+ } else if (mode == 2) {
+ this.set((String)value);
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 1, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(0, classCookie);
+ super.saveState(s);
+ s.saveString(this._line);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ this._line = r.restoreString();
+ this.setOwnerText();
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/WidgetButton.java b/NET/worlds/scape/WidgetButton.java
new file mode 100644
index 0000000..6d25390
--- /dev/null
+++ b/NET/worlds/scape/WidgetButton.java
@@ -0,0 +1,125 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.ImageCanvas;
+import java.awt.Canvas;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Image;
+
+abstract class WidgetButton extends Canvas {
+ private String name;
+ private Image image;
+ private Dimension dim;
+ private String prompt;
+ private ToolBar toolbar;
+ private boolean depressed;
+
+ WidgetButton(ToolBar toolbar, String name, String prompt) {
+ this.name = name;
+ this.toolbar = toolbar;
+ this.prompt = prompt;
+ }
+
+ public WObject getWObject() {
+ return this.toolbar.getCurrentWObject();
+ }
+
+ public String drag(boolean initialDrag, float deltax, float deltay) {
+ return null;
+ }
+
+ protected ToolBar getToolBar() {
+ return this.toolbar;
+ }
+
+ protected Point3Temp getWorldAxis(int ax, int ay, int az) {
+ Point3Temp p = new Point3(ax, ay, az).vectorTimes(Pilot.getActive());
+ float x = Math.abs(p.x);
+ float y = Math.abs(p.y);
+ float z = Math.abs(p.z);
+ if (x > y) {
+ if (x > z) {
+ return p.x > 0.0F ? Point3Temp.make(1.0F, 0.0F, 0.0F) : Point3Temp.make(-1.0F, 0.0F, 0.0F);
+ }
+ } else if (y > z) {
+ return p.y > 0.0F ? Point3Temp.make(0.0F, 1.0F, 0.0F) : Point3Temp.make(0.0F, -1.0F, 0.0F);
+ }
+
+ return p.z > 0.0F ? Point3Temp.make(0.0F, 0.0F, 1.0F) : Point3Temp.make(0.0F, 0.0F, -1.0F);
+ }
+
+ protected void applyWorldTransform(boolean initialDrag, Transform t) {
+ WObject wobj = this.getWObject();
+ if (initialDrag) {
+ Console.getFrame().getEditTile().addUndoable(new UndoablTransform(wobj));
+ }
+
+ Point3Temp pos = wobj.getPosition();
+ wobj.moveTo(0.0F, 0.0F, 0.0F).post(t).moveBy(pos);
+ wobj.markEdited();
+ }
+
+ public void draw(boolean depressed) {
+ this.depressed = depressed;
+ Graphics g = this.getGraphics();
+ this.drawOutline(g);
+ g.dispose();
+ }
+
+ public void perform() {
+ }
+
+ public boolean usesDrag() {
+ return true;
+ }
+
+ private void drawOutline(Graphics g) {
+ g.setColor(this.getBackground());
+ g.draw3DRect(0, 0, this.dim.width - 1, this.dim.height - 1, !this.depressed);
+ }
+
+ public boolean available() {
+ return this.getWObject() != null;
+ }
+
+ @Override
+ public void paint(Graphics g) {
+ super.paint(g);
+ if (this.available() && this.dim.width != 0) {
+ g.drawImage(this.image, 2, 2, this);
+ this.drawOutline(g);
+ }
+ }
+
+ private Dimension imageSize() {
+ if (this.image == null) {
+ this.image = ImageCanvas.getSystemImage(this.name, this);
+ if (this.image != null) {
+ int width = this.image.getWidth(this);
+ int height = this.image.getHeight(this);
+ if (width != -1 && height != -1) {
+ return this.dim = new Dimension(width + 4, height + 4);
+ }
+ }
+
+ this.dim = new Dimension(0, 0);
+ }
+
+ return this.dim;
+ }
+
+ @Override
+ public Dimension preferredSize() {
+ return this.imageSize();
+ }
+
+ @Override
+ public Dimension minimumSize() {
+ return this.imageSize();
+ }
+
+ public String getPrompt() {
+ return this.prompt;
+ }
+}
diff --git a/NET/worlds/scape/WobClassLoader.java b/NET/worlds/scape/WobClassLoader.java
new file mode 100644
index 0000000..cc7b8d5
--- /dev/null
+++ b/NET/worlds/scape/WobClassLoader.java
@@ -0,0 +1,96 @@
+package NET.worlds.scape;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.util.Hashtable;
+
+public class WobClassLoader extends ClassLoader {
+ static Hashtable loaders = new Hashtable();
+ Hashtable classes = new Hashtable();
+ String zipName;
+
+ public static synchronized Class get(String zipName, String cname) {
+ WobClassLoader cl = (WobClassLoader)loaders.get(zipName);
+ if (cl == null) {
+ cl = new WobClassLoader(zipName);
+ loaders.put(zipName, cl);
+ }
+
+ try {
+ return cl.loadClass(cname, true);
+ } catch (ClassNotFoundException var4) {
+ return null;
+ }
+ }
+
+ public WobClassLoader(String n) {
+ this.zipName = n;
+ }
+
+ @Override
+ protected synchronized Class loadClass(String cname, boolean resolve) throws ClassNotFoundException {
+ Class cl = (Class)this.classes.get(cname);
+ if (cl == null) {
+ try {
+ return this.findSystemClass(cname);
+ } catch (NoClassDefFoundError var7) {
+ } catch (ClassNotFoundException var8) {
+ }
+
+ byte[] data = this.loadData(cname);
+ if (data != null) {
+ try {
+ cl = this.defineClass(data, 0, data.length);
+ } catch (ClassFormatError var6) {
+ throw new ClassNotFoundException(cname);
+ }
+ }
+
+ if (cl == null || !cname.equals(cl.getName())) {
+ throw new ClassNotFoundException(cname);
+ }
+
+ this.classes.put(cname, cl);
+ }
+
+ if (resolve) {
+ this.resolveClass(cl);
+ }
+
+ return cl;
+ }
+
+ private byte[] loadData(String cname) {
+ byte[] data = (byte[])null;
+ InputStream in = null;
+
+ byte[] var7;
+ try {
+ if (cname == null) {
+ return null;
+ }
+
+ File file = new File(this.zipName);
+ int len = (int)file.length();
+ in = new FileInputStream(file);
+ data = new byte[len];
+ if (in.read(data) != len) {
+ return null;
+ }
+
+ var7 = data;
+ } catch (Exception var16) {
+ return null;
+ } finally {
+ if (in != null) {
+ try {
+ in.close();
+ } catch (Exception var15) {
+ }
+ }
+ }
+
+ return var7;
+ }
+}
diff --git a/NET/worlds/scape/WobLoaded.java b/NET/worlds/scape/WobLoaded.java
new file mode 100644
index 0000000..11afd39
--- /dev/null
+++ b/NET/worlds/scape/WobLoaded.java
@@ -0,0 +1,5 @@
+package NET.worlds.scape;
+
+public interface WobLoaded {
+ void wobLoaded(WobLoader var1, SuperRoot var2);
+}
diff --git a/NET/worlds/scape/WobLoader.java b/NET/worlds/scape/WobLoader.java
new file mode 100644
index 0000000..eb6d0e6
--- /dev/null
+++ b/NET/worlds/scape/WobLoader.java
@@ -0,0 +1,107 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.network.URL;
+
+public class WobLoader implements BGLoaded {
+ private WobLoaded loaded;
+ private URL origURL;
+ SuperRoot value;
+
+ public WobLoader(URL url, WobLoaded loaded) {
+ this(url, loaded, false);
+ }
+
+ public WobLoader(URL url, WobLoaded loaded, boolean immediate) {
+ this.origURL = url;
+ this.loaded = loaded;
+ if (url.endsWith(".class")) {
+ String s = url.getAbsolute();
+ if (s.startsWith("system:")) {
+ int len = s.length();
+
+ try {
+ Class c = Class.forName(s.substring(7, len - 6));
+ SuperRoot sr = (SuperRoot)c.newInstance();
+ sr.loadInit();
+ this.gotIt(sr);
+ } catch (Exception var8) {
+ var8.printStackTrace(System.out);
+ Console.println("Can't make instance of class " + url);
+ this.gotIt(null);
+ }
+
+ return;
+ }
+ }
+
+ if (immediate) {
+ String s = url.unalias();
+ if (s.indexOf(58) > 1) {
+ this.gotIt(null);
+ } else {
+ this.syncBackgroundLoad(this.asyncBackgroundLoad(s, url), url);
+ }
+ } else {
+ BackgroundLoader.get(this, url);
+ }
+ }
+
+ public static SuperRoot immediateLoad(URL url) {
+ WobLoader w = new WobLoader(url, null, true);
+ return w.value;
+ }
+
+ @Override
+ public Object asyncBackgroundLoad(String localName, URL remoteURL) {
+ return remoteURL.endsWith(".class") ? WobClassLoader.get(localName, remoteURL.getClassName()) : localName;
+ }
+
+ @Override
+ public boolean syncBackgroundLoad(Object obj, URL remoteURL) {
+ SuperRoot sr = null;
+ if (obj != null) {
+ if (obj instanceof String) {
+ sr = SuperRoot.readFile((String)obj, remoteURL);
+ } else {
+ try {
+ sr = (SuperRoot)((Class)obj).newInstance();
+ sr.loadInit();
+ } catch (Exception var5) {
+ var5.printStackTrace(System.out);
+ }
+ }
+ }
+
+ this.gotIt(sr);
+ return false;
+ }
+
+ private void gotIt(SuperRoot s) {
+ if (s != null) {
+ s.setSourceURL(this.origURL);
+ }
+
+ this.value = s;
+ if (this.loaded != null) {
+ this.loaded.wobLoaded(this, s);
+ }
+ }
+
+ @Override
+ public Room getBackgroundLoadRoom() {
+ if (this.loaded instanceof SuperRoot) {
+ for (SuperRoot o = (SuperRoot)this.loaded; o != null; o = o.getOwner()) {
+ if (o instanceof WObject) {
+ return ((WObject)o).getRoom();
+ }
+ }
+ }
+
+ return null;
+ }
+
+ public URL getWobName() {
+ return this.origURL;
+ }
+}
diff --git a/NET/worlds/scape/World.java b/NET/worlds/scape/World.java
new file mode 100644
index 0000000..87b7ca4
--- /dev/null
+++ b/NET/worlds/scape/World.java
@@ -0,0 +1,1157 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.AdBanner;
+import NET.worlds.console.Console;
+import NET.worlds.console.Gamma;
+import NET.worlds.console.Main;
+import NET.worlds.console.WorldsMarkPart;
+import NET.worlds.core.Hashtable;
+import NET.worlds.core.IniFile;
+import NET.worlds.core.Std;
+import NET.worlds.network.Galaxy;
+import NET.worlds.network.NetUpdate;
+import NET.worlds.network.URL;
+import NET.worlds.network.WorldServer;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.text.MessageFormat;
+import java.util.Enumeration;
+import java.util.Vector;
+
+public class World extends SuperRoot implements URLSelf, LoadedURLSelf, IncrementalRestorer {
+ static WorldRedirector redir = new WorldRedirector(URL.make(Gamma.getHome() + "redir.txt"));
+ private static boolean cloistered = false;
+ private static boolean cloisteredSet = false;
+ private String adCubeBaseURL = null;
+ private boolean hasClickableAdCube = false;
+ private boolean adCubeFormatIsGif = false;
+ private String defaultAdCubeURL = IniFile.override().getIniString("defaultAdCubeURL", "http://www.worlds.com/");
+ private boolean hasBeenEdited = false;
+ private String defaultRoomName = "";
+ protected Hashtable roomHash = new Hashtable();
+ protected Vector<Object> roomList = new Vector<Object>();
+ Vector<Object> eventHandlers;
+ private static boolean[] didTouch = new boolean[1];
+ private static int lastGeneratedFrameEvents;
+ private int renderStamp;
+ private int timeoutAge = 15000;
+ private int nextRoomCheck = 0;
+ private static Hashtable worldHash = new Hashtable();
+ private static Vector<World> worldList = new Vector<World>();
+ private boolean registerable = false;
+ private static Object classCookie = new Object();
+ private static final int INIT = 0;
+ private static final int RESTOREROOMS = 1;
+ private static final int ADDROOMS = 2;
+ private static final int LOADCONSOLE = 3;
+ private static final int DONE = -1;
+ private Enumeration<Room> tmpenum;
+ protected Console console = null;
+ String loadErr;
+ static URL defaultServerURL = URL.make("worldserver://www.3dcd.com:6650/");
+ private URL worldServerURL;
+ private URL desiredWorldServerURL = defaultServerURL;
+ private boolean isCourtesyVIP;
+ private boolean isForceHuman = false;
+ private boolean hasAdBanner = false;
+ private int adBannerWidth = 474;
+ private int adBannerHeight = 65;
+ private String adBannerURL = "$SCRIPTSERVERgetad.pl?s=$SERIALNUM";
+ private static AdBanner theAdBanner = null;
+ private boolean isMultiuser;
+
+ World() {
+ }
+
+ @Override
+ public World getWorld() {
+ return this;
+ }
+
+ public static void load(URL url, LoadedURLSelf callback, boolean force) {
+ if (Gamma.loadProgress != null) {
+ Gamma.loadProgress.setMessage("Loading world files...");
+ Gamma.loadProgress.advance();
+ }
+
+ if (url.toString().indexOf("UserHomeWorld") != -1) {
+ String homeWorld = WorldsMarkPart.getFirstSystemMarkURL();
+ if (homeWorld != null) {
+ int poundIdx = homeWorld.indexOf("#");
+ if (poundIdx != -1) {
+ homeWorld = homeWorld.substring(0, poundIdx);
+ }
+
+ url = URL.make(homeWorld);
+ }
+ }
+
+ File f = new File(url.unalias());
+ if (!f.exists()) {
+ url = redir.get(url);
+ }
+
+ if (isProscribed(url, force)) {
+ callback.loadedURLSelf(null, url, "Can't autoload WorldsStore");
+ } else {
+ World w = (World)worldHash.get(url);
+ if (w != null) {
+ w.incRef();
+ callback.loadedURLSelf(w, url, null);
+ } else {
+ URLSelfLoader.load(url, callback, true);
+ }
+ }
+ }
+
+ public static void load(URL url, LoadedURLSelf callback) {
+ load(url, callback, false);
+ }
+
+ public static boolean isCloistered() {
+ if (!cloisteredSet) {
+ URL homeDir = URL.make("home:" + WorldsMarkPart.getFirstWorld());
+ cloistered = new File(homeDir.unalias() + "/cloistered").exists();
+ cloisteredSet = true;
+ }
+
+ return cloistered;
+ }
+
+ public static URL getHomeStore() {
+ URL storeinf = URL.make("home:" + WorldsMarkPart.getFirstWorld() + "/store.inf");
+ URL homeStore = URL.make("home:PolyGram/polygramdlb.world");
+ File sf = new File(storeinf.unalias());
+ if (!sf.exists() || !sf.isFile()) {
+ sf = new File(URL.make("home:PolyGram/store.inf").unalias());
+ if (!sf.exists() || !sf.isFile()) {
+ return homeStore;
+ }
+ }
+
+ try {
+ BufferedReader rdr = new BufferedReader(new FileReader(sf));
+ String s = rdr.readLine();
+ rdr.close();
+ homeStore = new URL(s);
+ } catch (IOException var5) {
+ }
+
+ return homeStore;
+ }
+
+ public static boolean isWorldsStoreProscribed() {
+ return isCloistered() && IniFile.gamma().getIniInt("WorldsStoreProscribed", 1) != 0;
+ }
+
+ public static boolean isProscribed(URL url, boolean forceLoad) {
+ return !forceLoad && !WorldValidator.allow(url.toString());
+ }
+
+ public boolean isHomeWorld() {
+ URL url = this.getSourceURL();
+ if (url != null) {
+ URL homeURL = URL.make("home:" + WorldsMarkPart.getFirstWorld());
+ if (url.unalias().startsWith(homeURL.unalias() + "/")) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public void setEdited(boolean state) {
+ if (state != this.hasBeenEdited) {
+ this.hasBeenEdited = state;
+ worldListChanged();
+ }
+ }
+
+ @Override
+ public void markEdited() {
+ this.setEdited(true);
+ }
+
+ public String getAdCubeBaseURL() {
+ if (this.adCubeBaseURL == null) {
+ String worldURL = this.getSourceURL().toString();
+ if (worldURL.lastIndexOf("/") == -1) {
+ return "ads/ad";
+ } else {
+ worldURL = worldURL.substring(0, worldURL.lastIndexOf("/"));
+ WorldServer w = Pilot.getActive().getServer();
+ if (w != null && w.getGalaxy().getOnline()) {
+ String adserverURL = NetUpdate.getUpgradeServerURL();
+ if (adserverURL != null) {
+ int i1 = worldURL.lastIndexOf("/");
+ int i2 = worldURL.lastIndexOf(":");
+ i1 = i1 > i2 ? i1 : i2;
+ if (i1 > -1) {
+ worldURL = worldURL.substring(i1 + 1);
+ }
+
+ return adserverURL + worldURL + "/ads/ad";
+ }
+ }
+
+ return worldURL + "/ads/ad";
+ }
+ } else {
+ return this.adCubeBaseURL;
+ }
+ }
+
+ public void setAdCubeBaseURL(String s) {
+ this.adCubeBaseURL = new String(s);
+ }
+
+ public boolean getHasClickableAdCube() {
+ return this.hasClickableAdCube;
+ }
+
+ public void setHasClickableAdCube(boolean b) {
+ this.hasClickableAdCube = b;
+ }
+
+ public boolean getAdCubeFormatIsGif() {
+ return this.adCubeFormatIsGif;
+ }
+
+ public void setAdCubeFormatIsGif(boolean b) {
+ this.adCubeFormatIsGif = b;
+ }
+
+ public String getDefaultAdCubeURL() {
+ return this.defaultAdCubeURL;
+ }
+
+ public void setDefaultAdCubeURL(String s) {
+ this.defaultAdCubeURL = new String(s);
+ }
+
+ public boolean getEdited() {
+ return this.hasBeenEdited;
+ }
+
+ private static void worldListChanged() {
+ if (Gamma.getShaper() != null) {
+ Gamma.getShaper().worldListChange();
+ }
+ }
+
+ @Override
+ public void getChildren(DeepEnumeration d) {
+ d.addChildEnumeration(this.getRooms());
+ if (this.eventHandlers != null) {
+ d.addChildVector(this.eventHandlers);
+ }
+ }
+
+ public Room getRoom(String roomName) {
+ if (roomName.indexOf("UserHomeRoom") != -1) {
+ roomName = this.getDefaultRoomName();
+ }
+
+ return (Room)this.roomHash.get(roomName);
+ }
+
+ public String getDefaultRoomName() {
+ if (this.getRoom(this.defaultRoomName) == null) {
+ if (this.roomList.isEmpty()) {
+ this.defaultRoomName = "";
+ } else {
+ this.defaultRoomName = ((Room)this.roomList.elementAt(0)).getName();
+ }
+ }
+
+ return this.defaultRoomName;
+ }
+
+ public void setDefaultRoomName(String name) {
+ this.defaultRoomName = name;
+ }
+
+ public void addRoom(Room room) {
+ String name = room.getName();
+ int roomNum = 1;
+
+ while (this.getRoom(name) != null) {
+ name = "Room" + roomNum++;
+ }
+
+ room.setName(name);
+ this.roomHash.put(name, room);
+ this.roomList.addElement(room);
+ this.add(room);
+ URL sourceURL = this.getSourceURL();
+ if (sourceURL != null && worldHash.containsKey(sourceURL)) {
+ room.register();
+ }
+ }
+
+ public void renameRoom(String oldName, String newName, Room room) {
+ if (oldName != null) {
+ assert this.roomHash.get(oldName) == room;
+
+ this.roomHash.remove(oldName);
+ } else {
+ assert !this.roomList.removeElement(room);
+
+ this.roomList.addElement(room);
+ }
+
+ assert newName != null;
+
+ assert room.getName().equals(newName);
+
+ this.roomHash.put(newName, room);
+ }
+
+ public void removeRoom(Room room) {
+ this.roomHash.remove(this.roomHash.getKey(room));
+ this.roomList.removeElement(room);
+ }
+
+ public Enumeration<Object> getRooms() {
+ return this.roomList.elements();
+ }
+
+ public static Room findRoomByName(String name) {
+ Enumeration<World> we = worldList.elements();
+
+ while (we.hasMoreElements()) {
+ World w = we.nextElement();
+ Enumeration<Object> re = w.getRooms();
+
+ while (re.hasMoreElements()) {
+ Room r = (Room)re.nextElement();
+ if (r.toString().equals(name)) {
+ return r;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ public void invokeActions(String actLabel) {
+ Enumeration<Object> en = this.getDeepOwned();
+
+ while (en.hasMoreElements()) {
+ Object obj = en.nextElement();
+ if (obj instanceof WObject) {
+ ((WObject)obj).doAction(actLabel, null);
+ }
+ }
+ }
+
+ public boolean deliver(FrameEvent event) {
+ if (this.eventHandlers != null) {
+ if (Main.profile != 0) {
+ int i = this.eventHandlers.size();
+
+ while (--i >= 0) {
+ FrameHandler fh = (FrameHandler)this.eventHandlers.elementAt(i);
+ int start = Std.getRealTime();
+ long startBytes = Runtime.getRuntime().freeMemory();
+ event.retargetAndDeliver(fh, null);
+ int dur = Std.getRealTime() - start;
+ long used = Runtime.getRuntime().freeMemory() - startBytes;
+ if (dur > Main.profile) {
+ System.out.println("Took " + dur + "ms and " + used + " bytes to call world eventHandler " + fh);
+ }
+ }
+ } else {
+ int i = this.eventHandlers.size();
+
+ while (--i >= 0) {
+ event.retargetAndDeliver((FrameHandler)this.eventHandlers.elementAt(i), null);
+ }
+ }
+ }
+
+ return true;
+ }
+
+ public static void generateFrameEvents(FrameEvent f) {
+ didTouch[0] = false;
+ int now = Std.getFastTime();
+ int i = worldList.size();
+
+ while (--i >= 0) {
+ World w = worldList.elementAt(i);
+ if (!w.discardIfOld(didTouch)) {
+ w.deliver(f);
+ }
+ }
+
+ if (Pilot.getActiveWorld() != null) {
+ lastGeneratedFrameEvents = now;
+ }
+ }
+
+ public Enumeration<Object> getHandlers() {
+ return this.eventHandlers == null ? new Vector<Object>().elements() : this.eventHandlers.elements();
+ }
+
+ public boolean hasHandler(SuperRoot h) {
+ return this.eventHandlers != null && this.eventHandlers.indexOf(h) != -1;
+ }
+
+ public World addHandler(SuperRoot h) {
+ if (!(h instanceof FrameHandler)) {
+ Object[] arguments = new Object[]{new String(h.getName())};
+ Console.println(MessageFormat.format(Console.message("FrameHandler"), arguments));
+ return this;
+ } else {
+ if (this.eventHandlers == null) {
+ this.eventHandlers = new Vector<Object>();
+ }
+
+ this.eventHandlers.addElement(h);
+ this.add(h);
+ return this;
+ }
+ }
+
+ public void removeHandler(SuperRoot h) {
+ if (this.eventHandlers.contains(h)) {
+ h.detach();
+ this.eventHandlers.removeElement(h);
+ if (this.eventHandlers.size() == 0) {
+ this.eventHandlers = null;
+ }
+ }
+ }
+
+ @Override
+ public void incRef() {
+ this.renderStamp = Std.getFastTime();
+ }
+
+ @Override
+ public void decRef() {
+ }
+
+ private void touchAdjacentRooms(boolean[] didTouch) {
+ if (!didTouch[0]) {
+ didTouch[0] = true;
+ Room r = Pilot.getActiveRoom();
+ if (r != null) {
+ Vector<Portal> portals = r.getOutgoingPortals();
+ int i = portals.size();
+
+ while (--i >= 0) {
+ Room farr = portals.elementAt(i).farSideRoom();
+ if (farr != null) {
+ farr.noteRef();
+ }
+ }
+ }
+ }
+ }
+
+ boolean discardIfOld(boolean[] didTouch) {
+ int now = Std.getFastTime();
+ if (now < this.nextRoomCheck) {
+ return false;
+ } else {
+ this.nextRoomCheck = now + 5000 + (int)(3000.0 * Math.random());
+ this.touchAdjacentRooms(didTouch);
+ int i = this.roomList.size();
+
+ while (--i >= 0) {
+ ((Room)this.roomList.elementAt(i)).discardIfOld();
+ }
+
+ if (this.hasBeenEdited) {
+ return false;
+ } else {
+ i = now - this.renderStamp;
+ if (i > this.timeoutAge && this.renderStamp < lastGeneratedFrameEvents && i > this.timeoutAge) {
+ this.discard();
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+ }
+
+ @Override
+ public void discard() {
+ URL url = this.getSourceURL();
+ synchronized (worldHash) {
+ worldHash.remove(url);
+ worldList.removeElement(this);
+ }
+
+ worldListChanged();
+ URLSelfLoader.unload(this);
+ if (this.eventHandlers != null) {
+ int i = this.eventHandlers.size();
+
+ while (--i >= 0) {
+ this.removeHandler((SuperRoot)this.eventHandlers.elementAt(i));
+ }
+ }
+
+ assert this.eventHandlers == null;
+
+ this.discardRooms();
+ if (this.console != null) {
+ this.console.decRef();
+ }
+
+ this.console = null;
+ System.gc();
+ System.runFinalization();
+ }
+
+ private void discardRooms() {
+ while (!this.roomList.isEmpty()) {
+ Room r = (Room)this.roomList.elementAt(0);
+ r.discard();
+ }
+ }
+
+ @Override
+ protected void finalize() {
+ this.discardRooms();
+ super.finalize();
+ }
+
+ private void markInitialized() {
+ if (this.getSourceURL() != null) {
+ this.register();
+ } else {
+ this.registerable = true;
+ }
+ }
+
+ private void register() {
+ URL url = this.getSourceURL();
+ synchronized (worldHash) {
+ assert !worldHash.containsKey(url);
+
+ worldHash.put(url, this);
+ worldList.addElement(this);
+ }
+
+ worldListChanged();
+ this.registerable = false;
+ int i = this.roomList.size();
+
+ while (--i >= 0) {
+ ((Room)this.roomList.elementAt(i)).register();
+ }
+ }
+
+ @Override
+ public void setSourceURL(URL url) {
+ super.setSourceURL(url);
+ if (this.registerable) {
+ this.register();
+ }
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Default Room Name"));
+ } else if (mode == 1) {
+ ret = this.getDefaultRoomName();
+ } else if (mode == 2) {
+ String name = (String)value;
+ if (this.getRoom(name) == null) {
+ Console.println(name + Console.message("No-room-named"));
+ } else {
+ this.setDefaultRoomName(name);
+ }
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Multiuser"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(this.getMultiuser());
+ } else if (mode == 2) {
+ this.setMultiuser((Boolean)value);
+ }
+ break;
+ case 2:
+ if (mode == 0) {
+ ret = new Property(this, index, "Console");
+ } else if (mode == 1) {
+ ret = this.console;
+ }
+ break;
+ case 3:
+ if (mode == 0) {
+ ret = PropAdder.make(new VectorProperty(this, index, "Rooms"));
+ } else if (mode == 1) {
+ ret = VectorProperty.toVector(this.roomHash);
+ } else if (mode == 4) {
+ ((Room)value).detach();
+ } else if (mode == 3) {
+ if (!(value instanceof Room)) {
+ throw new Error("Can only add Rooms to a World.");
+ }
+
+ this.addRoom((Room)value);
+ } else if (mode == 5 && value instanceof Room) {
+ ret = value;
+ }
+ break;
+ case 4:
+ if (mode == 0) {
+ ret = FloatPropertyEditor.make(new Property(this, index, "Time-out Age (seconds)"));
+ } else if (mode == 1) {
+ ret = new Float(this.timeoutAge / 1000.0F);
+ } else if (mode == 2) {
+ this.timeoutAge = Math.round((Float)value * 1000.0F);
+ }
+ break;
+ case 5:
+ if (mode == 0) {
+ ret = PropAdder.make(new VectorProperty(this, index, "Running Actions (delete to stop)"));
+ } else if (mode == 1) {
+ if (this.eventHandlers != null) {
+ ret = this.eventHandlers.clone();
+ }
+ } else if (mode == 4) {
+ this.removeHandler((SuperRoot)value);
+ }
+ break;
+ case 6:
+ if (mode == 0) {
+ ret = URLPropertyEditor.make(new Property(this, index, "Server URL"), "console");
+ } else if (mode == 1) {
+ ret = this.desiredWorldServerURL;
+ if (ret != null) {
+ String u = this.desiredWorldServerURL.unalias();
+ if (u.startsWith("worldserver://")) {
+ ret = URL.make(u + "default.console");
+ }
+ }
+ } else if (mode == 2) {
+ URL url = (URL)value;
+ if (url != null) {
+ String u = url.unalias();
+ int len = u.length();
+ if (u.startsWith("worldserver://")) {
+ if (!url.endsWith("/default.console") || len < 31) {
+ Console.println(Console.message("server-URL") + "default.console");
+ break;
+ }
+
+ u = u.substring(14, len - 16);
+ }
+
+ url = Console.makeServerURL(u);
+ }
+
+ this.setWorldServerURL(url);
+ }
+ break;
+ case 7:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Courtesy VIP"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(this.getCourtesyVIP());
+ } else if (mode == 2) {
+ this.setCourtesyVIP((Boolean)value);
+ }
+ break;
+ case 8:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Force Human"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(this.getForceHuman());
+ } else if (mode == 2) {
+ this.setForceHuman((Boolean)value);
+ }
+ break;
+ case 9:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Has Ad Banner"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(this.getHasAdBanner());
+ } else if (mode == 2) {
+ this.setHasAdBanner((Boolean)value);
+ this.setupAdBanner();
+ }
+ break;
+ case 10:
+ if (mode == 0) {
+ ret = IntegerPropertyEditor.make(new Property(this, index, "Banner Width"));
+ } else if (mode == 1) {
+ ret = new Integer(this.getBannerWidth());
+ } else if (mode == 2) {
+ this.setBannerWidth((Integer)value);
+ this.setupAdBanner();
+ }
+ break;
+ case 11:
+ if (mode == 0) {
+ ret = IntegerPropertyEditor.make(new Property(this, index, "Banner Height"));
+ } else if (mode == 1) {
+ ret = new Integer(this.getBannerHeight());
+ } else if (mode == 2) {
+ this.setBannerHeight((Integer)value);
+ this.setupAdBanner();
+ }
+ break;
+ case 12:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Ad Banner URL"));
+ } else if (mode == 1) {
+ ret = this.getBannerURL();
+ } else if (mode == 2) {
+ String name = (String)value;
+ this.setBannerURL(name);
+ }
+ break;
+ case 13:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Has Clickable Ad Cube"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(this.getHasClickableAdCube());
+ } else if (mode == 2) {
+ this.setHasClickableAdCube((Boolean)value);
+ }
+ break;
+ case 14:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Ad Cube image format"), "CMP", "GIF");
+ } else if (mode == 1) {
+ ret = new Boolean(this.getAdCubeFormatIsGif());
+ } else if (mode == 2) {
+ this.setAdCubeFormatIsGif((Boolean)value);
+ }
+ break;
+ case 15:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Ad cube base URL"));
+ } else if (mode == 1) {
+ ret = this.getAdCubeBaseURL();
+ } else if (mode == 2) {
+ String name = (String)value;
+ this.setAdCubeBaseURL(name);
+ }
+ break;
+ case 16:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Ad cube default click URL"));
+ } else if (mode == 1) {
+ ret = this.getDefaultAdCubeURL();
+ } else if (mode == 2) {
+ String name = (String)value;
+ this.setDefaultAdCubeURL(name);
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 17, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ s.saveVersion(13, classCookie);
+ super.saveState(s);
+ s.saveString(this.defaultRoomName);
+ URL.save(s, this.desiredWorldServerURL);
+ s.saveInt(this.timeoutAge);
+ s.saveBoolean(this.getMultiuser());
+ s.saveBoolean(this.getCourtesyVIP());
+ s.saveBoolean(this.getForceHuman());
+ s.saveBoolean(this.getHasAdBanner());
+ s.saveInt(this.getBannerWidth());
+ s.saveInt(this.getBannerHeight());
+ s.saveString(this.getBannerURL());
+ s.saveBoolean(this.getHasClickableAdCube());
+ s.saveBoolean(this.getAdCubeFormatIsGif());
+ s.saveString(this.getAdCubeBaseURL());
+ s.saveString(this.getDefaultAdCubeURL());
+ s.save(this.roomHash);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ URLSelfLoader.immediateLoad(this, r);
+ }
+
+ private void restoreOldURL(Restorer r) throws IOException {
+ String s = r.restoreString();
+ URL url;
+ if (s == null || s.equals("UNSHARED")) {
+ url = null;
+ } else if (!s.endsWith(".console")) {
+ url = Console.makeServerURL(s);
+ } else {
+ url = URL.restore(r, s, null);
+ }
+
+ if (url == null) {
+ url = defaultServerURL;
+ } else {
+ this.setMultiuser(true);
+ }
+
+ this.setWorldServerURL(url);
+ }
+
+ public int restorePreRooms(Restorer r) throws IOException, TooNewException {
+ int version = r.restoreVersion(classCookie);
+ switch (version) {
+ case 0:
+ r.setOldFlag();
+ this.setName(r.restoreString());
+ this.defaultRoomName = r.restoreString();
+ this.restoreOldURL(r);
+ this.roomHash = (Hashtable)r.restore(false);
+ break;
+ case 1:
+ case 3:
+ r.setOldFlag();
+ super.restoreState(r);
+ this.defaultRoomName = r.restoreString();
+ this.restoreOldURL(r);
+ this.roomHash = (Hashtable)r.restore(false);
+ break;
+ case 2:
+ r.setOldFlag();
+ super.restoreState(r);
+ this.defaultRoomName = r.restoreString();
+ this.restoreOldURL(r);
+ r.restoreString();
+ this.roomHash = (Hashtable)r.restore(false);
+ break;
+ case 4:
+ super.restoreState(r);
+ this.defaultRoomName = r.restoreString();
+ this.restoreOldURL(r);
+ this.roomHash = (Hashtable)r.restore(false);
+ break;
+ case 5:
+ super.restoreState(r);
+ this.defaultRoomName = r.restoreString();
+ this.restoreOldURL(r);
+ this.timeoutAge = r.restoreInt();
+ this.roomHash = (Hashtable)r.restore(false);
+ break;
+ case 6:
+ super.restoreState(r);
+ this.defaultRoomName = r.restoreString();
+ this.restoreOldURL(r);
+ this.timeoutAge = r.restoreInt();
+ r.restoreBoolean();
+ this.roomHash = (Hashtable)r.restore(false);
+ break;
+ case 7:
+ super.restoreState(r);
+ this.defaultRoomName = r.restoreString();
+ URL url = URL.restore(r);
+ if (url == null) {
+ url = defaultServerURL;
+ } else {
+ this.setMultiuser(true);
+ }
+
+ this.setWorldServerURL(url);
+ this.timeoutAge = r.restoreInt();
+ r.restoreBoolean();
+ this.roomHash = (Hashtable)r.restore(false);
+ break;
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ super.restoreState(r);
+ this.defaultRoomName = r.restoreString();
+ this.setWorldServerURL(URL.restore(r));
+ this.timeoutAge = r.restoreInt();
+ this.setMultiuser(r.restoreBoolean());
+ if (version > 9) {
+ this.setCourtesyVIP(r.restoreBoolean());
+ }
+
+ if (version > 10) {
+ this.setForceHuman(r.restoreBoolean());
+ }
+
+ if (version > 11) {
+ this.setHasAdBanner(r.restoreBoolean());
+ this.setBannerWidth(r.restoreInt());
+ this.setBannerHeight(r.restoreInt());
+ this.setBannerURL(r.restoreString());
+ }
+
+ if (version > 12) {
+ this.setHasClickableAdCube(r.restoreBoolean());
+ this.setAdCubeFormatIsGif(r.restoreBoolean());
+ this.setAdCubeBaseURL(r.restoreString());
+ this.setDefaultAdCubeURL(r.restoreString());
+ }
+
+ this.roomHash = (Hashtable)r.restore(false);
+ break;
+ default:
+ throw new TooNewException();
+ }
+
+ Enumeration<Room> e = this.roomHash.elements();
+
+ while (e.hasMoreElements()) {
+ this.roomList.addElement(e.nextElement());
+ }
+
+ if (version < 9 && this.timeoutAge == 60000) {
+ this.timeoutAge = 15000;
+ }
+
+ return version;
+ }
+
+ @Override
+ public Object clone() {
+ World newWorld = (World)super.clone();
+ int worldNum = 1;
+
+ String newname;
+ URL key;
+ do {
+ newname = "World" + worldNum++;
+ key = URL.make("session:" + newname + ".world");
+ } while (worldHash.containsKey(key));
+
+ newWorld.setName(newname);
+ newWorld.setSourceURL(key);
+ return newWorld;
+ }
+
+ @Override
+ public int incRestore(int state, Restorer r, URLSelfLoader p) throws Exception {
+ switch (state) {
+ case 0:
+ p.itemp2 = this.restorePreRooms(r);
+ p.itemp1 = this.roomHash.restoreCount(r);
+ case 1:
+ if (--p.itemp1 >= 0) {
+ this.roomHash.restoreEntry(r);
+ return 1;
+ } else {
+ if (p.itemp2 == 4) {
+ this.timeoutAge = r.restoreInt();
+ if (this.timeoutAge == 900000 || this.timeoutAge == 60000) {
+ this.timeoutAge = 15000;
+ }
+ }
+
+ if (r.version() < 3) {
+ return -1;
+ }
+ }
+ case 2:
+ case 3:
+ return this.finishRestore(state, r.version() != Saver.version() || r.oldFlag(), p.getURL());
+ default:
+ assert false;
+
+ return -1;
+ }
+ }
+
+ public int finishRestore(int state, boolean oldFlag, URL url) throws Exception {
+ switch (state) {
+ case 0:
+ case 1:
+ this.tmpenum = this.roomHash.elements();
+ this.roomHash = new Hashtable();
+ case 2:
+ if (this.tmpenum.hasMoreElements()) {
+ Room rm = this.tmpenum.nextElement();
+ this.addRoom(rm);
+ return 2;
+ } else {
+ this.tmpenum = null;
+ }
+ case 3:
+ if (this.console == null && this.loadErr == null) {
+ return 3;
+ } else {
+ if (this.loadErr != null) {
+ throw new IOException(this.loadErr);
+ }
+
+ this.markInitialized();
+ return -1;
+ }
+ default:
+ assert false;
+
+ return -1;
+ }
+ }
+
+ @Override
+ public void postRestore(int version) {
+ super.postRestore(version);
+ if (version <= 2) {
+ int state = 0;
+
+ try {
+ while ((state = this.finishRestore(state, true, URL.make("error:This file"))) != -1) {
+ }
+ } catch (Exception var4) {
+ var4.printStackTrace(System.out);
+
+ assert false;
+ }
+ }
+ }
+
+ public Console getConsole() {
+ return this.console;
+ }
+
+ @Override
+ public void loadedURLSelf(URLSelf o, URL url, String err) {
+ if (err == null && o instanceof Console) {
+ Console oldConsole = this.console;
+ this.console = (Console)o;
+ if (oldConsole != null) {
+ Galaxy oldGalaxy = oldConsole.getGalaxy();
+ Galaxy galaxy = this.console.getGalaxy();
+
+ assert oldGalaxy != null;
+
+ assert galaxy != null;
+
+ if (oldGalaxy != galaxy) {
+ oldGalaxy.forceObjectRereg();
+ }
+
+ oldConsole.decRef();
+ }
+
+ this.worldServerURL = url;
+ if (Pilot.getActive() != null && Pilot.getActive().getWorld() == this) {
+ Pilot.changeActiveRoom(Pilot.getActive().getRoom());
+ }
+ } else {
+ if (err == null) {
+ Object[] arguments = new Object[]{new String("" + url)};
+ Console.println(MessageFormat.format(Console.message("no-world"), arguments));
+ o.decRef();
+ }
+
+ Console.println(Console.message("cant-load") + err);
+ Console.load(null, this);
+ }
+ }
+
+ public boolean getCourtesyVIP() {
+ return this.isCourtesyVIP;
+ }
+
+ private void setCourtesyVIP(boolean b) {
+ this.isCourtesyVIP = b;
+ }
+
+ public boolean getForceHuman() {
+ return this.isForceHuman;
+ }
+
+ private void setForceHuman(boolean b) {
+ this.isForceHuman = b;
+ }
+
+ public boolean getHasAdBanner() {
+ return this.hasAdBanner;
+ }
+
+ public void setHasAdBanner(boolean b) {
+ this.hasAdBanner = b;
+ }
+
+ public int getBannerWidth() {
+ return this.adBannerWidth;
+ }
+
+ public void setBannerWidth(int i) {
+ this.adBannerWidth = i;
+ }
+
+ public int getBannerHeight() {
+ return this.adBannerHeight;
+ }
+
+ public void setBannerHeight(int i) {
+ this.adBannerHeight = i;
+ }
+
+ public String getBannerURL() {
+ return this.adBannerURL;
+ }
+
+ public void setBannerURL(String s) {
+ this.adBannerURL = s;
+ }
+
+ public void setupAdBanner() {
+ if (theAdBanner != null) {
+ theAdBanner.detach();
+ theAdBanner = null;
+ }
+
+ if (this.hasAdBanner) {
+ theAdBanner = new AdBanner(this.adBannerWidth, this.adBannerHeight, this.adBannerURL);
+ }
+ }
+
+ private boolean getMultiuser() {
+ return this.isMultiuser;
+ }
+
+ private void setMultiuser(boolean b) {
+ this.isMultiuser = b;
+ this.setWorldServerURL(this.desiredWorldServerURL);
+ }
+
+ public World setWorldServerURL(URL s) {
+ this.desiredWorldServerURL = s;
+ String i = s.getInternal();
+ if (i.startsWith("worldserver://www.3dcd.com") && NetUpdate.overrideWorldServer != null) {
+ i = i.substring(26);
+ if (i.startsWith(":") && NetUpdate.overrideWorldServer.indexOf(58, 13) >= 0) {
+ int j = 1;
+
+ while (j < i.length() && Character.isDigit(i.charAt(j))) {
+ j++;
+ }
+
+ i = i.substring(j);
+ }
+
+ s = URL.make(NetUpdate.overrideWorldServer + i);
+ }
+
+ this.loadErr = null;
+ Console.load(this.isMultiuser ? s : null, this);
+ return this;
+ }
+
+ public static Enumeration<World> getWorlds() {
+ return worldList.elements();
+ }
+}
diff --git a/NET/worlds/scape/WorldRedirector.java b/NET/worlds/scape/WorldRedirector.java
new file mode 100644
index 0000000..ca6cf72
--- /dev/null
+++ b/NET/worlds/scape/WorldRedirector.java
@@ -0,0 +1,79 @@
+package NET.worlds.scape;
+
+import NET.worlds.network.URL;
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.util.Hashtable;
+
+public class WorldRedirector {
+ private Hashtable _ht = new Hashtable();
+
+ public WorldRedirector() {
+ }
+
+ public WorldRedirector(URL mappingfile) {
+ try {
+ BufferedReader in = new BufferedReader(new FileReader(mappingfile.unalias()));
+ this.addFile(in);
+ } catch (IOException var3) {
+ System.out.println("Reading " + mappingfile + " got " + var3);
+ }
+ }
+
+ void addFile(BufferedReader in) throws IOException {
+ String line;
+ while ((line = in.readLine()) != null) {
+ this.addLine(line);
+ }
+ }
+
+ void addLine(String line) {
+ if (!line.startsWith("#")) {
+ int split = line.indexOf("=>");
+ if (split > 0) {
+ String key = line.substring(0, split);
+ String value = line.substring(split + 2);
+ this._ht.put(key, value);
+ }
+ }
+ }
+
+ public URL get(URL orig) {
+ String prefix = orig.toString();
+ String suffix = "";
+
+ while (true) {
+ Object res = this._ht.get(prefix);
+ if (res != null) {
+ try {
+ URL result;
+ if (suffix == "") {
+ result = new URL((String)res);
+ } else {
+ result = new URL((String)res + "/" + suffix);
+ }
+
+ System.out.println("Redirecting " + orig + " => " + result);
+ return result;
+ } catch (MalformedURLException var7) {
+ System.out.println("Failed: " + var7);
+ }
+ }
+
+ int split = prefix.lastIndexOf(47);
+ if (split == -1) {
+ return orig;
+ }
+
+ if (suffix == "") {
+ suffix = prefix.substring(split + 1);
+ } else {
+ suffix = prefix.substring(split + 1) + "/" + suffix;
+ }
+
+ prefix = prefix.substring(0, split);
+ }
+ }
+}
diff --git a/NET/worlds/scape/WorldScript.java b/NET/worlds/scape/WorldScript.java
new file mode 100644
index 0000000..f754282
--- /dev/null
+++ b/NET/worlds/scape/WorldScript.java
@@ -0,0 +1,47 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.DialogReceiver;
+import java.util.Vector;
+
+public abstract class WorldScript implements DialogReceiver, AnimatedActionCallback {
+ public static final int CURRENT_SCRIPT_VERSION = 15;
+ protected static WorldScriptToolkit toolkit = WorldScriptToolkit.getInstance();
+
+ public int getMinScriptVersion() {
+ return 15;
+ }
+
+ public abstract void roomEnter(String var1);
+
+ public abstract void roomExit(String var1);
+
+ public abstract void worldEnter();
+
+ public abstract void worldExit();
+
+ public abstract void onEachFrame();
+
+ @Override
+ public void dialogDone(Object who, boolean confirmed) {
+ }
+
+ public void onTriggerAction(String message) {
+ }
+
+ public Vector onShapeClick(Object shape, String shapeName) {
+ return null;
+ }
+
+ @Override
+ public void motionComplete(int completionCode) {
+ }
+
+ public void onMenuClick(String action, Object source) {
+ }
+
+ public void objectVisibilityNotification(Object obj, boolean visible) {
+ }
+
+ public void onConversation(String who, String text) {
+ }
+}
diff --git a/NET/worlds/scape/WorldScriptLoader.java b/NET/worlds/scape/WorldScriptLoader.java
new file mode 100644
index 0000000..f209e1d
--- /dev/null
+++ b/NET/worlds/scape/WorldScriptLoader.java
@@ -0,0 +1,109 @@
+package NET.worlds.scape;
+
+import NET.worlds.network.Cache;
+import NET.worlds.network.CacheFile;
+import NET.worlds.network.NetUpdate;
+import NET.worlds.network.URL;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.util.Hashtable;
+
+class WorldScriptLoader extends ClassLoader {
+ Hashtable cache = new Hashtable();
+ String lastWorldName;
+
+ private byte[] loadClassData(String name) {
+ String prefix = "NET.worlds.scape.";
+ if (name.startsWith(prefix)) {
+ name = name.substring(prefix.length());
+ }
+
+ int nameIdx = name.indexOf("WorldScript");
+ if (nameIdx == -1) {
+ nameIdx = 0;
+ } else {
+ nameIdx += new String("WorldScript").length();
+ }
+
+ int extIdx = name.indexOf(".class");
+ String worldName;
+ if (nameIdx == 0 && this.lastWorldName != null) {
+ worldName = this.lastWorldName;
+ if (!name.endsWith(".class")) {
+ name = name + ".class";
+ }
+ } else if (extIdx != -1) {
+ worldName = name.substring(nameIdx, extIdx);
+ } else {
+ worldName = name.substring(nameIdx);
+ name = name + ".class";
+ }
+
+ URL scriptURL = URL.make(NetUpdate.getUpgradeServerURL() + worldName + "/" + name);
+ CacheFile f = Cache.getFile(scriptURL, true);
+ f.waitUntilLoaded();
+ if (f.error()) {
+ return null;
+ } else {
+ this.lastWorldName = worldName;
+ String fileName = f.getLocalName();
+
+ try {
+ File file = new File(fileName);
+ FileInputStream fis = new FileInputStream(file);
+ byte[] buffer = new byte[1024];
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+
+ while (true) {
+ try {
+ int bytesRead = fis.read(buffer);
+ if (bytesRead == -1) {
+ break;
+ }
+
+ os.write(buffer, 0, bytesRead);
+ } catch (Exception var14) {
+ break;
+ }
+ }
+
+ return os.toByteArray();
+ } catch (Exception var15) {
+ return null;
+ }
+ }
+ }
+
+ @Override
+ public synchronized Class loadClass(String name, boolean resolve) {
+ Class c = (Class)this.cache.get(name);
+ if (c == null) {
+ byte[] data = (byte[])null;
+ if (!name.startsWith("java.")) {
+ data = this.loadClassData(name);
+ }
+
+ if (data == null) {
+ try {
+ return this.findSystemClass(name);
+ } catch (Error var6) {
+ System.out.println("Could not load script " + name + " " + var6);
+ return null;
+ } catch (Exception var7) {
+ System.out.println("Could not load script " + name + " " + var7);
+ return null;
+ }
+ }
+
+ c = this.defineClass(data, 0, data.length);
+ this.cache.put(name, c);
+ }
+
+ if (resolve) {
+ this.resolveClass(c);
+ }
+
+ return c;
+ }
+}
diff --git a/NET/worlds/scape/WorldScriptManager.java b/NET/worlds/scape/WorldScriptManager.java
new file mode 100644
index 0000000..b38e832
--- /dev/null
+++ b/NET/worlds/scape/WorldScriptManager.java
@@ -0,0 +1,164 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.DefaultConsole;
+import NET.worlds.console.Main;
+import NET.worlds.console.MainCallback;
+import NET.worlds.console.MainTerminalCallback;
+import NET.worlds.console.RenderCanvas;
+import java.awt.PopupMenu;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.Enumeration;
+import java.util.Vector;
+
+public class WorldScriptManager implements ActionListener, MainCallback, MainTerminalCallback {
+ private static WorldScriptManager instance = new WorldScriptManager();
+ private static WorldScriptLoader loader = new WorldScriptLoader();
+ private WorldScript currentScript = null;
+ private String lastRoom;
+
+ public static WorldScriptManager getInstance() {
+ return instance;
+ }
+
+ private WorldScriptManager() {
+ Main.register(this);
+ }
+
+ @Override
+ public void terminalCallback() {
+ if (this.currentScript != null) {
+ this.currentScript.worldExit();
+ }
+
+ this.currentScript = null;
+ Main.unregister(this);
+ }
+
+ public void worldEntered(String worldName) {
+ if (this.currentScript != null) {
+ this.currentScript.worldExit();
+ }
+
+ this.currentScript = null;
+ if (worldName != null) {
+ worldName = worldName.replace(' ', '_');
+ worldName = worldName.replace('-', '_');
+ worldName = worldName.replace('.', '_');
+ worldName = worldName.replace('/', '_');
+ worldName = worldName.replace('\\', '_');
+
+ try {
+ this.currentScript = (WorldScript)loader.loadClass("WorldScript" + worldName + ".class", true).newInstance();
+ } catch (Exception var3) {
+ System.out.println("Exception constructing world script: " + var3);
+ } catch (Error var4) {
+ System.out.println("Error constructing world script: " + var4);
+ }
+
+ if (this.currentScript != null) {
+ if (this.currentScript.getMinScriptVersion() > 15) {
+ System.out
+ .println("Script requires newer client version. script is ver. " + this.currentScript.getMinScriptVersion() + " and client has ver. " + 15);
+ this.currentScript = null;
+ } else {
+ this.currentScript.worldEnter();
+ }
+ }
+ }
+ }
+
+ @Override
+ public void mainCallback() {
+ if (this.currentScript != null) {
+ this.currentScript.onEachFrame();
+ }
+ }
+
+ public void onPrerender(WObject obj, Camera cam) {
+ if (this.currentScript != null) {
+ Console c = Console.getActive();
+ if (c == null) {
+ return;
+ }
+
+ if (!(c instanceof DefaultConsole)) {
+ return;
+ }
+
+ DefaultConsole dc = (DefaultConsole)c;
+ RenderCanvas rc = dc.getRender();
+ if (rc == null) {
+ return;
+ }
+
+ Camera renderCam = rc.getCamera();
+ if (cam != renderCam) {
+ return;
+ }
+
+ Point3Temp p = obj.inCamSpace(cam);
+ boolean v = p != null && p.z > 1.0F && p.x < p.z && -p.x < p.z;
+ this.currentScript.objectVisibilityNotification(obj, v);
+ }
+ }
+
+ public void action(String message) {
+ if (this.currentScript != null) {
+ this.currentScript.onTriggerAction(message);
+ }
+ }
+
+ public PopupMenu shapeClicked(Shape shape) {
+ if (this.currentScript != null) {
+ SuperRoot ultimateOwner = shape;
+
+ while (ultimateOwner.getOwner() != null) {
+ ultimateOwner = ultimateOwner.getOwner();
+ if (ultimateOwner instanceof PosableShape) {
+ shape = (Shape)ultimateOwner;
+ break;
+ }
+ }
+
+ Vector v = this.currentScript.onShapeClick(shape, shape.getName());
+ if (v != null) {
+ PopupMenu m = new PopupMenu();
+ Enumeration e = v.elements();
+
+ while (e.hasMoreElements()) {
+ m.add((String)e.nextElement());
+ }
+
+ return m;
+ }
+ }
+
+ return null;
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ if (this.currentScript != null) {
+ this.currentScript.onMenuClick(e.getActionCommand(), e.getSource());
+ }
+ }
+
+ public void roomEntered(String roomName) {
+ if (this.currentScript != null) {
+ if (this.lastRoom != null) {
+ this.currentScript.roomExit(this.lastRoom);
+ }
+
+ this.currentScript.roomEnter(roomName);
+ this.lastRoom = new String(roomName);
+ }
+ }
+
+ public void onConversation(String who, String what) {
+ if (this.currentScript != null) {
+ this.currentScript.onConversation(who, what);
+ }
+ }
+}
diff --git a/NET/worlds/scape/WorldScriptToolkit.java b/NET/worlds/scape/WorldScriptToolkit.java
new file mode 100644
index 0000000..4f52d21
--- /dev/null
+++ b/NET/worlds/scape/WorldScriptToolkit.java
@@ -0,0 +1,100 @@
+package NET.worlds.scape;
+
+public abstract class WorldScriptToolkit {
+ public static final int videoWallNotFound = -1;
+ public static final int videoUnitialized = 0;
+ public static final int videoStopped = 1;
+ public static final int videoPaused = 2;
+ public static final int videoPlaying = 3;
+ private static WorldScriptToolkit instance = new WorldScriptToolkitImp();
+
+ public abstract int getTime();
+
+ public abstract void teleport(String var1, boolean var2);
+
+ public abstract float getPilotX();
+
+ public abstract float getPilotY();
+
+ public abstract float getPilotYaw();
+
+ public abstract void walkTo(float var1, float var2, float var3, float var4);
+
+ public abstract void walkTo(float var1, float var2, float var3);
+
+ public abstract void walkTo(WorldScript var1, float var2, float var3, float var4, float var5);
+
+ public abstract float getWalkFriction();
+
+ public abstract void setWalkFriction(float var1);
+
+ public abstract void showWebPage(String var1);
+
+ public abstract void showWebPage(String var1, int var2, int var3);
+
+ public abstract void showAdBanner(String var1, int var2, int var3);
+
+ public abstract void showExternalWebPage(String var1);
+
+ public abstract Object playSound(String var1, int var2);
+
+ public abstract void stopSound(Object var1);
+
+ public abstract boolean serviceSound(Object var1);
+
+ public abstract String expandURLMacros(String var1);
+
+ public abstract int getIniInt(String var1, int var2);
+
+ public abstract String getIniString(String var1, String var2);
+
+ public abstract void setIniInt(String var1, int var2);
+
+ public abstract void setIniString(String var1, String var2);
+
+ public abstract int getClientVersion();
+
+ public abstract void messageBox(String var1, String var2);
+
+ public abstract Object yesNoDialog(String var1, String var2, String var3, String var4, WorldScript var5);
+
+ public abstract void printToChat(String var1);
+
+ public abstract Object findObjectInRoom(String var1);
+
+ public abstract void walkObjectTo(WorldScript var1, Object var2, float var3, float var4, float var5, float var6);
+
+ public abstract void moveObjectTo(Object var1, float var2, float var3, float var4);
+
+ public abstract void moveObjectTo(Object var1, float var2, float var3, float var4, float var5);
+
+ public abstract boolean animateBot(Object var1, String var2);
+
+ public abstract boolean watchVisibility(Object var1);
+
+ public abstract boolean setShapeURL(Object var1, String var2);
+
+ public abstract int getVideoWallStatus(Object var1);
+
+ public abstract boolean playVideo(Object var1, int var2);
+
+ public abstract boolean stopVideo(Object var1);
+
+ public abstract boolean setVideoURL(Object var1, String var2, int var3, int var4);
+
+ public abstract boolean setWebWallURL(Object var1, String var2);
+
+ public abstract boolean setWebWallURL(Object var1, String var2, String var3);
+
+ public abstract void setAdCube(boolean var1, boolean var2, String var3, String var4);
+
+ public abstract boolean isLoggedIn();
+
+ public abstract int getConcurrentDownloads();
+
+ public abstract boolean getIsVIP();
+
+ public static WorldScriptToolkit getInstance() {
+ return instance;
+ }
+}
diff --git a/NET/worlds/scape/WorldScriptToolkitImp.java b/NET/worlds/scape/WorldScriptToolkitImp.java
new file mode 100644
index 0000000..180f0ea
--- /dev/null
+++ b/NET/worlds/scape/WorldScriptToolkitImp.java
@@ -0,0 +1,429 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.console.DefaultConsole;
+import NET.worlds.console.NoWebControlException;
+import NET.worlds.console.OkCancelDialog;
+import NET.worlds.console.WebControl;
+import NET.worlds.console.WebControlImp;
+import NET.worlds.core.IniFile;
+import NET.worlds.core.Std;
+import NET.worlds.network.CacheEntry;
+import NET.worlds.network.Galaxy;
+import NET.worlds.network.URL;
+
+class WorldScriptToolkitImp extends WorldScriptToolkit {
+ @Override
+ public int getTime() {
+ return Std.getSynchronizedTime();
+ }
+
+ @Override
+ public void teleport(String destination, boolean showDlg) {
+ TeleportAction.teleport(destination, null, false, showDlg);
+ }
+
+ @Override
+ public float getPilotX() {
+ Pilot p = Pilot.getActive();
+ return p != null ? p.getX() : 0.0F;
+ }
+
+ @Override
+ public float getPilotY() {
+ Pilot p = Pilot.getActive();
+ return p != null ? p.getY() : 0.0F;
+ }
+
+ @Override
+ public float getPilotYaw() {
+ Pilot p = Pilot.getActive();
+ return p != null ? 360.0F - p.getYaw() : 0.0F;
+ }
+
+ private SmoothDriver getSmoothDriver() {
+ Pilot p = Pilot.getActive();
+ if (p != null && p instanceof HoloPilot) {
+ HoloPilot hp = (HoloPilot)p;
+ return hp.getSmoothDriver();
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public float getWalkFriction() {
+ SmoothDriver sd = this.getSmoothDriver();
+ return sd != null ? sd.getVelocityDamping() : 0.0F;
+ }
+
+ @Override
+ public void setWalkFriction(float friction) {
+ SmoothDriver sd = this.getSmoothDriver();
+ if (sd != null) {
+ sd.setVelocityDamping(friction);
+ }
+ }
+
+ @Override
+ public void walkTo(float x, float y, float yaw, float velocity) {
+ Pilot p = Pilot.getActive();
+ if (p != null && p instanceof HoloPilot) {
+ HoloPilot hp = (HoloPilot)p;
+ hp.walkTo(new Point2(x, y), yaw, velocity);
+ }
+ }
+
+ @Override
+ public void walkTo(float x, float y, float yaw) {
+ Pilot p = Pilot.getActive();
+ if (p != null && p instanceof HoloPilot) {
+ HoloPilot hp = (HoloPilot)p;
+ hp.walkTo(new Point2(x, y), yaw);
+ }
+ }
+
+ @Override
+ public void walkTo(WorldScript script, float x, float y, float yaw, float velocity) {
+ Pilot p = Pilot.getActive();
+ if (p != null && p instanceof HoloPilot) {
+ HoloPilot hp = (HoloPilot)p;
+ hp.walkTo(new Point2(x, y), yaw, velocity);
+ hp.addCallback(script);
+ }
+ }
+
+ @Override
+ public void showWebPage(String url) {
+ this.showWebPage(url, 100, 100);
+ }
+
+ @Override
+ public void showWebPage(String url, int percentW, int percentH) {
+ Console c = Console.getActive();
+ if (c != null && c instanceof DefaultConsole) {
+ DefaultConsole dc = (DefaultConsole)c;
+
+ try {
+ WebControl wc = new WebControl(dc.getRender(), percentW, percentH, true, false, false);
+ wc.activate();
+ wc.setURL(url);
+ } catch (NoWebControlException var7) {
+ new SendURLAction(url).doIt();
+ }
+ }
+ }
+
+ @Override
+ public void showExternalWebPage(String url) {
+ new SendURLAction(url).doIt();
+ }
+
+ @Override
+ public void showAdBanner(String url, int width, int height) {
+ Pilot p = Pilot.getActive();
+ if (p != null) {
+ World w = p.getWorld();
+ if (w != null) {
+ w.setHasAdBanner(true);
+ w.setBannerURL(url);
+ w.setBannerWidth(width);
+ w.setBannerHeight(height);
+ w.setupAdBanner();
+ }
+ }
+ }
+
+ @Override
+ public Object playSound(String soundFile, int loop) {
+ Sound owner = new Sound(URL.make(soundFile));
+ SoundPlayer autoSound = null;
+ if (soundFile.toLowerCase().endsWith(".wav")) {
+ autoSound = new WavSoundPlayer(owner);
+ } else {
+ autoSound = new WMPSoundPlayer(owner);
+ }
+
+ autoSound.start(loop);
+ return autoSound;
+ }
+
+ @Override
+ public boolean serviceSound(Object soundPlayer) {
+ if (!(soundPlayer instanceof SoundPlayer)) {
+ System.out.println("Error - invalid handle passed to serviceSound");
+ return false;
+ } else {
+ SoundPlayer sp = (SoundPlayer)soundPlayer;
+ return sp.getState() == 0;
+ }
+ }
+
+ @Override
+ public void stopSound(Object soundPlayer) {
+ if (!(soundPlayer instanceof SoundPlayer)) {
+ System.out.println("Error - invalid handle passed to stopSound");
+ } else {
+ SoundPlayer autoSound = (SoundPlayer)soundPlayer;
+ autoSound.stop();
+ }
+ }
+
+ @Override
+ public String expandURLMacros(String urlIn) {
+ return WebControlImp.processURL(urlIn);
+ }
+
+ @Override
+ public int getIniInt(String entry, int defaultVal) {
+ return IniFile.gamma().getIniInt(entry, defaultVal);
+ }
+
+ @Override
+ public String getIniString(String entry, String defaultVal) {
+ return IniFile.gamma().getIniString(entry, defaultVal);
+ }
+
+ @Override
+ public void setIniInt(String entry, int val) {
+ IniFile.gamma().setIniInt(entry, val);
+ }
+
+ @Override
+ public void setIniString(String entry, String val) {
+ IniFile.gamma().setIniString(entry, val);
+ }
+
+ @Override
+ public int getClientVersion() {
+ return Std.getVersion();
+ }
+
+ @Override
+ public void messageBox(String text, String caption) {
+ Console c = Console.getActive();
+ if (c != null) {
+ new OkCancelDialog(Console.getFrame(), null, caption, null, Console.message("OK"), text, true);
+ }
+ }
+
+ @Override
+ public Object yesNoDialog(String text, String caption, String yes, String no, WorldScript callback) {
+ Console c = Console.getActive();
+ return c == null ? null : new OkCancelDialog(Console.getFrame(), callback, caption, no, yes, text);
+ }
+
+ @Override
+ public void printToChat(String text) {
+ Console c = Console.getActive();
+ if (c != null) {
+ Console.println(text);
+ }
+ }
+
+ @Override
+ public boolean watchVisibility(Object obj) {
+ if (obj == null) {
+ return false;
+ } else if (!(obj instanceof WObject)) {
+ return false;
+ } else {
+ WObject wobj = (WObject)obj;
+ Room r = wobj.getRoom();
+ if (r == null) {
+ return false;
+ } else {
+ r.addPrerenderHandler(wobj);
+ return true;
+ }
+ }
+ }
+
+ @Override
+ public int getVideoWallStatus(Object video) {
+ if (video != null && video instanceof VideoWall) {
+ VideoWall vw = (VideoWall)video;
+ return vw.getState();
+ } else {
+ return -1;
+ }
+ }
+
+ @Override
+ public boolean playVideo(Object video, int repeat) {
+ if (video != null && video instanceof VideoWall) {
+ VideoWall vw = (VideoWall)video;
+ VideoSurface vs = vw.getVideoSurface();
+ if (vs == null) {
+ return false;
+ } else {
+ vs.play(repeat);
+ return true;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public boolean stopVideo(Object video) {
+ if (video != null && video instanceof VideoWall) {
+ VideoWall vw = (VideoWall)video;
+ VideoSurface vs = vw.getVideoSurface();
+ if (vs == null) {
+ return false;
+ } else {
+ vs.stop();
+ return true;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public boolean setVideoURL(Object video, String url, int width, int height) {
+ if (video != null && video instanceof VideoWall) {
+ VideoWall vw = (VideoWall)video;
+ vw.changeURL(url, width, height);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public boolean setWebWallURL(Object webWall, String url) {
+ if (webWall != null && webWall instanceof WebPageWall) {
+ WebPageWall wpw = (WebPageWall)webWall;
+ WebControlImp wci = wpw.getWebControlImp();
+ return wci != null && url != null ? wci.setURL(url) : false;
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public boolean setWebWallURL(Object webWall, String url, String postData) {
+ if (webWall != null && webWall instanceof WebPageWall) {
+ WebPageWall wpw = (WebPageWall)webWall;
+ WebControlImp wci = wpw.getWebControlImp();
+ return wci != null && url != null ? wci.setURL(url, postData) : false;
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public boolean animateBot(Object obj, String action) {
+ if (!(obj instanceof PosableShape)) {
+ return false;
+ } else {
+ PosableShape ps = (PosableShape)obj;
+ ps.animate(action);
+ return true;
+ }
+ }
+
+ @Override
+ public boolean setShapeURL(Object obj, String url) {
+ if (!(obj instanceof Shape)) {
+ return false;
+ } else {
+ Shape s = (Shape)obj;
+ s.setURL(URL.make(url));
+ return true;
+ }
+ }
+
+ @Override
+ public Object findObjectInRoom(String objectName) {
+ Room r = Pilot.getActive().getRoom();
+ if (r != null) {
+ DeepEnumeration e = new DeepEnumeration();
+ r.getChildren(e);
+
+ while (e.hasMoreElements()) {
+ SuperRoot wobj = (SuperRoot)e.nextElement();
+ if (wobj.getName().equals(objectName)) {
+ return wobj;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ @Override
+ public void walkObjectTo(WorldScript script, Object obj, float x, float y, float yaw, float vel) {
+ if (obj instanceof WObject) {
+ HandsOffDriver hod = new HandsOffDriver();
+ hod.setDestPos(new Point2(x, y), yaw, vel);
+ hod.setTarget((Transform)obj);
+ hod.addCallback(script);
+ ((WObject)obj).addHandler(hod);
+ }
+ }
+
+ @Override
+ public void moveObjectTo(Object obj, float x, float y, float yaw) {
+ if (obj instanceof Transform) {
+ Transform t = (Transform)obj;
+ t.moveTo(x, y, t.getZ()).yaw(yaw);
+ }
+ }
+
+ @Override
+ public void moveObjectTo(Object obj, float x, float y, float z, float yaw) {
+ if (obj instanceof Transform) {
+ Transform t = (Transform)obj;
+ t.moveTo(x, y, z).yaw(yaw);
+ }
+ }
+
+ public void moveObjectTo(Object obj, float x, float y, float z, float yaw, float sc) {
+ if (obj instanceof Transform) {
+ Transform t = (Transform)obj;
+ t.moveTo(x, y, z).yaw(yaw);
+ t.scale(sc);
+ }
+ }
+
+ @Override
+ public boolean isLoggedIn() {
+ Console c = Console.getActive();
+ if (c != null) {
+ Galaxy g = c.getGalaxy();
+ if (g != null) {
+ return g.getOnline();
+ }
+ }
+
+ return false;
+ }
+
+ @Override
+ public int getConcurrentDownloads() {
+ return CacheEntry.getConcurrentDownloads();
+ }
+
+ @Override
+ public boolean getIsVIP() {
+ Console c = Console.getActive();
+ return c != null ? c.getVIP() : false;
+ }
+
+ @Override
+ public void setAdCube(boolean clickable, boolean usesGIF, String baseURL, String defaultURL) {
+ Pilot p = Pilot.getActive();
+ if (p != null) {
+ World w = p.getWorld();
+ if (w != null) {
+ w.setHasClickableAdCube(clickable);
+ w.setAdCubeFormatIsGif(usesGIF);
+ w.setAdCubeBaseURL(baseURL);
+ w.setDefaultAdCubeURL(defaultURL);
+ }
+ }
+ }
+}
diff --git a/NET/worlds/scape/WorldValidator.java b/NET/worlds/scape/WorldValidator.java
new file mode 100644
index 0000000..dbfd629
--- /dev/null
+++ b/NET/worlds/scape/WorldValidator.java
@@ -0,0 +1,84 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.core.IniFile;
+import NET.worlds.network.Cache;
+import NET.worlds.network.CacheFile;
+import NET.worlds.network.NetUpdate;
+import NET.worlds.network.URL;
+import java.io.RandomAccessFile;
+import java.util.Vector;
+
+public class WorldValidator {
+ static Vector worldList = null;
+ private static final boolean debug = true;
+
+ public static boolean allow(String worldName) {
+ if (IniFile.gamma().getIniInt("FreeFreeFree", 1) == 1) {
+ return true;
+ } else if (NetUpdate.isInternalVersion()) {
+ return true;
+ } else {
+ Console c = Console.getActive();
+ if (c != null && !c.getGalaxy().getOnline()) {
+ return true;
+ } else {
+ if (worldList == null) {
+ try {
+ initializeList();
+ } catch (Exception var3) {
+ return true;
+ }
+ }
+
+ if (worldList == null) {
+ return true;
+ } else {
+ worldName = normalize(worldName);
+ System.out.println("Validating " + worldName);
+ boolean allow = worldList.contains(worldName);
+ System.out.println(allow);
+ return allow;
+ }
+ }
+ }
+ }
+
+ public static void initializeList() throws Exception {
+ String worldListFile = NetUpdate.getUpgradeServerURL() + "tables/worlds.txt";
+ URL worldListURL = URL.make(worldListFile);
+ CacheFile cf = Cache.getFile(worldListURL, true);
+ cf.waitUntilLoaded();
+ if (!cf.error()) {
+ boolean foundAtLeastOneEntry = false;
+ worldList = new Vector();
+ RandomAccessFile f = new RandomAccessFile(cf.getLocalName(), "r");
+
+ while (f.getFilePointer() < f.length()) {
+ String line = f.readLine();
+ if (line.indexOf(".world") != -1) {
+ line = normalize(line);
+ foundAtLeastOneEntry = true;
+ System.out.println("Adding world " + line);
+ worldList.addElement(line);
+ }
+ }
+
+ f.close();
+ if (!foundAtLeastOneEntry) {
+ throw new Exception();
+ }
+ } else {
+ throw new Exception();
+ }
+ }
+
+ private static String normalize(String worldName) {
+ String out = URL.make(worldName).getAbsolute();
+ if (out.startsWith("home:/")) {
+ out = "home:" + out.substring(6);
+ }
+
+ return out.toLowerCase().trim();
+ }
+}
diff --git a/NET/worlds/scape/WrRamp.java b/NET/worlds/scape/WrRamp.java
new file mode 100644
index 0000000..6e72628
--- /dev/null
+++ b/NET/worlds/scape/WrRamp.java
@@ -0,0 +1,207 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+public class WrRamp extends Room {
+ private static final float epsilon = 0.01F;
+ public Portal portal1;
+ public Portal portal2;
+ private float dzByLength;
+
+ public WrRamp(
+ World world,
+ String name,
+ float length,
+ float width,
+ float pWidth,
+ float pHeight,
+ float dz,
+ float lintelZ,
+ float floorTileX,
+ float floorTileY,
+ float ceilTileX,
+ float ceilTileY,
+ float leftTileX,
+ float leftTileY,
+ float rightTileX,
+ float rightTileY,
+ Material floor,
+ Material left,
+ Material right,
+ Material doorpost,
+ Material lintel,
+ Material ceiling
+ ) {
+ super(world, name);
+ if (pWidth > width) {
+ System.out.println("WrRamp: portal too wide; reducing.");
+ pWidth = width;
+ }
+
+ if (length < 0.0F) {
+ System.out.println("WrRamp: length must be positive; inverting.");
+ length = -length;
+ }
+
+ if (width < 0.0F) {
+ System.out.println("WrRamp: width must be positive; inverting.");
+ width = -width;
+ }
+
+ if (pWidth < 0.0F) {
+ System.out.println("WrRamp: portal width must be positive; inverting.");
+ pWidth = -pWidth;
+ }
+
+ if (pHeight < 0.0F) {
+ System.out.println("WrRamp: portal height must be positive; inverting.");
+ pHeight = -pHeight;
+ }
+
+ if (lintelZ < 0.0F) {
+ System.out.println("WrRamp: lintel height must be positive; ignoring.");
+ lintelZ = 0.0F;
+ }
+
+ if (floorTileX < 10.0F) {
+ System.out.println("WrRamp: floor tile width must be at least 10; fixing.");
+ floorTileX = 10.0F;
+ }
+
+ if (floorTileY < 10.0F) {
+ System.out.println("WrRamp: floor tile length must be at least 10; fixing.");
+ floorTileY = 10.0F;
+ }
+
+ if (ceilTileX < 10.0F) {
+ System.out.println("WrRamp: ceiling tile width must be at least 10; fixing.");
+ ceilTileX = 10.0F;
+ }
+
+ if (ceilTileY < 10.0F) {
+ System.out.println("WrRamp: ceiling tile length must be at least 10; fixing.");
+ ceilTileY = 10.0F;
+ }
+
+ if (leftTileX < 10.0F) {
+ System.out.println("WrRamp: lWall tile width must be at least 10; fixing.");
+ leftTileX = 10.0F;
+ }
+
+ if (leftTileY < 10.0F) {
+ System.out.println("WrRamp: lWall tile length must be at least 10; fixing.");
+ leftTileY = 10.0F;
+ }
+
+ if (rightTileX < 10.0F) {
+ System.out.println("WrRamp: rWall tile width must be at least 10; fixing.");
+ rightTileX = 10.0F;
+ }
+
+ if (rightTileY < 10.0F) {
+ System.out.println("WrRamp: rWall tile length must be at least 10; fixing.");
+ rightTileY = 10.0F;
+ }
+
+ RoomEnvironment env = this.getEnvironment();
+ float postX = (width - pWidth) / 2.0F;
+ this.dzByLength = dz / length;
+ float nearTop = pHeight + lintelZ;
+ float farTop = dz + nearTop;
+ this.portal1 = new Portal(width - postX, 0.0F, 0.0F, postX, 0.0F, pHeight);
+ this.portal2 = new Portal(postX, length, dz, width - postX, length, dz + pHeight);
+ env.add(this.portal1);
+ env.add(this.portal2);
+ float[] floorVerts = new float[]{
+ 0.0F,
+ 0.0F,
+ 0.0F,
+ 0.0F,
+ 0.0F,
+ width,
+ 0.0F,
+ 0.0F,
+ width / floorTileX,
+ 0.0F,
+ width,
+ length,
+ dz,
+ width / floorTileX,
+ length / floorTileY,
+ 0.0F,
+ length,
+ dz,
+ 0.0F,
+ length / floorTileY
+ };
+ env.add(new Polygon(floorVerts, floor));
+ if (lintelZ > 0.0F) {
+ env.add(new Rect(width, 0.0F, pHeight, 0.0F, 0.0F, nearTop, lintel));
+ env.add(new Rect(0.0F, length, dz + pHeight, width, length, farTop, lintel));
+ }
+
+ if (width > pWidth) {
+ env.add(new Rect(width, 0.0F, 0.0F, width - postX, 0.0F, pHeight, doorpost));
+ env.add(new Rect(postX, 0.0F, 0.0F, 0.0F, 0.0F, pHeight, doorpost));
+ env.add(new Rect(0.0F, length, dz, postX, length, dz + pHeight, doorpost));
+ env.add(new Rect(width - postX, length, dz, width, length, dz + pHeight, doorpost));
+ }
+
+ float[] ceilVerts = new float[]{
+ 0.0F,
+ 0.0F,
+ nearTop,
+ 0.0F,
+ 0.0F,
+ 0.0F,
+ length,
+ farTop,
+ 0.0F,
+ length / ceilTileY,
+ width,
+ length,
+ farTop,
+ width / ceilTileX,
+ length / ceilTileY,
+ width,
+ 0.0F,
+ nearTop,
+ width / ceilTileX,
+ 0.0F
+ };
+ env.add(new Polygon(ceilVerts, ceiling));
+ float bottom = Math.min(dz, 0.0F);
+ float top = Math.max(nearTop, farTop);
+ env.add(new Rect(-0.01F, 0.0F, bottom, -0.01F, length, top, left));
+ env.add(new Rect(width + 0.01F, length, bottom, width + 0.01F, 0.0F, top, right));
+ }
+
+ public WrRamp() {
+ }
+
+ @Override
+ public float floorHeight(float x, float y, float z) {
+ return y * this.dzByLength;
+ }
+
+ @Override
+ public Point3 surfaceNormal(float x, float y, float z) {
+ Point3 A = new Point3(1.0F, 0.0F, 0.0F);
+ Point3Temp B = Point3Temp.make(0.0F, 1.0F, this.dzByLength);
+ A.cross(B);
+ A.normalize();
+ return A;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ super.saveState(s);
+ s.saveFloat(this.dzByLength);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ super.restoreState(r);
+ this.dzByLength = r.restoreFloat();
+ }
+}
diff --git a/NET/worlds/scape/WrRectPatch.java b/NET/worlds/scape/WrRectPatch.java
new file mode 100644
index 0000000..7efd67c
--- /dev/null
+++ b/NET/worlds/scape/WrRectPatch.java
@@ -0,0 +1,19 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+class WrRectPatch extends RectPatch {
+ private static Object classCookie = new Object();
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ assert false;
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ RectPatch p = new RectPatch();
+ r.replace(this, p);
+ p.restoreStateRectPatchHelper(r, classCookie);
+ }
+}
diff --git a/NET/worlds/scape/WrStaircase.java b/NET/worlds/scape/WrStaircase.java
new file mode 100644
index 0000000..78ee4bc
--- /dev/null
+++ b/NET/worlds/scape/WrStaircase.java
@@ -0,0 +1,137 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+public class WrStaircase extends Room {
+ private static final float epsilon = 0.01F;
+ public Portal portal1;
+ public Portal portal2;
+ private float dzByLength;
+
+ public WrStaircase(
+ World world,
+ String name,
+ float length,
+ float width,
+ float pWidth,
+ float pHeight,
+ float dz,
+ float lintelZ,
+ int numSteps,
+ Material riser,
+ Material tread,
+ Material left,
+ Material right,
+ Material doorpost,
+ Material lintel,
+ Material ceiling
+ ) {
+ super(world, name);
+ if (pWidth > width) {
+ System.out.println("WrStaircase: portal too wide; reducing.");
+ pWidth = width;
+ }
+
+ if (length < 0.0F) {
+ System.out.println("WrStaircase: length must be positive; inverting.");
+ length = -length;
+ }
+
+ if (width < 0.0F) {
+ System.out.println("WrStaircase: width must be positive; inverting.");
+ width = -width;
+ }
+
+ if (pWidth < 0.0F) {
+ System.out.println("WrStaircase: portal width must be positive; inverting.");
+ pWidth = -pWidth;
+ }
+
+ if (pHeight < 0.0F) {
+ System.out.println("WrStaircase: portal height must be positive; inverting.");
+ pHeight = -pHeight;
+ }
+
+ if (lintelZ < 0.0F) {
+ System.out.println("WrStaircase: lintel height must be positive; ignoring.");
+ lintelZ = 0.0F;
+ }
+
+ if (numSteps < 2) {
+ System.out.println("WrStaircase: must have at least 2 steps.");
+ numSteps = 2;
+ }
+
+ RoomEnvironment env = this.getEnvironment();
+ float postX = (width - pWidth) / 2.0F;
+ float bottom = Math.min(dz, 0.0F);
+ float ceilingHeight = Math.max(dz, 0.0F) + pHeight + lintelZ;
+ this.dzByLength = dz / length;
+ this.portal1 = new Portal(width - postX, 0.0F, 0.0F, postX, 0.0F, pHeight);
+ this.portal2 = new Portal(postX, length, dz, width - postX, length, dz + pHeight);
+ env.add(this.portal1);
+ env.add(this.portal2);
+ float stepWidth = length / numSteps;
+ float stepHeight = dz / numSteps;
+
+ for (int i = 1; i <= numSteps; i++) {
+ Rect w = new Rect(0.0F, i * stepWidth, (i - 1) * stepHeight, width, i * stepWidth, i * stepHeight - 0.01F, riser);
+ w.setTileSize(stepHeight, stepHeight);
+ env.add(w);
+ }
+
+ for (int i = 0; i < numSteps; i++) {
+ Rect w = Rect.floor(0.0F, i * stepWidth, i * stepHeight, width, (i + 1) * stepWidth - 0.01F, tread);
+ w.setTileSize(Math.abs(stepWidth), Math.abs(stepWidth));
+ env.add(w);
+ }
+
+ if (ceilingHeight > pHeight) {
+ env.add(new Rect(width, 0.0F, pHeight, 0.0F, 0.0F, ceilingHeight - 0.01F, lintel));
+ }
+
+ if (ceilingHeight > dz + pHeight) {
+ env.add(new Rect(0.0F, length, dz + pHeight, width, length, ceilingHeight - 0.01F, lintel));
+ }
+
+ if (width > pWidth) {
+ env.add(new Rect(width, 0.0F, 0.0F, width - postX, 0.0F, pHeight, doorpost));
+ env.add(new Rect(postX, 0.0F, 0.0F, 0.0F, 0.0F, pHeight, doorpost));
+ env.add(new Rect(0.0F, length, dz, postX, length, dz + pHeight, doorpost));
+ env.add(new Rect(width - postX, length, dz, width, length, dz + pHeight, doorpost));
+ }
+
+ env.add(Rect.ceiling(0.0F, 0.0F, ceilingHeight, width, length, ceiling));
+ env.add(new Rect(-0.01F, 0.0F, bottom, -0.01F, length, ceilingHeight, left));
+ env.add(new Rect(width + 0.01F, length, bottom, width + 0.01F, 0.0F, ceilingHeight, right));
+ }
+
+ public WrStaircase() {
+ }
+
+ @Override
+ public float floorHeight(float x, float y, float z) {
+ return y * this.dzByLength;
+ }
+
+ @Override
+ public Point3 surfaceNormal(float x, float y, float z) {
+ Point3 A = new Point3(1.0F, 0.0F, 0.0F);
+ Point3Temp B = Point3Temp.make(0.0F, 1.0F, this.dzByLength);
+ A.cross(B);
+ A.normalize();
+ return A;
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ super.saveState(s);
+ s.saveFloat(this.dzByLength);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ super.restoreState(r);
+ this.dzByLength = r.restoreFloat();
+ }
+}
diff --git a/NET/worlds/scape/WrVisiRectPatch.java b/NET/worlds/scape/WrVisiRectPatch.java
new file mode 100644
index 0000000..b8e3db1
--- /dev/null
+++ b/NET/worlds/scape/WrVisiRectPatch.java
@@ -0,0 +1,46 @@
+package NET.worlds.scape;
+
+import java.io.IOException;
+
+class WrVisiRectPatch extends RectPatch {
+ private static Object classCookie = new Object();
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ assert false;
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException, TooNewException {
+ RectPatch p = new RectPatch();
+ r.replace(this, p);
+ switch (r.restoreVersion(classCookie)) {
+ case 0:
+ super.restoreState(r);
+ this.xTile = r.restoreFloat();
+ this.xTileOffset = r.restoreFloat();
+ this.yTile = r.restoreFloat();
+ this.yTileOffset = r.restoreFloat();
+ this.mat = (Material)r.restoreMaybeNull();
+ this.t[0] = (Polygon)r.restoreMaybeNull();
+ this.t[1] = (Polygon)r.restoreMaybeNull();
+ this.t[2] = (Polygon)r.restoreMaybeNull();
+ this.t[3] = (Polygon)r.restoreMaybeNull();
+ p.xDim = this.xDim;
+ p.yDim = this.yDim;
+ p.z[0] = this.z[0];
+ p.z[1] = this.z[1];
+ p.z[2] = this.z[2];
+ p.z[3] = this.z[3];
+ p.xTile = this.xTile;
+ p.xTileOffset = this.xTileOffset;
+ p.yTile = this.yTile;
+ p.yTileOffset = this.yTileOffset;
+ p.mat = this.mat;
+ p.setVisible(true);
+ return;
+ default:
+ throw new TooNewException();
+ }
+ }
+}
diff --git a/NET/worlds/scape/YawWidget.java b/NET/worlds/scape/YawWidget.java
new file mode 100644
index 0000000..489c88b
--- /dev/null
+++ b/NET/worlds/scape/YawWidget.java
@@ -0,0 +1,21 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+
+class YawWidget extends WidgetButton {
+ public YawWidget(ToolBar toolbar) {
+ super(toolbar, "yaw.gif", Console.message("Yaw"));
+ }
+
+ @Override
+ public String drag(boolean initialDrag, float deltax, float deltay) {
+ if (Math.abs(deltay) > Math.abs(deltax)) {
+ deltax = 0.0F;
+ }
+
+ Transform t = Transform.make();
+ this.applyWorldTransform(initialDrag, t.spin(this.getWorldAxis(0, 0, 1), deltax));
+ t.recycle();
+ return "Yaw";
+ }
+}
diff --git a/NET/worlds/scape/sendURL.java b/NET/worlds/scape/sendURL.java
new file mode 100644
index 0000000..4f512e5
--- /dev/null
+++ b/NET/worlds/scape/sendURL.java
@@ -0,0 +1,156 @@
+package NET.worlds.scape;
+
+import NET.worlds.console.Console;
+import NET.worlds.network.URL;
+import java.io.IOException;
+import java.text.MessageFormat;
+
+public class sendURL extends TriggeredSwitchableBehavior implements MouseDownHandler, BumpHandler, FrameHandler {
+ protected String browser;
+ protected String destination;
+ protected boolean silentURL;
+ protected boolean initialized = false;
+
+ public sendURL() {
+ this.trigger = new String("none");
+ this.externalTriggerTag = new String("");
+ this.silentURL = false;
+ this.browser = new String("NETSCAPE");
+ this.destination = new String("http://www.worlds.net");
+ }
+
+ public static native int init(String var0);
+
+ public static native int get(String var0);
+
+ public static native int silent_get(String var0);
+
+ @Override
+ public void ExternalTrigger(Trigger source, int seqno, int eventno) {
+ this.sendURLStart();
+ }
+
+ public void sendURLStart() {
+ if (this.silentURL) {
+ silent_get(this.destination);
+ } else {
+ get(this.destination);
+ }
+ }
+
+ @Override
+ public boolean handle(FrameEvent e) {
+ if (!this.initialized) {
+ init(this.browser);
+ this.initialized = true;
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean handle(MouseDownEvent e) {
+ if (this.enabled && this.trigger.equals("click")) {
+ this.sendURLStart();
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean handle(BumpEventTemp e) {
+ if (this.enabled && this.trigger.equals("bump")) {
+ this.sendURLStart();
+ }
+
+ return true;
+ }
+
+ @Override
+ public Object properties(int index, int offset, int mode, Object value) throws NoSuchPropertyException {
+ Object ret = null;
+ switch (index - offset) {
+ case 0:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Trigger"));
+ } else if (mode == 1) {
+ ret = new String(this.trigger);
+ } else if (mode == 2) {
+ this.trigger = ((String)value).toString().trim();
+ if (this.trigger.equals("external")) {
+ Trigger.TriggeredSwitchableBehaviorList[Trigger.TriggeredSwitchableBehaviorListCount] = this;
+ Trigger.TriggeredSwitchableBehaviorListCount++;
+ }
+ }
+ break;
+ case 1:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "External Trigger Tag"));
+ } else if (mode == 1) {
+ ret = new String(this.externalTriggerTag);
+ } else if (mode == 2) {
+ this.externalTriggerTag = ((String)value).toString().trim();
+ }
+ break;
+ case 2:
+ if (mode == 0) {
+ ret = BooleanPropertyEditor.make(new Property(this, index, "Silent URL"), "No", "Yes");
+ } else if (mode == 1) {
+ ret = new Boolean(this.silentURL);
+ } else if (mode == 2) {
+ this.silentURL = (Boolean)value;
+ }
+ break;
+ case 3:
+ if (mode == 0) {
+ ret = StringPropertyEditor.make(new Property(this, index, "Destination"));
+ } else if (mode == 1) {
+ ret = new String(this.destination);
+ } else if (mode == 2) {
+ this.destination = ((String)value).toString().trim();
+ }
+ break;
+ default:
+ ret = super.properties(index, offset + 4, mode, value);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + "[enabled " + this.enabled + ", trigger " + this.trigger + ", externalTriggerTag " + this.externalTriggerTag + "]";
+ }
+
+ @Override
+ public void saveState(Saver s) throws IOException {
+ Object[] arguments = new Object[]{new String(this.getName())};
+ Console.println(MessageFormat.format(Console.message("sendURL-obs"), arguments));
+ s.saveString(this.trigger);
+ s.saveString(this.externalTriggerTag);
+ s.saveBoolean(this.silentURL);
+ s.saveString(this.destination);
+ }
+
+ @Override
+ public void restoreState(Restorer r) throws IOException {
+ this.trigger = r.restoreString();
+ this.externalTriggerTag = r.restoreString();
+ this.silentURL = r.restoreBoolean();
+ this.destination = r.restoreString();
+ if (this.trigger.equals("external")) {
+ Object[] arguments = new Object[]{new String(this.getName())};
+ Console.println(MessageFormat.format(Console.message("sendURL-obs"), arguments));
+ Trigger.TriggeredSwitchableBehaviorList[Trigger.TriggeredSwitchableBehaviorListCount] = this;
+ Trigger.TriggeredSwitchableBehaviorListCount++;
+ } else {
+ SendURLAction sua = new SendURLAction();
+ if (this.destination != null) {
+ sua.setDestination(URL.make(this.destination));
+ }
+
+ sua.setTrigger(this.trigger);
+ r.replace(this, sua);
+ }
+ }
+}