Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add various lifetime-bound try-with-resources APIs to client gametests #4318

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@
import net.minecraft.client.gui.screen.Screen;

/**
* Context for a client gametest containing various helpful functions and functions to access the game. Functions in
* this class can only be called on the client gametest thread.
* Context for a client gametest containing various helpful functions and functions to access the game.
*
* <p>Functions in this class can only be called on the client gametest thread.
*/
@ApiStatus.NonExtendable
public interface ClientGameTestContext {
Expand Down Expand Up @@ -61,25 +62,28 @@ public interface ClientGameTestContext {
* Waits for a predicate to be true. Fails if the predicate is not satisfied after {@link #DEFAULT_TIMEOUT} ticks.
*
* @param predicate The predicate to check
* @return The number of ticks waited
*/
void waitFor(Predicate<MinecraftClient> predicate);
int waitFor(Predicate<MinecraftClient> predicate);

/**
* Waits for a predicate to be true. Fails if the predicate is not satisfied after {@code timeout} ticks. If
* {@code timeout} is {@link #NO_TIMEOUT}, there is no timeout.
*
* @param predicate The predicate to check
* @param timeout The number of ticks before timing out
* @return The number of ticks waited
*/
void waitFor(Predicate<MinecraftClient> predicate, int timeout);
int waitFor(Predicate<MinecraftClient> predicate, int timeout);

/**
* Waits for the given screen class to be shown. If {@code screenClass} is {@code null}, waits for the current
* screen to be {@code null}. Fails if the screen does not open after {@link #DEFAULT_TIMEOUT} ticks.
*
* @param screenClass The screen class to wait to open
* @return The number of ticks waited
*/
void waitForScreen(@Nullable Class<? extends Screen> screenClass);
int waitForScreen(@Nullable Class<? extends Screen> screenClass);

/**
* Opens a {@link Screen} on the client.
Expand Down Expand Up @@ -126,7 +130,14 @@ public interface ClientGameTestContext {
*
* @return The client gametest input handler
*/
ClientGameTestInput getInput();
TestInput getInput();

/**
* Creates a world builder for creating singleplayer worlds and dedicated servers.
*
* @return A new world builder
*/
TestWorldBuilder worldBuilder();

/**
* Restores all game options in {@link MinecraftClient#options} to their default values for client gametests. This
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/*
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package net.fabricmc.fabric.api.client.gametest.v1;

import org.jetbrains.annotations.ApiStatus;

import net.minecraft.SharedConstants;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.util.math.BlockPos;

/**
* Context for a client gametest containing various helpful functions while a client world is open.
*
* <p>Functions in this class can only be called on the client gametest thread.
*/
@ApiStatus.NonExtendable
public interface TestClientWorldContext {
/**
* The default timeout in ticks to wait for chunks to load/render (1 minute).
*/
int DEFAULT_CHUNK_LOAD_TIMEOUT = SharedConstants.TICKS_PER_MINUTE;

/**
* Waits for all chunks that will be downloaded from the server to be downloaded. Fails if the chunks haven't been
* downloaded after {@link #DEFAULT_CHUNK_LOAD_TIMEOUT} ticks. See {@link #waitForChunksDownload(int)} for details.
*
* @return The number of ticks waited
*/
default int waitForChunksDownload() {
return waitForChunksDownload(DEFAULT_CHUNK_LOAD_TIMEOUT);
}

/**
Waits for all chunks that will be downloaded from the server to be downloaded. After this, methods such as
* {@link ClientWorld#getChunk(int, int)} and {@link ClientWorld#getBlockState(BlockPos)} will return the expected
* value. However, the chunks may not yet be rendered and may not appear in screenshots, if you need this, use
* {@link #waitForChunksRender(int)} instead. Fails if the chunks haven't been downloaded after {@code timeout}
* ticks.
*
* @param timeout The number of ticks before timing out
* @return The number of ticks waited
*/
int waitForChunksDownload(int timeout);

/**
* Waits for all chunks to be downloaded and rendered. After this, all chunks that will ever be visible are visible
* in screenshots. Fails if the chunks haven't been downloaded and rendered after
* {@link #DEFAULT_CHUNK_LOAD_TIMEOUT} ticks.
*
* @return The number of ticks waited
*/
default int waitForChunksRender() {
return waitForChunksRender(DEFAULT_CHUNK_LOAD_TIMEOUT);
}

/**
* Waits for all chunks to be downloaded and rendered. After this, all chunks that will ever be visible are visible
* in screenshots. Fails if the chunks haven't been downloaded and rendered after {@code timeout} ticks.
*
* @param timeout The number of ticks before timing out
* @return The number of ticks waited
*/
default int waitForChunksRender(int timeout) {
return waitForChunksRender(true, timeout);
}

/**
* Waits for all chunks to be rendered, optionally waiting for chunks to be downloaded first. After this, all chunks
* that are present in the client world will be visible in screenshots. Fails if the chunks haven't been rendered
* (and optionally downloaded) after {@link #DEFAULT_CHUNK_LOAD_TIMEOUT} ticks.
*
* @param waitForDownload Whether to wait for chunks to be downloaded
* @return The number of ticks waited
*/
default int waitForChunksRender(boolean waitForDownload) {
return waitForChunksRender(waitForDownload, DEFAULT_CHUNK_LOAD_TIMEOUT);
}

/**
* Waits for all chunks to be rendered, optionally waiting for chunks to be downloaded first. After this, all chunks
* that are present in the client world will be visible in screenshots. Fails if the chunks haven't been rendered
* (and optionally downloaded) after {@code timeout} ticks.
*
* @param waitForDownload Whether to wait for chunks to be downloaded
* @param timeout The number of ticks before timing out
* @return The number of ticks waited
*/
int waitForChunksRender(boolean waitForDownload, int timeout);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package net.fabricmc.fabric.api.client.gametest.v1;

import org.jetbrains.annotations.ApiStatus;

/**
* Context for a client gametest containing various helpful functions while an in-process dedicated server is running.
* This class implements {@link AutoCloseable} and is intended to be used in a try-with-resources statement. When
* closed, the dedicated server will be stopped.
*
* <p>Functions in this class can only be called on the client gametest thread.
*/
@ApiStatus.NonExtendable
public interface TestDedicatedServerContext extends TestServerContext, AutoCloseable {
/**
* Connects the client to the dedicated server. The resulting connection is intended to be used in a
* try-with-resources statement.
*
* @return The connection handle to the dedicated server
*/
TestServerConnection connect();

/**
* Stops the dedicated server.
*/
@Override
void close();
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
* The client gametest input handler used to simulate inputs to the client.
*/
@ApiStatus.NonExtendable
public interface ClientGameTestInput {
public interface TestInput {
/**
* Starts holding down a key binding. The key binding will be held until it is released. The key binding must be
* bound. Does nothing if the key binding is already being held.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package net.fabricmc.fabric.api.client.gametest.v1;

import org.jetbrains.annotations.ApiStatus;

/**
* Context for a connection to a dedicated server containing various helpful functions while the connection is alive.
* This class implements {@link AutoCloseable} and is intended to be used in a try-with-resources statement. When
* closed, the client will be disconnected from the server.
*
* <p>Functions in this class can only be called on the client gametest thread.
*/
@ApiStatus.NonExtendable
public interface TestServerConnection extends AutoCloseable {
/**
* Gets the client world context for this connection.
*
* @return The client world context
*/
TestClientWorldContext getClientWorld();

/**
* Disconnects the client from the dedicated server.
*/
@Override
void close();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package net.fabricmc.fabric.api.client.gametest.v1;

import org.apache.commons.lang3.function.FailableConsumer;
import org.apache.commons.lang3.function.FailableFunction;
import org.jetbrains.annotations.ApiStatus;

import net.minecraft.server.MinecraftServer;

/**
* Context for a client gametest containing various helpful functions while a server (integrated or dedicated) is
* running.
*
* <p>Functions in this class can only be called on the client gametest thread.
*/
@ApiStatus.NonExtendable
public interface TestServerContext {
/**
* Runs a command on the server.
*
* @param command The command to run
*/
void runCommand(String command);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A thing for the future, but getting the result of the command might be handy, not quite how it would work but I could see it being useful.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function was just copied over from TestDedicatedServer. But yes, could be handy. Annoyingly the current function it's implemented with doesn't return the result of the command but it should hopefully be a case of finding a different function to use.


/**
* Runs the given action on the server thread, and waits for it to complete.
*
* @param action The action to run on the server thread
* @param <E> The type of the checked exception that the action throws
* @throws E When the action throws an exception
*/
<E extends Throwable> void runOnServer(FailableConsumer<MinecraftServer, E> action) throws E;

/**
* Runs the given function on the server thread, and returns the result.
*
* @param function The function to run on the server thread
* @return The result of the function
* @param <T> The type of the value to return
* @param <E> The type of the checked exception that the function throws
* @throws E When the function throws an exception
*/
<T, E extends Throwable> T computeOnServer(FailableFunction<MinecraftServer, T, E> function) throws E;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package net.fabricmc.fabric.api.client.gametest.v1;

import org.jetbrains.annotations.ApiStatus;

/**
* Context for a client gametest containing various helpful functions while a singleplayer game is open.
*
* <p>Functions in this class can only be called on the client gametest thread.
*/
@ApiStatus.NonExtendable
public interface TestSingleplayerContext extends AutoCloseable {
/**
* Gets the handle for the world save.
*
* @return The handle for the world save
*/
TestWorldSave getWorldSave();

/**
* Gets the handle for the client world.
*
* @return The handle for the client world
*/
TestClientWorldContext getClientWorld();

/**
* Gets the handle for the integrated server.
*
* @return The handle for the integrated server
*/
TestServerContext getServer();

/**
* Closes the singleplayer world.
*/
@Override
void close();
}
Loading