minecraft-src/com/mojang/realmsclient/gui/screens/configuration/RealmsConfigureWorldScreen.java
2025-09-18 12:27:44 +00:00

360 lines
14 KiB
Java

package com.mojang.realmsclient.gui.screens.configuration;
import com.mojang.logging.LogUtils;
import com.mojang.realmsclient.RealmsMainScreen;
import com.mojang.realmsclient.client.RealmsClient;
import com.mojang.realmsclient.client.RealmsError;
import com.mojang.realmsclient.dto.PlayerInfo;
import com.mojang.realmsclient.dto.PreferredRegionsDto;
import com.mojang.realmsclient.dto.RealmsRegion;
import com.mojang.realmsclient.dto.RealmsServer;
import com.mojang.realmsclient.dto.RealmsSlot;
import com.mojang.realmsclient.dto.RegionDataDto;
import com.mojang.realmsclient.dto.RegionSelectionPreference;
import com.mojang.realmsclient.dto.RegionSelectionPreferenceDto;
import com.mojang.realmsclient.dto.ServiceQuality;
import com.mojang.realmsclient.exception.RealmsServiceException;
import com.mojang.realmsclient.gui.screens.RealmsGenericErrorScreen;
import com.mojang.realmsclient.gui.screens.RealmsLongRunningMcoTaskScreen;
import com.mojang.realmsclient.util.RealmsUtil;
import com.mojang.realmsclient.util.task.CloseServerTask;
import com.mojang.realmsclient.util.task.OpenServerTask;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.components.AbstractWidget;
import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.components.Tooltip;
import net.minecraft.client.gui.components.tabs.LoadingTab;
import net.minecraft.client.gui.components.tabs.Tab;
import net.minecraft.client.gui.components.tabs.TabManager;
import net.minecraft.client.gui.components.tabs.TabNavigationBar;
import net.minecraft.client.gui.layouts.HeaderAndFooterLayout;
import net.minecraft.client.gui.layouts.LinearLayout;
import net.minecraft.client.gui.navigation.ScreenRectangle;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.screens.worldselection.CreateWorldScreen;
import net.minecraft.client.renderer.RenderPipelines;
import net.minecraft.network.chat.CommonComponents;
import net.minecraft.network.chat.Component;
import net.minecraft.realms.RealmsScreen;
import net.minecraft.util.StringUtil;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
@Environment(EnvType.CLIENT)
public class RealmsConfigureWorldScreen extends RealmsScreen {
private static final Logger LOGGER = LogUtils.getLogger();
private static final Component PLAY_TEXT = Component.translatable("mco.selectServer.play");
private final RealmsMainScreen lastScreen;
@Nullable
private RealmsServer serverData;
@Nullable
private PreferredRegionsDto regions;
private final Map<RealmsRegion, ServiceQuality> regionServiceQuality = new LinkedHashMap();
private final long serverId;
private boolean stateChanged;
private final TabManager tabManager = new TabManager(guiEventListener -> {
AbstractWidget var10000 = this.addRenderableWidget(guiEventListener);
}, guiEventListener -> this.removeWidget(guiEventListener), this::onTabSelected, this::onTabDeselected);
@Nullable
private Button playButton;
@Nullable
private TabNavigationBar tabNavigationBar;
private final HeaderAndFooterLayout layout = new HeaderAndFooterLayout(this);
public RealmsConfigureWorldScreen(RealmsMainScreen lastScreen, long serverId, @Nullable RealmsServer serverData, @Nullable PreferredRegionsDto regions) {
super(Component.empty());
this.lastScreen = lastScreen;
this.serverId = serverId;
this.serverData = serverData;
this.regions = regions;
}
public RealmsConfigureWorldScreen(RealmsMainScreen lastScreen, long serverId) {
this(lastScreen, serverId, null, null);
}
@Override
public void init() {
if (this.serverData == null) {
this.fetchServerData(this.serverId);
}
if (this.regions == null) {
this.fetchRegionData();
}
Component component = Component.translatable("mco.configure.world.loading");
this.tabNavigationBar = TabNavigationBar.builder(this.tabManager, this.width)
.addTabs(
new LoadingTab(this.getFont(), RealmsWorldsTab.TITLE, component),
new LoadingTab(this.getFont(), RealmsPlayersTab.TITLE, component),
new LoadingTab(this.getFont(), RealmsSubscriptionTab.TITLE, component),
new LoadingTab(this.getFont(), RealmsSettingsTab.TITLE, component)
)
.build();
this.addRenderableWidget(this.tabNavigationBar);
LinearLayout linearLayout = this.layout.addToFooter(LinearLayout.horizontal().spacing(8));
this.playButton = linearLayout.addChild(Button.builder(PLAY_TEXT, button -> {
this.onClose();
RealmsMainScreen.play(this.serverData, this);
}).width(150).build());
this.playButton.active = false;
linearLayout.addChild(Button.builder(CommonComponents.GUI_BACK, button -> this.onClose()).build());
this.layout.visitWidgets(abstractWidget -> {
abstractWidget.setTabOrderGroup(1);
this.addRenderableWidget(abstractWidget);
});
this.tabNavigationBar.selectTab(0, false);
this.repositionElements();
if (this.serverData != null && this.regions != null) {
this.onRealmsDataFetched();
}
}
private void onTabSelected(Tab tab) {
if (this.serverData != null && tab instanceof RealmsConfigurationTab realmsConfigurationTab) {
realmsConfigurationTab.onSelected(this.serverData);
}
}
private void onTabDeselected(Tab tab) {
if (this.serverData != null && tab instanceof RealmsConfigurationTab realmsConfigurationTab) {
realmsConfigurationTab.onDeselected(this.serverData);
}
}
public int getContentHeight() {
return this.layout.getContentHeight();
}
public int getHeaderHeight() {
return this.layout.getHeaderHeight();
}
public Screen getLastScreen() {
return this.lastScreen;
}
public Screen createErrorScreen(RealmsServiceException exception) {
return new RealmsGenericErrorScreen(exception, this.lastScreen);
}
@Override
public void repositionElements() {
if (this.tabNavigationBar != null) {
this.tabNavigationBar.setWidth(this.width);
this.tabNavigationBar.arrangeElements();
int i = this.tabNavigationBar.getRectangle().bottom();
ScreenRectangle screenRectangle = new ScreenRectangle(0, i, this.width, this.height - this.layout.getFooterHeight() - i);
this.tabManager.setTabArea(screenRectangle);
this.layout.setHeaderHeight(i);
this.layout.arrangeElements();
}
}
private void updateButtonStates() {
if (this.serverData != null && this.playButton != null) {
this.playButton.active = this.serverData.shouldPlayButtonBeActive();
if (!this.playButton.active && this.serverData.state == RealmsServer.State.CLOSED) {
this.playButton.setTooltip(Tooltip.create(RealmsServer.WORLD_CLOSED_COMPONENT));
}
}
}
@Override
public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) {
super.render(guiGraphics, mouseX, mouseY, partialTick);
guiGraphics.blit(RenderPipelines.GUI_TEXTURED, Screen.FOOTER_SEPARATOR, 0, this.height - this.layout.getFooterHeight() - 2, 0.0F, 0.0F, this.width, 2, 32, 2);
}
@Override
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
return this.tabNavigationBar.keyPressed(keyCode) ? true : super.keyPressed(keyCode, scanCode, modifiers);
}
@Override
protected void renderMenuBackground(GuiGraphics partialTick) {
partialTick.blit(RenderPipelines.GUI_TEXTURED, CreateWorldScreen.TAB_HEADER_BACKGROUND, 0, 0, 0.0F, 0.0F, this.width, this.layout.getHeaderHeight(), 16, 16);
this.renderMenuBackground(partialTick, 0, this.layout.getHeaderHeight(), this.width, this.height);
}
@Override
public void onClose() {
if (this.serverData != null && this.tabManager.getCurrentTab() instanceof RealmsConfigurationTab realmsConfigurationTab) {
realmsConfigurationTab.onDeselected(this.serverData);
}
this.minecraft.setScreen(this.lastScreen);
if (this.stateChanged) {
this.lastScreen.resetScreen();
}
}
public void fetchRegionData() {
RealmsUtil.supplyAsync(
RealmsClient::getPreferredRegionSelections, RealmsUtil.openScreenAndLogOnFailure(this::createErrorScreen, "Couldn't get realms region data")
)
.thenAcceptAsync(preferredRegionsDto -> {
this.regions = preferredRegionsDto;
this.onRealmsDataFetched();
}, this.minecraft);
}
public void fetchServerData(long serverId) {
RealmsUtil.supplyAsync(
realmsClient -> realmsClient.getOwnRealm(serverId), RealmsUtil.openScreenAndLogOnFailure(this::createErrorScreen, "Couldn't get own world")
)
.thenAcceptAsync(realmsServer -> {
this.serverData = realmsServer;
this.onRealmsDataFetched();
}, this.minecraft);
}
private void onRealmsDataFetched() {
if (this.serverData != null && this.regions != null) {
this.regionServiceQuality.clear();
for (RegionDataDto regionDataDto : this.regions.regionData()) {
if (regionDataDto.region() != RealmsRegion.INVALID_REGION) {
this.regionServiceQuality.put(regionDataDto.region(), regionDataDto.serviceQuality());
}
}
if (this.tabNavigationBar != null) {
this.removeWidget(this.tabNavigationBar);
}
this.tabNavigationBar = TabNavigationBar.builder(this.tabManager, this.width)
.addTabs(
new RealmsWorldsTab(this, (Minecraft)Objects.requireNonNull(this.minecraft), this.serverData),
new RealmsPlayersTab(this, this.minecraft, this.serverData),
new RealmsSubscriptionTab(this, this.minecraft, this.serverData),
new RealmsSettingsTab(this, this.minecraft, this.serverData, this.regionServiceQuality)
)
.build();
this.addRenderableWidget(this.tabNavigationBar);
this.tabNavigationBar.selectTab(0, false);
this.tabNavigationBar.setTabActiveState(3, !this.serverData.expired);
if (this.serverData.expired) {
this.tabNavigationBar.setTabTooltip(3, Tooltip.create(Component.translatable("mco.configure.world.settings.expired")));
} else {
this.tabNavigationBar.setTabTooltip(3, null);
}
this.updateButtonStates();
this.repositionElements();
}
}
public void saveSlotSettings(RealmsSlot slot) {
RealmsSlot realmsSlot = (RealmsSlot)this.serverData.slots.get(this.serverData.activeSlot);
slot.options.templateId = realmsSlot.options.templateId;
slot.options.templateImage = realmsSlot.options.templateImage;
RealmsClient realmsClient = RealmsClient.getOrCreate();
try {
if (this.serverData.activeSlot != slot.slotId) {
throw new RealmsServiceException(RealmsError.CustomError.configurationError());
}
realmsClient.updateSlot(this.serverData.id, slot.slotId, slot.options, slot.settings);
this.serverData.slots.put(this.serverData.activeSlot, slot);
if (slot.options.gameMode != realmsSlot.options.gameMode || slot.isHardcore() != realmsSlot.isHardcore()) {
RealmsMainScreen.refreshServerList();
}
this.stateChanged();
} catch (RealmsServiceException var5) {
LOGGER.error("Couldn't save slot settings", (Throwable)var5);
this.minecraft.setScreen(new RealmsGenericErrorScreen(var5, this));
return;
}
this.minecraft.setScreen(this);
}
public void saveSettings(String name, String description, RegionSelectionPreference regionSelectionPreference, @Nullable RealmsRegion preferredRegiom) {
String string = StringUtil.isBlank(description) ? "" : description;
String string2 = StringUtil.isBlank(name) ? "" : name;
RealmsClient realmsClient = RealmsClient.getOrCreate();
try {
RealmsSlot realmsSlot = (RealmsSlot)this.serverData.slots.get(this.serverData.activeSlot);
RealmsRegion realmsRegion = regionSelectionPreference == RegionSelectionPreference.MANUAL ? preferredRegiom : null;
RegionSelectionPreferenceDto regionSelectionPreferenceDto = new RegionSelectionPreferenceDto(regionSelectionPreference, realmsRegion);
realmsClient.updateConfiguration(
this.serverData.id, string2, string, regionSelectionPreferenceDto, realmsSlot.slotId, realmsSlot.options, realmsSlot.settings
);
this.serverData.regionSelectionPreference = regionSelectionPreferenceDto;
this.serverData.name = name;
this.serverData.motd = string;
this.stateChanged();
} catch (RealmsServiceException var11) {
LOGGER.error("Couldn't save settings", (Throwable)var11);
this.minecraft.setScreen(new RealmsGenericErrorScreen(var11, this));
return;
}
this.minecraft.setScreen(this);
}
public void openTheWorld(boolean join) {
RealmsConfigureWorldScreen realmsConfigureWorldScreen = this.getNewScreenWithKnownData(this.serverData);
this.minecraft
.setScreen(new RealmsLongRunningMcoTaskScreen(this.getNewScreen(), new OpenServerTask(this.serverData, realmsConfigureWorldScreen, join, this.minecraft)));
}
public void closeTheWorld() {
RealmsConfigureWorldScreen realmsConfigureWorldScreen = this.getNewScreenWithKnownData(this.serverData);
this.minecraft.setScreen(new RealmsLongRunningMcoTaskScreen(this.getNewScreen(), new CloseServerTask(this.serverData, realmsConfigureWorldScreen)));
}
public void stateChanged() {
this.stateChanged = true;
if (this.tabNavigationBar != null) {
for (Tab tab : this.tabNavigationBar.getTabs()) {
if (tab instanceof RealmsConfigurationTab realmsConfigurationTab) {
realmsConfigurationTab.updateData(this.serverData);
}
}
}
}
public boolean invitePlayer(long worldId, String playerName) {
RealmsClient realmsClient = RealmsClient.getOrCreate();
try {
List<PlayerInfo> list = realmsClient.invite(worldId, playerName);
if (this.serverData != null) {
this.serverData.players = list;
} else {
this.serverData = realmsClient.getOwnRealm(worldId);
}
this.stateChanged();
return true;
} catch (RealmsServiceException var6) {
LOGGER.error("Couldn't invite user", (Throwable)var6);
return false;
}
}
public RealmsConfigureWorldScreen getNewScreen() {
RealmsConfigureWorldScreen realmsConfigureWorldScreen = new RealmsConfigureWorldScreen(this.lastScreen, this.serverId);
realmsConfigureWorldScreen.stateChanged = this.stateChanged;
return realmsConfigureWorldScreen;
}
public RealmsConfigureWorldScreen getNewScreenWithKnownData(RealmsServer server) {
RealmsConfigureWorldScreen realmsConfigureWorldScreen = new RealmsConfigureWorldScreen(this.lastScreen, this.serverId, server, this.regions);
realmsConfigureWorldScreen.stateChanged = this.stateChanged;
return realmsConfigureWorldScreen;
}
}