diff --git a/src/client/java/dev/quickinfos/QuickInfosClient.java b/src/client/java/dev/quickinfos/QuickInfosClient.java index e4bacd6..e8cd20f 100644 --- a/src/client/java/dev/quickinfos/QuickInfosClient.java +++ b/src/client/java/dev/quickinfos/QuickInfosClient.java @@ -7,6 +7,7 @@ import dev.quickinfos.infos.*; import dev.quickinfos.trackers.DeathCoordinatesTracker; import dev.quickinfos.trackers.Tracker; +import dev.quickinfos.utils.ExitUtils; import dev.quickinfos.utils.ScreenUtils; import dev.quickinfos.utils.StaticUtils; import net.fabricmc.api.ClientModInitializer; @@ -42,7 +43,7 @@ private void onInitializeLoadStatic() { } } - for (Info info : new Info[] {new Coordinates(), new DeathCoordinates(), new TargetedBlock(), new TargetedBlockCoordinates(), new CurrentBiome(), new FacingDirection()}) { + for (Info info : new Info[] {new Coordinates(), new DeathCoordinates(), new TargetedBlock(), new TargetedBlockCoordinates(), new TargetedEntity(), new TargetedEntityCoordinates(), new CurrentBiome(), new FacingDirection(), new FPS(), new Ping()}) { try { Singleton.INFOS_INSTANCES.put(info.getClass().getName(), info); } catch (Throwable e) { @@ -52,14 +53,19 @@ private void onInitializeLoadStatic() { } private void onInitializeLoadConfig() { - Singleton.config = ConfigManager.loadConfig(); - if(Singleton.config.isValid()){ - Singleton.useUserConfig(); + try{ + Singleton.config = ConfigManager.loadConfig(); + if(Singleton.config.isValid()){ + Singleton.useUserConfig(); + return; + } } - else { - Singleton.useDefaultConfig(); - Singleton.useDefaultOrderedInfos(); + catch (Throwable e) { + System.out.println("Failed to load config: " + e.getMessage()); } + + Singleton.useDefaultConfig(); + Singleton.useDefaultOrderedInfos(); } private void onInitializeRegisterEvents() { @@ -110,10 +116,10 @@ private void onInitializeRegisterEvents() { commandContext -> { try{ ScreenUtils.openScreen(commandContext.getSource().getClient()); - return 0; + return ExitUtils.PROPER_EXIT; }catch (Throwable e){ commandContext.getSource().sendError(Text.of(e.toString())); - return 1; + return ExitUtils.ERROR_IN_OPENED_SCREEN_EXIT; } } )) diff --git a/src/client/java/dev/quickinfos/Singleton.java b/src/client/java/dev/quickinfos/Singleton.java index cd77480..9d02578 100644 --- a/src/client/java/dev/quickinfos/Singleton.java +++ b/src/client/java/dev/quickinfos/Singleton.java @@ -2,9 +2,6 @@ import dev.quickinfos.config.Config; import dev.quickinfos.enums.Positions; -import dev.quickinfos.infos.Coordinates; -import dev.quickinfos.infos.CurrentBiome; -import dev.quickinfos.infos.FacingDirection; import dev.quickinfos.infos.Info; import dev.quickinfos.trackers.Tracker; import dev.quickinfos.utils.DefaultConfigUtils; @@ -31,15 +28,15 @@ public class Singleton { private Singleton() {} public static void useDefaultConfig(){ - INFOS_INSTANCES.get(Coordinates.class.getName()).setOn(true); - INFOS_INSTANCES.get(CurrentBiome.class.getName()).setOn(true); - INFOS_INSTANCES.get(FacingDirection.class.getName()).setOn(true); - - POSITION = Positions.TOP_RIGHT; - SHOW = true; + for (String info : DefaultConfigUtils.DEFAULT_INFOS) { + INFOS_INSTANCES.get(info).setOn(true); + } TOGGLE_INFO_KEY = KeyUtils.registerToggleInfo(DefaultConfigUtils.TOGGLE_INFO_KEYCODE); SHOW_MENU_KEY = KeyUtils.registerShowMenu(DefaultConfigUtils.SHOW_MENU_KEYCODE); + + POSITION = DefaultConfigUtils.POSITION; + SHOW = DefaultConfigUtils.SHOW; } public static void useDefaultOrderedInfos() { @@ -63,10 +60,10 @@ public static void useUserConfig(){ } } - POSITION = config.getPosition(); - SHOW = config.getShow(); - TOGGLE_INFO_KEY = KeyUtils.registerToggleInfo(config.getToggleKeyCode()); SHOW_MENU_KEY = KeyUtils.registerShowMenu(config.getShowMenuKeyCode()); + + POSITION = config.getPosition(); + SHOW = config.getShow(); } } diff --git a/src/client/java/dev/quickinfos/infos/FPS.java b/src/client/java/dev/quickinfos/infos/FPS.java new file mode 100644 index 0000000..f396067 --- /dev/null +++ b/src/client/java/dev/quickinfos/infos/FPS.java @@ -0,0 +1,18 @@ +package dev.quickinfos.infos; + +import net.minecraft.client.MinecraftClient; +import org.jetbrains.annotations.NotNull; + +public class FPS extends Info { + + @Override + public String getHumanReadableName() { + return "FPS"; + } + + @Override + public String render(@NotNull MinecraftClient client) { + return String.format("%d FPS", client.getCurrentFps()); + } + +} diff --git a/src/client/java/dev/quickinfos/infos/Ping.java b/src/client/java/dev/quickinfos/infos/Ping.java new file mode 100644 index 0000000..37e8972 --- /dev/null +++ b/src/client/java/dev/quickinfos/infos/Ping.java @@ -0,0 +1,35 @@ +package dev.quickinfos.infos; + +import dev.quickinfos.exceptions.CannotRenderInfoException; +import dev.quickinfos.utils.StaticUtils; +import net.minecraft.client.MinecraftClient; +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; +import java.util.UUID; + +public class Ping extends Info { + + @Override + public String getHumanReadableName() { + return "Ping"; + } + + @Override + public String render(@NotNull MinecraftClient client) { + if (client.getNetworkHandler() == null) + return StaticUtils.NONE_INFO_CALCULATED; + + if (client.player == null) + throw new CannotRenderInfoException(this); + + try { + UUID uuid = client.player.getUuid(); + return String.format("%dms", Objects.requireNonNull(client.getNetworkHandler().getPlayerListEntry(uuid)).getLatency()); + } + catch (Throwable e) { + throw new CannotRenderInfoException(this); + } + } + +} diff --git a/src/client/java/dev/quickinfos/infos/TargetedEntity.java b/src/client/java/dev/quickinfos/infos/TargetedEntity.java new file mode 100644 index 0000000..917efcf --- /dev/null +++ b/src/client/java/dev/quickinfos/infos/TargetedEntity.java @@ -0,0 +1,27 @@ +package dev.quickinfos.infos; + +import dev.quickinfos.exceptions.CannotRenderInfoException; +import dev.quickinfos.utils.PlayerUtils; +import dev.quickinfos.utils.StaticUtils; +import net.minecraft.client.MinecraftClient; +import net.minecraft.util.hit.EntityHitResult; +import org.jetbrains.annotations.NotNull; + +public class TargetedEntity extends Info { + + @Override + public String getHumanReadableName() { + return "Targeted Entity"; + } + + @Override + public String render(@NotNull MinecraftClient client) { + if (client.player == null || client.world == null) + throw new CannotRenderInfoException(this); + + EntityHitResult targetedEntity = PlayerUtils.getTargetedEntityInRange(client.player); + return targetedEntity != null ? String.format("Target %s", targetedEntity.getEntity().getName()) : + StaticUtils.NONE_INFO_CALCULATED; + } + +} diff --git a/src/client/java/dev/quickinfos/infos/TargetedEntityCoordinates.java b/src/client/java/dev/quickinfos/infos/TargetedEntityCoordinates.java new file mode 100644 index 0000000..fb02f00 --- /dev/null +++ b/src/client/java/dev/quickinfos/infos/TargetedEntityCoordinates.java @@ -0,0 +1,32 @@ +package dev.quickinfos.infos; + +import dev.quickinfos.exceptions.CannotRenderInfoException; +import dev.quickinfos.utils.PlayerUtils; +import dev.quickinfos.utils.StaticUtils; +import net.minecraft.client.MinecraftClient; +import net.minecraft.util.hit.EntityHitResult; +import net.minecraft.util.math.Vec3d; +import org.jetbrains.annotations.NotNull; + +public class TargetedEntityCoordinates extends Info { + + @Override + public String getHumanReadableName() { + return "Targeted Entity's Coordinates"; + } + + @Override + public String render(@NotNull MinecraftClient client) { + if (client.player == null) + throw new CannotRenderInfoException(this); + + EntityHitResult targetedEntity = PlayerUtils.getTargetedEntityInRange(client.player); + + if(targetedEntity == null) + return StaticUtils.NONE_INFO_CALCULATED; + + Vec3d pos = targetedEntity.getPos(); + return String.format("Target at %f / %f / %f", pos.getX(), pos.getY(), pos.getZ()); + } + +} diff --git a/src/client/java/dev/quickinfos/screen/Dimension.java b/src/client/java/dev/quickinfos/screen/Dimension.java new file mode 100644 index 0000000..6e21b1c --- /dev/null +++ b/src/client/java/dev/quickinfos/screen/Dimension.java @@ -0,0 +1,35 @@ +package dev.quickinfos.screen; + +public class Dimension { + private final int x; + private final int y; + private final int width; + private final int height; + + public Dimension(int x, int y) { + this(x, y, 0, 0); + } + + public Dimension(int x, int y, int width, int height) { + this.x = x; + this.y = y; + this.width = width; + this.height = height; + } + + public int getHeight() { + return height; + } + + public int getWidth() { + return width; + } + + public int getY() { + return y; + } + + public int getX() { + return x; + } +} diff --git a/src/client/java/dev/quickinfos/screen/QuickInfosScreen.java b/src/client/java/dev/quickinfos/screen/QuickInfosScreen.java index 694ece6..5b9fc30 100644 --- a/src/client/java/dev/quickinfos/screen/QuickInfosScreen.java +++ b/src/client/java/dev/quickinfos/screen/QuickInfosScreen.java @@ -4,9 +4,9 @@ import dev.quickinfos.config.ConfigManager; import dev.quickinfos.enums.Positions; import dev.quickinfos.infos.Info; +import dev.quickinfos.utils.ScreenUtils; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.gui.widget.ButtonWidget; import net.minecraft.text.Text; import java.util.ArrayList; @@ -14,12 +14,20 @@ public class QuickInfosScreen extends Screen { public ArrayList upDownWidgets = new ArrayList<>(); + public static final Dimension TITLE_DIMENSION = new Dimension(40, 10); + public static final Dimension SUBTITLE_DIMENSION = new Dimension(40, TITLE_DIMENSION.getY() + 10); + public static final Dimension SHOW_BUTTON_DIMENSION = new Dimension(SUBTITLE_DIMENSION.getX(), SUBTITLE_DIMENSION.getY() + 15, 160, 20); + public static final Dimension POSITION_BUTTON_DIMENSION = new Dimension(SHOW_BUTTON_DIMENSION.getX() + SHOW_BUTTON_DIMENSION.getWidth() + 10, SHOW_BUTTON_DIMENSION.getY(), SHOW_BUTTON_DIMENSION.getWidth() - 10, SHOW_BUTTON_DIMENSION.getHeight()); + public static final Dimension INFO_LIST_DIMENSION = new Dimension(SHOW_BUTTON_DIMENSION.getX(), POSITION_BUTTON_DIMENSION.getY() + 25, 320, SHOW_BUTTON_DIMENSION.getHeight()); + public static final int INFO_LIST_MARGIN = 20; + public QuickInfosScreen(Text title) { super(title); } @Override public void init() { + createShowButton(); createPositionButton(); refreshUpDownList(); } @@ -27,8 +35,8 @@ public void init() { @Override public void render(DrawContext context, int mouseX, int mouseY, float delta) { super.render(context, mouseX, mouseY, delta); - context.drawText(this.textRenderer, "Quick infos menu", 40, 40 - this.textRenderer.fontHeight - 10, 0xFFFFFFFF, true); - context.drawText(this.textRenderer, "Checkout Minecraft default controls menu for keybindings", 40, 60 - this.textRenderer.fontHeight - 10, 0xFFFFFFFF, true); + context.drawText(this.textRenderer, "Quick infos menu (This screen will changed in the next mod version)", TITLE_DIMENSION.getX(), TITLE_DIMENSION.getY(), 0xFFFFFFFF, true); + context.drawText(this.textRenderer, "Checkout Minecraft default controls menu for keybindings", SUBTITLE_DIMENSION.getX(), SUBTITLE_DIMENSION.getY(), 0xFFFFFFFF, true); } @Override @@ -40,14 +48,6 @@ public void close() { } } - public String buildMessage(Info info){ - return String.format("%s : %s", info.getHumanReadableName(), info.isOn() ? "ON" : "OFF"); - } - - public String buildMessage(Positions position){ - return String.format("Info position : %s", position.toString().replace("_", " ")); - } - public void onActivate(UpDownWidget upDownWidget) { Info info = upDownWidget.getInfo(); info.setOn(!info.isOn()); @@ -73,39 +73,29 @@ private void move(UpDownWidget upDownWidget, boolean up) { } private void refreshUpDownList(){ - if(!upDownWidgets.isEmpty()) { - for(UpDownWidget widget : upDownWidgets){ - this.remove(widget.getUp()); - this.remove(widget.getCenter()); - this.remove(widget.getDown()); - } - upDownWidgets.clear(); - } - int y = 100; + int y = QuickInfosScreen.INFO_LIST_DIMENSION.getY(); + upDownWidgets.forEach(widget -> widget.getWidgets().forEach(this::remove)); + upDownWidgets.clear(); for(Info orderedInfo : Singleton.ORDERED_INFOS){ - upDownWidgets.add(new UpDownWidget(orderedInfo, 40, y, 320, 20, this)); - y+= 22; - } - for(UpDownWidget widget : upDownWidgets){ - this.addDrawableChild(widget.getUp()); - this.addDrawableChild(widget.getCenter()); - this.addDrawableChild(widget.getDown()); + upDownWidgets.add(new UpDownWidget(orderedInfo, QuickInfosScreen.INFO_LIST_DIMENSION.getX(), y, QuickInfosScreen.INFO_LIST_DIMENSION.getWidth(), QuickInfosScreen.INFO_LIST_DIMENSION.getHeight(),this)); + y+= QuickInfosScreen.INFO_LIST_MARGIN; } + upDownWidgets.forEach(widget -> widget.getWidgets().forEach(this::addDrawableChild)); + } + + private void createPositionButton() { + this.addDrawableChild(ScreenUtils.createButton(Singleton.POSITION, () -> { + switch (Singleton.POSITION){ + case TOP_RIGHT -> Singleton.POSITION = Positions.BOTTOM_RIGHT; + case BOTTOM_RIGHT -> Singleton.POSITION = Positions.BOTTOM_LEFT; + case BOTTOM_LEFT -> Singleton.POSITION = Positions.TOP_LEFT; + case TOP_LEFT -> Singleton.POSITION = Positions.TOP_RIGHT; + } + }, QuickInfosScreen.POSITION_BUTTON_DIMENSION.getX(), QuickInfosScreen.POSITION_BUTTON_DIMENSION.getY(), QuickInfosScreen.POSITION_BUTTON_DIMENSION.getWidth(), QuickInfosScreen.POSITION_BUTTON_DIMENSION.getHeight())); } - private void createPositionButton(){ - ButtonWidget posButton = ButtonWidget.builder(Text.of(buildMessage(Singleton.POSITION)), button -> { - switch (Singleton.POSITION){ - case TOP_RIGHT -> Singleton.POSITION = Positions.BOTTOM_RIGHT; - case BOTTOM_RIGHT -> Singleton.POSITION = Positions.BOTTOM_LEFT; - case BOTTOM_LEFT -> Singleton.POSITION = Positions.TOP_LEFT; - case TOP_LEFT -> Singleton.POSITION = Positions.TOP_RIGHT; - } - button.setMessage(Text.of(buildMessage(Singleton.POSITION))); - }) - .dimensions(40, 65, 160, 20) - .build(); - this.addDrawableChild(posButton); + private void createShowButton(){ + this.addDrawableChild(ScreenUtils.createButton("Show/Hide", () -> Singleton.SHOW = !Singleton.SHOW, QuickInfosScreen.SHOW_BUTTON_DIMENSION.getX(), QuickInfosScreen.SHOW_BUTTON_DIMENSION.getY(), QuickInfosScreen.SHOW_BUTTON_DIMENSION.getWidth(), QuickInfosScreen.SHOW_BUTTON_DIMENSION.getHeight())); } } diff --git a/src/client/java/dev/quickinfos/screen/UpDownWidget.java b/src/client/java/dev/quickinfos/screen/UpDownWidget.java index b40c400..7a3c142 100644 --- a/src/client/java/dev/quickinfos/screen/UpDownWidget.java +++ b/src/client/java/dev/quickinfos/screen/UpDownWidget.java @@ -1,8 +1,10 @@ package dev.quickinfos.screen; import dev.quickinfos.infos.Info; +import dev.quickinfos.utils.ScreenUtils; import net.minecraft.client.gui.widget.ButtonWidget; -import net.minecraft.text.Text; + +import java.util.LinkedList; public class UpDownWidget { private final Info info; @@ -13,36 +15,18 @@ public class UpDownWidget { public UpDownWidget(Info info, int x, int y, int width, int height, QuickInfosScreen screen) { this.info = info; + int square = height; - this.up = ButtonWidget.builder(Text.of("↑"), button -> screen.onMoveUp(this)) - .dimensions(x, y, height, height) - .build(); - - this.center = ButtonWidget.builder(Text.of(screen.buildMessage(info)), button -> { - screen.onActivate(this); - button.setMessage(Text.of(screen.buildMessage(info))); - }) - .dimensions(x+width/8, y, 3*width/4, height) - .build(); - - this.down = ButtonWidget.builder(Text.of("↓"), button -> screen.onMoveDown(this)) - .dimensions(x+width-height, y, height, height) - .build(); + this.up = ScreenUtils.createButton("↑", () -> screen.onMoveUp(this), x, y, square, square); + this.center = ScreenUtils.createButton(info, () -> screen.onActivate(this),x+width/8, y, 3*width/4, height); + this.down = ScreenUtils.createButton("↓", () -> screen.onMoveDown(this), x+width-height, y, square, square); } public Info getInfo() { return info; } - public ButtonWidget getUp() { - return up; - } - - public ButtonWidget getCenter() { - return center; - } - - public ButtonWidget getDown() { - return down; + public LinkedList getWidgets() { + return new LinkedList<>() { { add(up); add(center); add(down); } }; } } diff --git a/src/client/java/dev/quickinfos/utils/DefaultConfigUtils.java b/src/client/java/dev/quickinfos/utils/DefaultConfigUtils.java index a45ba23..86c810e 100644 --- a/src/client/java/dev/quickinfos/utils/DefaultConfigUtils.java +++ b/src/client/java/dev/quickinfos/utils/DefaultConfigUtils.java @@ -1,8 +1,22 @@ package dev.quickinfos.utils; +import dev.quickinfos.enums.Positions; +import dev.quickinfos.infos.Coordinates; +import dev.quickinfos.infos.CurrentBiome; +import dev.quickinfos.infos.FacingDirection; import org.lwjgl.glfw.GLFW; public class DefaultConfigUtils { + public static Positions POSITION = Positions.TOP_RIGHT; + public static boolean SHOW = true; + public static int SHOW_MENU_KEYCODE = GLFW.GLFW_KEY_M; public static int TOGGLE_INFO_KEYCODE = GLFW.GLFW_KEY_K; + public static int NONE_KEY_IF_ERROR = GLFW.GLFW_KEY_UNKNOWN; + + public static String[] DEFAULT_INFOS = new String[]{ + Coordinates.class.getName(), + CurrentBiome.class.getName(), + FacingDirection.class.getName() + }; } diff --git a/src/client/java/dev/quickinfos/utils/ExitUtils.java b/src/client/java/dev/quickinfos/utils/ExitUtils.java new file mode 100644 index 0000000..e88b0c5 --- /dev/null +++ b/src/client/java/dev/quickinfos/utils/ExitUtils.java @@ -0,0 +1,6 @@ +package dev.quickinfos.utils; + +public class ExitUtils { + public static int PROPER_EXIT = 0; + public static int ERROR_IN_OPENED_SCREEN_EXIT = 1; +} diff --git a/src/client/java/dev/quickinfos/utils/KeyUtils.java b/src/client/java/dev/quickinfos/utils/KeyUtils.java index 6ee6312..496ddbe 100644 --- a/src/client/java/dev/quickinfos/utils/KeyUtils.java +++ b/src/client/java/dev/quickinfos/utils/KeyUtils.java @@ -15,11 +15,20 @@ public static KeyBinding registerShowMenu(int keyCode){ } public static KeyBinding registerKeyBindingInMinecraftControls(String translationKey, int keyCode){ - return KeyBindingHelper.registerKeyBinding(new KeyBinding( - translationKey, - InputUtil.Type.KEYSYM, - keyCode, - StaticUtils.QUICKINFOS_CATEGORY_CONTROLS - )); + try { + return KeyBindingHelper.registerKeyBinding(new KeyBinding( + translationKey, + InputUtil.Type.KEYSYM, + keyCode, + StaticUtils.QUICKINFOS_CATEGORY_CONTROLS + )); + } catch (Throwable e) { + return KeyBindingHelper.registerKeyBinding(new KeyBinding( + translationKey, + InputUtil.Type.KEYSYM, + DefaultConfigUtils.NONE_KEY_IF_ERROR, + StaticUtils.QUICKINFOS_CATEGORY_CONTROLS + )); + } } } diff --git a/src/client/java/dev/quickinfos/utils/PlayerUtils.java b/src/client/java/dev/quickinfos/utils/PlayerUtils.java index de5fbc1..00631a6 100644 --- a/src/client/java/dev/quickinfos/utils/PlayerUtils.java +++ b/src/client/java/dev/quickinfos/utils/PlayerUtils.java @@ -1,6 +1,7 @@ package dev.quickinfos.utils; import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.util.hit.EntityHitResult; import net.minecraft.util.hit.HitResult; import net.minecraft.util.hit.BlockHitResult; @@ -13,4 +14,9 @@ public static BlockHitResult getTargetedBlockInRange(ClientPlayerEntity player, HitResult hitResult = getTargetedObjectInRange(player, includeFluids); return hitResult.getType() == HitResult.Type.BLOCK ? (BlockHitResult) hitResult : null; } + + public static EntityHitResult getTargetedEntityInRange(ClientPlayerEntity player){ + HitResult hitResult = getTargetedObjectInRange(player, false); + return hitResult.getType() == HitResult.Type.ENTITY ? (EntityHitResult) hitResult : null; + } } diff --git a/src/client/java/dev/quickinfos/utils/ScreenUtils.java b/src/client/java/dev/quickinfos/utils/ScreenUtils.java index 6f5bff9..7098d1a 100644 --- a/src/client/java/dev/quickinfos/utils/ScreenUtils.java +++ b/src/client/java/dev/quickinfos/utils/ScreenUtils.java @@ -1,7 +1,10 @@ package dev.quickinfos.utils; +import dev.quickinfos.enums.Positions; +import dev.quickinfos.infos.Info; import dev.quickinfos.screen.QuickInfosScreen; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.widget.ButtonWidget; import net.minecraft.text.Text; import org.jetbrains.annotations.NotNull; @@ -9,4 +12,32 @@ public class ScreenUtils { public static void openScreen(@NotNull MinecraftClient client){ client.send(() -> client.setScreen(new QuickInfosScreen(Text.empty()))); } + + public static String buildMessage(Info info){ + return String.format("%s : %s", info.getHumanReadableName(), info.isOn() ? "ON" : "OFF"); + } + + public static String buildMessage(Positions position){ + return String.format("Info position : %s", position.toString().replace("_", " ")); + } + + public static String buildMessage(Object object){ + if(object instanceof String string) { + return string; + } else if(object instanceof Info info){ + return buildMessage(info); + } else if(object instanceof Positions position){ + return buildMessage(position); + } + return "Unknown type for buildMessage"; + } + + public static ButtonWidget createButton(Object object, Runnable onClick, int x, int y, int width, int height){ + return ButtonWidget.builder(Text.of(ScreenUtils.buildMessage(object)), button -> { + onClick.run(); + button.setMessage(Text.of(buildMessage(object))); + }) + .dimensions(x, y, width, height) + .build(); + } }