feat: Handle small terminals

This commit is contained in:
2025-12-16 22:40:54 +01:00
parent a26aaf69e1
commit 2bca24d6cd
3 changed files with 104 additions and 38 deletions

View File

@@ -0,0 +1,6 @@
package cz.jzitnik.events;
import cz.jzitnik.utils.events.Event;
public class TerminalTooSmallEvent implements Event {
}

View File

@@ -9,6 +9,7 @@ import cz.jzitnik.annotations.injectors.InjectDependency;
import cz.jzitnik.annotations.injectors.InjectState;
import cz.jzitnik.events.FullRoomDraw;
import cz.jzitnik.events.RerenderScreen;
import cz.jzitnik.events.TerminalTooSmallEvent;
import cz.jzitnik.game.GameRoom;
import cz.jzitnik.game.GameState;
import cz.jzitnik.game.Player;
@@ -62,56 +63,61 @@ public class FullRoomDrawHandler extends AbstractEventHandler<FullRoomDraw> {
@Override
public void handle(FullRoomDraw event) {
log.debug("Rendering full room");
TerminalScreen terminalScreen = terminalState.getTerminalScreen();
List<RerenderScreen.ScreenPart> partsToRerender = new ArrayList<>();
GameRoom currentRoom = gameState.getCurrentRoom();
try {
log.debug("Rendering full room");
TerminalScreen terminalScreen = terminalState.getTerminalScreen();
List<RerenderScreen.ScreenPart> partsToRerender = new ArrayList<>();
GameRoom currentRoom = gameState.getCurrentRoom();
Set<DoorPosition> doorPositions = RerenderUtils.getDoorPositions(currentRoom);
Set<DoorPosition> doorPositions = RerenderUtils.getDoorPositions(currentRoom);
var buffer = screenBuffer.getRenderedBuffer();
var overrideBuffer = currentRoom.getOverrideBuffer();
var buffer = screenBuffer.getRenderedBuffer();
var overrideBuffer = currentRoom.getOverrideBuffer();
BufferedImage room = resourceManager.getResource(currentRoom.getTexture());
BufferedImage doors = resourceManager.getResource(ResourceManager.Resource.DOORS);
Player player = gameState.getPlayer();
BufferedImage playerTexture = RerenderUtils.getPlayer(resourceManager, player);
TerminalSize terminalSize = terminalScreen.getTerminalSize();
BufferedImage room = resourceManager.getResource(currentRoom.getTexture());
BufferedImage doors = resourceManager.getResource(ResourceManager.Resource.DOORS);
Player player = gameState.getPlayer();
BufferedImage playerTexture = RerenderUtils.getPlayer(resourceManager, player);
TerminalSize terminalSize = terminalScreen.getTerminalSize();
int width = room.getWidth();
int height = room.getHeight();
int width = room.getWidth();
int height = room.getHeight();
var start = RerenderUtils.getStart(room, terminalSize);
int startX = start.getX();
int startY = start.getY();
var start = RerenderUtils.getStart(room, terminalSize);
int startX = start.getX();
int startY = start.getY();
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
RerenderUtils.PixelResult pixelResult = RerenderUtils.getPixel(currentRoom, room, doors, doorPositions, player, playerTexture, x, y);
int pixel = pixelResult.pixel();
int red = (pixel >> 16) & 0xff;
int green = (pixel >> 8) & 0xff;
int blue = pixel & 0xff;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
RerenderUtils.PixelResult pixelResult = RerenderUtils.getPixel(currentRoom, room, doors, doorPositions, player, playerTexture, x, y);
int pixel = pixelResult.pixel();
int red = (pixel >> 16) & 0xff;
int green = (pixel >> 8) & 0xff;
int blue = pixel & 0xff;
Pixel overridePixel = overrideBuffer[y][x];
Pixel pixel1 = new ColoredPixel(new TextColor.RGB(red, green, blue));
Pixel overridePixel = overrideBuffer[y][x];
Pixel pixel1 = new ColoredPixel(new TextColor.RGB(red, green, blue));
Pixel finalPixelLeft = overridePixel.getClass() == Empty.class || pixelResult.isPlayer() ? pixel1 : overridePixel;
Pixel finalPixelLeft = overridePixel.getClass() == Empty.class || pixelResult.isPlayer() ? pixel1 : overridePixel;
buffer[y + startY][x + startX] = finalPixelLeft;
buffer[y + startY][x + startX] = finalPixelLeft;
}
}
}
partsToRerender.add(new RerenderScreen.ScreenPart(
new TerminalPosition(startX, startY),
new TerminalPosition(startX + width, startY + height - 1)
));
partsToRerender.add(new RerenderScreen.ScreenPart(
new TerminalPosition(startX, startY),
new TerminalPosition(startX + width, startY + height - 1)
));
if (renderState.isFirstRender() || event.isFullRerender()) {
eventManager.emitEvent(RerenderScreen.full(terminalSize));
renderState.setFirstRender(false);
} else {
eventManager.emitEvent(new RerenderScreen(partsToRerender.toArray(RerenderScreen.ScreenPart[]::new)));
if (renderState.isFirstRender() || event.isFullRerender()) {
eventManager.emitEvent(RerenderScreen.full(terminalSize));
renderState.setFirstRender(false);
} else {
eventManager.emitEvent(new RerenderScreen(partsToRerender.toArray(RerenderScreen.ScreenPart[]::new)));
}
} catch (ArrayIndexOutOfBoundsException e) {
// Screen too small to fit the room
eventManager.emitEvent(new TerminalTooSmallEvent());
}
}
}

View File

@@ -0,0 +1,54 @@
package cz.jzitnik.events.handlers;
import com.googlecode.lanterna.SGR;
import com.googlecode.lanterna.TerminalSize;
import com.googlecode.lanterna.TextCharacter;
import com.googlecode.lanterna.TextColor;
import com.googlecode.lanterna.screen.Screen;
import com.googlecode.lanterna.screen.TerminalScreen;
import cz.jzitnik.annotations.EventHandler;
import cz.jzitnik.annotations.injectors.InjectState;
import cz.jzitnik.events.TerminalTooSmallEvent;
import cz.jzitnik.states.TerminalState;
import cz.jzitnik.utils.DependencyManager;
import cz.jzitnik.utils.events.AbstractEventHandler;
import java.io.IOException;
@EventHandler(TerminalTooSmallEvent.class)
public class TerminalTooSmallEventHandler extends AbstractEventHandler<TerminalTooSmallEvent> {
public TerminalTooSmallEventHandler(DependencyManager dm) {
super(dm);
}
@InjectState
private TerminalState terminalState;
@Override
public void handle(TerminalTooSmallEvent event) {
// Directly render message for the user
TerminalScreen terminalScreen = terminalState.getTerminalScreen();
terminalScreen.clear();
TerminalSize terminalSize = terminalScreen.getTerminalSize();
String text = "Terminal too small!";
String subText = "Please resize your terminal";
int startY = terminalSize.getRows() / 2;
int textStartX = (terminalSize.getColumns() / 2) - (text.length() / 2);
for (char character : text.toCharArray()) {
terminalScreen.setCharacter(textStartX++, startY, new TextCharacter(character, TextColor.ANSI.RED, TextColor.ANSI.DEFAULT, SGR.BOLD));
}
int subTextStartX = (terminalSize.getColumns() / 2) - (subText.length() / 2);
for (char character : subText.toCharArray()) {
terminalScreen.setCharacter(subTextStartX++, startY + 1, new TextCharacter(character, TextColor.ANSI.BLACK_BRIGHT, TextColor.ANSI.DEFAULT));
}
try {
terminalScreen.refresh(Screen.RefreshType.COMPLETE);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}