/** * Calls the 'process' method if the replay is activated and the event is of a type selected to be replayed. * This way, events of the types that are recorded and replayed are ignored during a replay. This is what makes * the player have no control over the character during a replay. * @param entity the entity which the event was sent against. * @param event the event being sent. */ @Override public void send(EntityRef entity, Event event) { if (recordAndReplayCurrentStatus.getStatus() != RecordAndReplayStatus.REPLAYING || !isSelectedToReplayEvent(event)) { originalSend(entity, event); } }
@Override public boolean step() { //Activate record when the preparations are ready if (recordAndReplayCurrentStatus.getStatus() == RecordAndReplayStatus.PREPARING_RECORD) { recordAndReplayCurrentStatus.setStatus(RecordAndReplayStatus.RECORDING); } //Activate the replay when the preparations are ready if (recordAndReplayCurrentStatus.getStatus() == RecordAndReplayStatus.PREPARING_REPLAY) { recordAndReplaySerializer.deserializeRecordAndReplayData(); recordAndReplayCurrentStatus.setStatus(RecordAndReplayStatus.REPLAYING); } return true; }
RecordAndReplayCurrentStatus recordAndReplayCurrentStatus = new RecordAndReplayCurrentStatus(); rootContext.put(RecordAndReplayCurrentStatus.class, recordAndReplayCurrentStatus); RecordAndReplayUtils recordAndReplayUtils = new RecordAndReplayUtils();
NetworkSystem networkSystem = mock(NetworkSystem.class); when(networkSystem.getMode()).thenReturn(NetworkMode.NONE); recordAndReplayCurrentStatus = new RecordAndReplayCurrentStatus(); RecordedEventStore eventStore = new RecordedEventStore(); RecordAndReplayUtils recordAndReplayUtils = new RecordAndReplayUtils(); DirectionAndOriginPosRecorderList directionAndOriginPosRecorderList = new DirectionAndOriginPosRecorderList(); RecordAndReplaySerializer recordAndReplaySerializer = new RecordAndReplaySerializer(entityManager, eventStore, recordAndReplayUtils, characterStateEventPositionMap, directionAndOriginPosRecorderList, null); recordAndReplayCurrentStatus.setStatus(RecordAndReplayStatus.REPLAYING); entity = entityManager.create(); Long id = entity.getId();
/** * Empty the RecordedEventStore and sets the RecordAndReplayStatus. */ private void finishReplay() { recordedEventStore.popEvents(); recordAndReplayCurrentStatus.setStatus(RecordAndReplayStatus.REPLAY_FINISHED); // stops the replay if every recorded event was already replayed }
private void setUpLocalPlayer(Context context) { LocalPlayer localPlayer = new LocalPlayer(); localPlayer.setRecordAndReplayClasses(new DirectionAndOriginPosRecorderList(), new RecordAndReplayCurrentStatus()); clientEntity = mock(EntityRef.class); ClientComponent clientComponent = new ClientComponent(); characterEntity = mock(EntityRef.class); clientComponent.character = characterEntity; when(clientEntity.getComponent(ClientComponent.class)).thenReturn(clientComponent); localPlayer.setClientEntity(clientEntity); context.put(LocalPlayer.class, localPlayer); registerEntityKeyCapturing(); }
@After public void cleanStates() { recordAndReplayCurrentStatus.setStatus(RecordAndReplayStatus.NOT_ACTIVATED); }
@Before public void setup() { ContextImpl context = new ContextImpl(); context.put(ModuleManager.class, moduleManager); context.put(NetworkSystem.class, mock(NetworkSystem.class)); context.put(RecordAndReplayCurrentStatus.class, new RecordAndReplayCurrentStatus()); CoreRegistry.setContext(context); EntitySystemSetupUtil.addReflectionBasedLibraries(context); EntitySystemSetupUtil.addEntityManagementRelatedClasses(context); entityManager = context.get(EngineEntityManager.class); }
/** * Calls the 'process' method if the replay is activated and the event is of a type selected to be replayed. * This way, events of the types that are recorded and replayed are ignored during a replay. This is what makes * the player have no control over the character during a replay. * @param entity the entity which the event was sent against. * @param event the event being sent. * @param component the component sent along with the event. */ @Override public void send(EntityRef entity, Event event, Component component) { if (recordAndReplayCurrentStatus.getStatus() != RecordAndReplayStatus.REPLAYING || !isSelectedToReplayEvent(event)) { originalSend(entity, event, component); } }
private boolean isReplay() { boolean isReplay = false; if (recordAndReplayCurrentStatus.getStatus() == RecordAndReplayStatus.REPLAY_FINISHED || recordAndReplayCurrentStatus.getStatus() == RecordAndReplayStatus.REPLAYING) { isReplay = true; if (recordAndReplayUtils.isShutdownRequested()) { recordAndReplayCurrentStatus.setStatus(RecordAndReplayStatus.NOT_ACTIVATED); recordAndReplayUtils.reset(); } } return isReplay; }
@Override public void initialise() { setAnimationSystem(MenuAnimationSystems.createDefaultSwipeAnimation()); RecordScreen recordScreen = getManager().createScreen(RecordScreen.ASSET_URI, RecordScreen.class); ReplayScreen replayScreen = getManager().createScreen(ReplayScreen.ASSET_URI, ReplayScreen.class); WidgetUtil.trySubscribe(this, "record", button -> { recordAndReplayCurrentStatus.setStatus(RecordAndReplayStatus.PREPARING_RECORD); RecordAndReplayUtils recordAndReplayUtils = engine.createChildContext().get(RecordAndReplayUtils.class); recordScreen.setRecordAndReplayUtils(recordAndReplayUtils); triggerForwardAnimation(recordScreen); }); WidgetUtil.trySubscribe(this, "replay", button -> { RecordAndReplayUtils recordAndReplayUtils = engine.createChildContext().get(RecordAndReplayUtils.class); replayScreen.setRecordAndReplayUtils(recordAndReplayUtils); recordAndReplayCurrentStatus.setStatus(RecordAndReplayStatus.PREPARING_REPLAY); triggerForwardAnimation(replayScreen); }); WidgetUtil.trySubscribe(this, "credits", button -> triggerForwardAnimation(CreditsScreen.ASSET_URI)); WidgetUtil.trySubscribe(this, "telemetry", button -> triggerForwardAnimation(TelemetryScreen.ASSET_URI)); WidgetUtil.trySubscribe(this, "crashReporter", widget -> CrashReporter.report(new Throwable("There is no error."), LoggingContext.getLoggingPath(), CrashReporter.MODE.ISSUE_REPORTER)); WidgetUtil.trySubscribe(this, "close", button -> triggerBackAnimation()); }
@Before public void setup() { ContextImpl context = new ContextImpl(); CoreRegistry.setContext(context); ReflectFactory reflectFactory = new ReflectionReflectFactory(); CopyStrategyLibrary copyStrategies = new CopyStrategyLibrary(reflectFactory); TypeSerializationLibrary serializationLibrary = new TypeSerializationLibrary(reflectFactory, copyStrategies); EntitySystemLibrary entitySystemLibrary = new EntitySystemLibrary(context, serializationLibrary); compLibrary = entitySystemLibrary.getComponentLibrary(); entityManager = new PojoEntityManager(); entityManager.setComponentLibrary(entitySystemLibrary.getComponentLibrary()); entityManager.setPrefabManager(new PojoPrefabManager(context)); NetworkSystem networkSystem = mock(NetworkSystem.class); when(networkSystem.getMode()).thenReturn(NetworkMode.NONE); EventCatcher eventCatcher = new EventCatcher(null, null); RecordAndReplayCurrentStatus recordAndReplayCurrentStatus = new RecordAndReplayCurrentStatus(); eventSystem = new EventSystemImpl(entitySystemLibrary.getEventLibrary(), networkSystem, eventCatcher, recordAndReplayCurrentStatus); entityManager.setEventSystem(eventSystem); entity = entityManager.create(); }
@Override public void send(EntityRef entity, Event event, Component component) { if (Thread.currentThread() != mainThread) { pendingEvents.offer(new PendingEvent(entity, event, component)); } else { if (recordAndReplayCurrentStatus.getStatus() == RecordAndReplayStatus.RECORDING) { eventCatcher.addEvent(new PendingEvent(entity, event, component)); } SetMultimap<Class<? extends Component>, EventHandlerInfo> handlers = componentSpecificHandlers.get(event.getClass()); if (handlers != null) { List<EventHandlerInfo> eventHandlers = Lists.newArrayList(handlers.get(component.getClass())); eventHandlers.sort(priorityComparator); for (EventHandlerInfo eventHandler : eventHandlers) { if (eventHandler.isValidFor(entity)) { eventHandler.invoke(entity, event); } } } } }
private void saveRecordingData() { if (recordAndReplayCurrentStatus.getStatus() == RecordAndReplayStatus.RECORDING) { if (recordAndReplayUtils.isShutdownRequested()) { recordAndReplaySerializer.serializeRecordAndReplayData(); recordAndReplayCurrentStatus.setStatus(RecordAndReplayStatus.NOT_ACTIVATED); recordAndReplayUtils.reset(); } else { String recordingPath = PathManager.getInstance().getRecordingPath(recordAndReplayUtils.getGameTitle()).toString(); recordAndReplaySerializer.serializeRecordedEvents(recordingPath); } } }
@Override public void initialise() { setAnimationSystem(MenuAnimationSystems.createDefaultSwipeAnimation()); initWidgets(); if (isValidScreen()) { initSaveGamePathWidget(PathManager.getInstance().getSavesPath()); NameRecordingScreen nameRecordingScreen = getManager().createScreen(NameRecordingScreen.ASSET_URI, NameRecordingScreen.class); getGameInfos().subscribeSelection((widget, item) -> { load.setEnabled(item != null); updateDescription(item); }); getGameInfos().subscribe((widget, item) -> launchNamingScreen(nameRecordingScreen, item)); load.subscribe(button -> { final GameInfo gameInfo = getGameInfos().getSelection(); if (gameInfo != null) { launchNamingScreen(nameRecordingScreen, gameInfo); } }); close.subscribe(button -> { recordAndReplayCurrentStatus.setStatus(RecordAndReplayStatus.NOT_ACTIVATED); triggerBackAnimation(); }); } }
protected void reset(Set<Name> moduleNames) throws Exception { this.context = new ContextImpl(); RecordAndReplayCurrentStatus recordAndReplayCurrentStatus = new RecordAndReplayCurrentStatus(); context.put(RecordAndReplayCurrentStatus.class, recordAndReplayCurrentStatus); CoreRegistry.setContext(context); setupPathManager(); setupConfig(); setupModuleManager(moduleNames); setupDisplay(); setupAudio(); AssetManager assetManager = setupAssetManager(); setupBlockManager(assetManager); setupExtraDataManager(context); setupCollisionManager(); setupNetwork(); setupEntitySystem(); setupStorageManager(); setupComponentManager(); setupWorldProvider(); setupCelestialSystem(); loadPrefabs(); }
/** * Processes recorded events for a certain amount of time and only if the timestamp is right. */ private void processRecordedEvents() { if (recordAndReplayCurrentStatus.getStatus() == RecordAndReplayStatus.REPLAYING && !this.areRecordedEventsLoaded) { initialiseReplayData(); } //If replay is ready, process some recorded events if the time is right. if (recordAndReplayCurrentStatus.getStatus() == RecordAndReplayStatus.REPLAYING) { processRecordedEventsBatch(1); if (this.recordedEvents.isEmpty()) { if (recordAndReplayUtils.getFileCount() <= recordAndReplayUtils.getFileAmount()) { //Get next recorded events file loadNextRecordedEventFile(); } else { finishReplay(); } } } }
@Override public void initialise() { initWidgets(); if (isValidScreen()) { initSaveGamePathWidget(PathManager.getInstance().getRecordingsPath()); getGameInfos().subscribeSelection((widget, item) -> { load.setEnabled(item != null); delete.setEnabled(item != null); updateDescription(item); }); getGameInfos().subscribe((widget, item) -> loadGame(item)); load.subscribe(e -> { GameInfo gameInfo = getGameInfos().getSelection(); if (gameInfo != null) { loadGame(gameInfo); } }); delete.subscribe(button -> { TwoButtonPopup confirmationPopup = getManager().pushScreen(TwoButtonPopup.ASSET_URI, TwoButtonPopup.class); confirmationPopup.setMessage(translationSystem.translate("${engine:menu#remove-confirmation-popup-title}"), translationSystem.translate("${engine:menu#remove-confirmation-popup-message}")); confirmationPopup.setLeftButton(translationSystem.translate("${engine:menu#dialog-yes}"), this::removeSelectedReplay); confirmationPopup.setRightButton(translationSystem.translate("${engine:menu#dialog-no}"), () -> { }); }); close.subscribe(button -> { recordAndReplayCurrentStatus.setStatus(RecordAndReplayStatus.NOT_ACTIVATED); triggerBackAnimation(); }); } }
@BeforeClass public static void setupClass() throws Exception { context = new ContextImpl(); CoreRegistry.setContext(context); context.put(RecordAndReplayCurrentStatus.class, new RecordAndReplayCurrentStatus()); moduleManager = ModuleManagerFactory.create(); context.put(ModuleManager.class, moduleManager); ModuleAwareAssetTypeManager assetTypeManager = new ModuleAwareAssetTypeManager(); assetTypeManager.registerCoreAssetType(Prefab.class, (AssetFactory<Prefab, PrefabData>) PojoPrefab::new, "prefabs"); assetTypeManager.switchEnvironment(moduleManager.getEnvironment()); context.put(AssetManager.class, assetTypeManager.getAssetManager()); }
@Override public void send(EntityRef entity, Event event) { if (Thread.currentThread() != mainThread) { pendingEvents.offer(new PendingEvent(entity, event)); } else { if (recordAndReplayCurrentStatus.getStatus() == RecordAndReplayStatus.RECORDING) { eventCatcher.addEvent(new PendingEvent(entity, event)); } networkReplicate(entity, event); Set<EventHandlerInfo> selectedHandlersSet = selectEventHandlers(event.getClass(), entity); List<EventHandlerInfo> selectedHandlers = Lists.newArrayList(selectedHandlersSet); selectedHandlers.sort(priorityComparator); if (event instanceof ConsumableEvent) { sendConsumableEvent(entity, event, selectedHandlers); } else { sendStandardEvent(entity, event, selectedHandlers); } } }