Skip to content

Commit

Permalink
Fix cables randomly disconnecting, asynchronous custom audio loading
Browse files Browse the repository at this point in the history
  • Loading branch information
FoundationGames committed Aug 7, 2023
1 parent 1422f25 commit 8ee1672
Show file tree
Hide file tree
Showing 10 changed files with 75 additions and 28 deletions.
10 changes: 0 additions & 10 deletions src/main/java/io/github/foundationgames/phonos/Phonos.java
Original file line number Diff line number Diff line change
Expand Up @@ -77,16 +77,6 @@ public void onInitialize() {
Phonos.LOG.error("Error loading custom audio files", ex);
}
});
ServerLifecycleEvents.SERVER_STOPPED.register(e -> {
try {
var path = PhonosUtil.getCustomSoundFolder(e);
if (!Files.exists(path)) Files.createDirectory(path);

ServerCustomAudio.save(path);
} catch (IOException ex) {
Phonos.LOG.error("Error saving custom audio files", ex);
}
});
ServerPlayConnectionEvents.DISCONNECT.register((handler, server) ->
ServerCustomAudio.onPlayerDisconnect(handler.getPlayer()));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ public void setInputPluggedIn(int inputIndex, boolean pluggedIn, BlockState stat
inputIndex = MathHelper.clamp(inputIndex, 0, be.inputs.length - 1);
be.inputs[inputIndex] = pluggedIn;
be.sync();
be.markDirty();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ public void setInputPluggedIn(int inputIndex, boolean pluggedIn, BlockState stat
inputIndex = MathHelper.clamp(inputIndex, 0, be.inputs.length - 1);
be.inputs[inputIndex] = pluggedIn;
be.sync();
be.markDirty();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ public void setInputPluggedIn(int inputIndex, boolean pluggedIn, BlockState stat
}

be.sync();
be.markDirty();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public SatelliteStationBlockEntity(BlockPos pos, BlockState state) {
}

public void play() {
if (world instanceof ServerWorld sWorld && ServerCustomAudio.hasSaved(this.streamId)) {
if (world instanceof ServerWorld sWorld && ServerCustomAudio.loaded() && ServerCustomAudio.hasSaved(this.streamId)) {
var aud = ServerCustomAudio.loadSaved(this.streamId);
ServerOutgoingStreamHandler.startStream(this.streamId, aud, sWorld.getServer());

Expand Down Expand Up @@ -143,11 +143,13 @@ public void tick(World world, BlockPos pos, BlockState state) {
sync();
}

if (status == Status.NONE && (ServerCustomAudio.UPLOADING.containsKey(this.streamId) || ServerCustomAudio.SAVED.containsKey(this.streamId))) {
this.performAction(ACTION_LAUNCH);
} else if (status == Status.IN_ORBIT) {
if (!ServerCustomAudio.SAVED.containsKey(this.streamId)) {
this.performAction(ACTION_CRASH);
if (ServerCustomAudio.loaded()) {
if (status == Status.NONE && (ServerCustomAudio.UPLOADING.containsKey(this.streamId) || ServerCustomAudio.SAVED.containsKey(this.streamId))) {
this.performAction(ACTION_LAUNCH);
} else if (status == Status.IN_ORBIT) {
if (!ServerCustomAudio.SAVED.containsKey(this.streamId)) {
this.performAction(ACTION_CRASH);
}
}
}
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import com.google.gson.Gson;
import io.github.foundationgames.phonos.Phonos;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.client.option.SimpleOption;

import java.io.IOException;
import java.nio.file.Files;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,23 @@
import java.nio.ByteBuffer;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

public class ServerCustomAudio {
public static final String FILE_EXT = ".phonosaud";

public static final ExecutorService UPLOAD_POOL = Executors.newFixedThreadPool(1);
public static final ExecutorService FILESYS_POOL = Executors.newFixedThreadPool(4);

public static final Long2ObjectMap<AudioDataQueue> UPLOADING = Long2ObjectMaps.synchronize(new Long2ObjectOpenHashMap<>());
public static final Long2ObjectMap<AudioDataQueue> SAVED = new Long2ObjectOpenHashMap<>();
public static final Long2ObjectMap<AudioDataQueue> SAVED = Long2ObjectMaps.synchronize(new Long2ObjectOpenHashMap<>());

private static int TOTAL_SAVED_SIZE = 0;

Expand Down Expand Up @@ -94,6 +100,10 @@ private static void handleUpload(MinecraftServer srv, ServerPlayerEntity player,
}
}

public static boolean loaded() {
return LOADED;
}

public static void deleteSaved(MinecraftServer srv, long id) {
var aud = SAVED.remove(id);

Expand Down Expand Up @@ -132,7 +142,7 @@ public static void deleteOnly(long id, Path folder) throws IOException {
Files.deleteIfExists(path);
}

public static void save(Path folder) throws IOException {
public static void saveAll(Path folder) throws IOException {
if (!LOADED) {
Phonos.LOG.error("Tried to save custom uploaded audio before it was loaded!");

Expand Down Expand Up @@ -168,29 +178,51 @@ public static void save(Path folder) throws IOException {
}

public static void load(Path folder) throws IOException {
final var startTime = Instant.now();

SAVED.clear();

List<String> files = new ArrayList<>();
try (var paths = Files.walk(folder, 1)) {
for (var path : paths.toList()) {
var filename = path.getFileName().toString();
if (filename.endsWith(FILE_EXT)) {
var hexStr = filename.replace(FILE_EXT, "");

try {
long id = Long.parseUnsignedLong(hexStr, 16);
try (var in = Files.newInputStream(path)) {
var aud = AudioDataQueue.read(in, ByteBuffer::allocate);
SAVED.put(id, aud);
TOTAL_SAVED_SIZE += aud.originalSize;
}

Long.parseUnsignedLong(hexStr, 16);
files.add(hexStr);
} catch (NumberFormatException ex) {
Phonos.LOG.error("Audio data " + filename + " has invalid name");
}
}
}
}

LOADED = true;
Phonos.LOG.info("Loaded " + TOTAL_SAVED_SIZE + " bytes of saved audio from <world>/phonos/");
final int foundDataCount = files.size();
var loadedDataCount = new AtomicInteger(0);

for (final var hexStr : files) {
final var path = folder.resolve(hexStr + FILE_EXT);
FILESYS_POOL.submit(() -> {
long id = Long.parseUnsignedLong(hexStr, 16);

try (var in = Files.newInputStream(path)) {
var aud = AudioDataQueue.read(in, ByteBuffer::allocate);

SAVED.put(id, aud);
TOTAL_SAVED_SIZE += aud.originalSize;
} catch (IOException ex) {
Phonos.LOG.error("Error loading custom audio file {}", path.getFileName());
}

if (loadedDataCount.incrementAndGet() >= foundDataCount) {
LOADED = true;

var dur = Duration.between(startTime, Instant.now());
Phonos.LOG.info("Loaded {} bytes of saved audio from <world>/phonos/ in {} ms", TOTAL_SAVED_SIZE, dur.toMillis());
}
});
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,12 @@ public static void init() {
public static int satelliteInspect(ServerCommandSource source, BlockPos pos) {
var world = source.getWorld();

if (!ServerCustomAudio.loaded()) {
source.sendError(Text.translatable("command.phonos.satellite.not_loaded"));

return 1;
}

if (world.getBlockEntity(pos) instanceof SatelliteStationBlockEntity be) {
long id = be.streamId;

Expand All @@ -98,6 +104,12 @@ public static int satelliteInspect(ServerCommandSource source, BlockPos pos) {
}

public static int satelliteList(ServerCommandSource source) {
if (!ServerCustomAudio.loaded()) {
source.sendError(Text.translatable("command.phonos.satellite.not_loaded"));

return 1;
}

var set = ServerCustomAudio.SAVED.long2ObjectEntrySet();

if (set.isEmpty()) {
Expand Down Expand Up @@ -125,6 +137,12 @@ public static int satelliteList(ServerCommandSource source) {
}

public static int satelliteCrash(ServerCommandSource source, long id) throws CommandSyntaxException {
if (!ServerCustomAudio.loaded()) {
source.sendError(Text.translatable("command.phonos.satellite.not_loaded"));

return 1;
}

var idStr = Long.toHexString(id);
Phonos.LOG.info("Satellite {} was crashed via command by player {}.", idStr, source.getPlayerOrThrow());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ public boolean purge(Consumer<CableConnection> purgeAction) {
}

if (connections[i] != null && connections[i].shouldRemove(this.blockEntity.getWorld())) {
System.out.println("CAN EXIST: " + connections[i].end.canPlugExist(this.blockEntity.getWorld()));

purgeAction.accept(connections[i]);
connections[i] = null;
changed = true;
Expand Down
1 change: 1 addition & 0 deletions src/main/resources/assets/phonos/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

"command.phonos.radar.none_found": "Found no radio emitters on channel %s.",
"command.phonos.radar.success": "Nearest radio emitter located at %s.",
"command.phonos.satellite.not_loaded": "Satellites are not yet ready.",
"command.phonos.satellite.inspect.no_upload": "This station has no orbiting satellite!",
"command.phonos.satellite.inspect.invalid": "This block is not a satellite station!",
"command.phonos.satellite.crash": "Crashed satellite with id %s.",
Expand Down

0 comments on commit 8ee1672

Please sign in to comment.