diff --git a/AUTHORS b/AUTHORS index efded2ff2..452a59242 100644 --- a/AUTHORS +++ b/AUTHORS @@ -22,5 +22,6 @@ Cyberslas (littlej54192) Tovlyn Florian Kostenzer (123FLO321) Ben K. (Xyvoracle) +Zuo Fei (Goldenfield192) See sounds/CREDITS for links to the audio sources and their licensing info diff --git a/DevelopmentNotes/immersiverailroading-1.11.md b/DevelopmentNotes/immersiverailroading-1.11.md new file mode 100644 index 000000000..ff18fd142 --- /dev/null +++ b/DevelopmentNotes/immersiverailroading-1.11.md @@ -0,0 +1,61 @@ +## New Features + +### **Configuration** +- **Goldenfield192**: + - Added `stockDropInCreativeMode` in `Config/Debug` to facilitate world building. + - Added `excludeStandaloneWagons` in `Config/Debug` to reduce chunk loading costs (works with `keepStockLoaded`). + - Added `TrainsIgnoreBlocks` in `Config/Damage` to prevent destruction to specific block types (use registry names shown in the F3 panel). + - Added `TrackRenderDistance` in `Config/Graphics` to customize the maximum track render distance for values above 256. + - Added `DisableLightTextureRender` in `Config/Graphics` to disable flare rendering (Dynamic light is preserved if OptiFine is installed). + - Added `powerUnit` and `forceUnit` in `Config/Graphics` to customize units used in GUI and item tooltips. + +### **Track** +- **cam72cam**: Golden spikes can now modify the height of `slope` tracks instead of being fixed at 1 block upwards. +- **Goldenfield192**: + - Updated golden spike behavior for horizontal direction—now uses arc length for `turn` and shadow length for `straight` and `slope`. + - Introduced the transfer table as a new track type. + - Rewrote curve generation to prevent overlapping track segments. + - Added a new method for defining tracks (documented in [GitHub Gist](https://gist.github.com/Goldenfield192/70bc96cce31cd1a784868fbe302073b5)). + +### **Stock** +- **poizzy & cam72cam**: Stock parts can now be made transparent by adding `ALPHA`. +- **FnordyCave**: Added `snow_layers` (integer property) under `properties` in stock definitions to define reserved snow layers on tracks after cleaning. +- **SebastianD334**: + - Added `power_w`, `power_kw`, `power_ps` (Metric horsepower), and `power_hp` (Imperial horsepower) as alternatives for locomotive power definitions (legacy `horsepower` is equivalent to `power_hp` and is **no longer recommended and may not be supported by newer versions**). + - Added `tractive_effort_kn` and `tractive_effort_n` as alternatives for locomotive tractive effort definitions. + - Added `max_pressure_bar`, `max_pressure_kpa`, and `max_pressure_psi` as alternatives for steam locomotive pressure definitions (legacy `max_psi` is equivalent to `max_pressure_psi` and is **no longer recommended and may not be supported by newer versions**). +- **Goldenfield192**: + - Added `range_min` and `range_max` to the animatrix definition block to align with `RANGE_[min]_[max]` in control definitions. + - Added `revertDirection` to light definitions to specify if the light's direction is reversed (e.g., a front-facing light at the stock's tail). + - Added support for defining light working directions using `FORWARD` or `REVERSE`. + - Added `fuel_override` under `properties` to customize diesel locomotive fuels (documented in [GitHub PR #1577](https://github.com/TeamOpenIndustry/ImmersiveRailroading/pull/1577)). + +### **Translations** +- **Goldenfield192**: + - Stock labels can now be translated using the key `part.immersiverailroading:control.[name]` for [defaults](https://github.com/TeamOpenIndustry/ImmersiveRailroading/blob/master/src/main/java/cam72cam/immersiverailroading/library/ModelComponentType.java#L141) and `label.immersiverailroading:[stock_type].[stock_definition_name].[label]` or `label.immersiverailroading:[label]` for other `LABEL`s. + - Example: For a diesel locomotive defined as `test` with a control `WIDGET_1_LABEL_test`, IR will first search for `label.immersiverailroading:diesel.test.test`, then `label.immersiverailroading:test` if the first one not found. + - The first method is recommended for better compatibility. + - Added numerous new translation entries for GUI elements. + +### **Commands** +- **cam72cam**: Removed `/immersiverailroading reload` and added `/immersiverailroading cargoFill [radius: Integer]` to fill all stocks in the specified radius with the item held in the player's main hand (clears all stocks if the hand is empty). + - Default radius is 2. + +### **GUI** +- **SebastianD334 & Goldenfield192**: Added support for defining decimal digits in GUI definitions using `state.[name].X`. + - Example: `stat.speed.3` will display speed with 3 decimal digits. + +## Fixes and Refactoring + +- **DarkRaider**: + - Updated `clearArea` exception logic to avoid manual cleaning when placing tracks in snow. + - Adjusted grade crossing math to ensure symmetrical heights on both sides of the track. +- **Goldenfield192**: + - Fixed draggable widgets on unfinished stocks. + - Corrected particle emitter offsets, especially during high-speed movement. + - Resolved element overlapping in the track blueprint GUI. + - Fixed incorrect boiler machine model offsets. + - Addressed diesel throttle glitches when setting non-notched values via dragging or augmentation. + - Remapped non-existent materials in `firefly` and `iron_duke` to prevent unnecessary logs. + - Ensured stocks are removed when their pack is unloaded. + - Expanded paintbrush GUI button width to accommodate new translations. \ No newline at end of file diff --git a/src/main/java/cam72cam/immersiverailroading/Config.java b/src/main/java/cam72cam/immersiverailroading/Config.java index 19b9a195c..a70eb6016 100644 --- a/src/main/java/cam72cam/immersiverailroading/Config.java +++ b/src/main/java/cam72cam/immersiverailroading/Config.java @@ -60,6 +60,11 @@ public static class ConfigDamage { @Comment("Trains should break block") public static boolean TrainsBreakBlocks = true; + @Comment("Which block is reserved if TrainsBreakBlocks is true") + public static String[] TrainsIgnoreBlocks = new String[]{ + "littletiles:blocklittletiles" + }; + @Comment("How hard are blocks to break by rolling stock?") @Range(min = 0, max = 500) public static int blockHardness = 50; @@ -257,6 +262,9 @@ public static class ConfigDebug { @Comment("Keep rolling stock loaded even when it is not moving") public static boolean keepStockLoaded = true; + @Comment("Exclude unattached wagons from chunk loading when keepStockLoaded is true") + public static boolean excludeStandaloneWagons = false; + @Comment( "Print extra chunk loading info" ) public static boolean debugLog = false; diff --git a/src/main/java/cam72cam/immersiverailroading/ConfigGraphics.java b/src/main/java/cam72cam/immersiverailroading/ConfigGraphics.java index 068cc2ea5..47d25b205 100644 --- a/src/main/java/cam72cam/immersiverailroading/ConfigGraphics.java +++ b/src/main/java/cam72cam/immersiverailroading/ConfigGraphics.java @@ -1,8 +1,6 @@ package cam72cam.immersiverailroading; -import cam72cam.immersiverailroading.library.PressureDisplayType; -import cam72cam.immersiverailroading.library.SpeedDisplayType; -import cam72cam.immersiverailroading.library.TemperatureDisplayType; +import cam72cam.immersiverailroading.library.unit.*; import cam72cam.mod.config.ConfigFile.Comment; import cam72cam.mod.config.ConfigFile.Name; import cam72cam.mod.render.OptiFine; @@ -22,15 +20,21 @@ public class ConfigGraphics { @Comment( "Self explanatory" ) public static boolean trainsOnTheBrain = true; - @Comment( "What unit to use for speedometer. (kmh, mph or ms)" ) + @Comment("What unit to display speed in (kmh, ms, mph)") public static SpeedDisplayType speedUnit = SpeedDisplayType.kmh; - @Comment("What units to display pressure in (psi, bar)") - public static PressureDisplayType pressureUnit = PressureDisplayType.psi; + @Comment("What unit to display pressure in (psi, kpa, bar)") + public static PressureDisplayType pressureUnit = PressureDisplayType.bar; - @Comment("What units to display pressure in (psi, bar)") + @Comment("What unit to display temperature in (celcius, kelvin, farenheit)") public static TemperatureDisplayType temperatureUnit = TemperatureDisplayType.celcius; + @Comment("What unit to display locomotive power in (w, kw, ps (metric horsepower), horsepower (imperial horsepower))") + public static PowerDisplayType powerUnit = PowerDisplayType.kw; + + @Comment("What unit to display locomotive traction force in (kn, n, lbf)") + public static ForceDisplayType forceUnit = ForceDisplayType.kn; + @Comment( "How long to keep textures in memory after they have left the screen (higher numbers = smoother game play, lower numbers = less GPU memory used)") @Range(min = 0, max = 100) public static int textureCacheSeconds = 30; @@ -68,7 +72,13 @@ public class ConfigGraphics { @Comment("Try to fake interior lighting for locomotives/passenger cars that are being ridden") public static boolean FakeInteriorLighting = true; + @Comment("Disable headlights' texture render") + public static boolean DisableLightTextureRender = false; + @Comment("The track's maximum visibility range") @Range(min = 256, max = 4096) public static double TrackRenderDistance = 256; + + @Comment("Should semi-transparent parts render? Disable this if you are experiencing problems with semi-transparent parts when using a Shader") + public static boolean RenderSemiTransparentParts = true; } diff --git a/src/main/java/cam72cam/immersiverailroading/IRCommand.java b/src/main/java/cam72cam/immersiverailroading/IRCommand.java index e3f29d909..afb5c813a 100644 --- a/src/main/java/cam72cam/immersiverailroading/IRCommand.java +++ b/src/main/java/cam72cam/immersiverailroading/IRCommand.java @@ -1,12 +1,19 @@ package cam72cam.immersiverailroading; +import cam72cam.immersiverailroading.entity.EntityCoupleableRollingStock; import cam72cam.immersiverailroading.entity.EntityRollingStock; +import cam72cam.immersiverailroading.entity.Freight; import cam72cam.immersiverailroading.registry.DefinitionManager; import cam72cam.mod.entity.Player; +import cam72cam.mod.entity.boundingbox.IBoundingBox; +import cam72cam.mod.item.ItemStack; +import cam72cam.mod.math.Vec3d; +import cam72cam.mod.math.Vec3i; import cam72cam.mod.text.Command; import cam72cam.mod.text.PlayerMessage; import cam72cam.mod.world.World; +import java.awt.*; import java.io.IOException; import java.util.Comparator; import java.util.List; @@ -32,13 +39,39 @@ public int getRequiredPermissionLevel() { @Override public boolean execute(Consumer sender, Optional player, String[] args) { - if (args.length != 1) { + if (args.length == 0) { return false; } - if (args[0].equals("reload")) { - ImmersiveRailroading.warn("Reloading Immersive Railroading definitions"); - DefinitionManager.initDefinitions(); - ImmersiveRailroading.info("Done reloading Immersive Railroading definitions"); + if (args[0].equals("cargoFill")) { + if (player.isPresent()) { + int distance = 2; + if (args.length > 1) { + try { + distance = Integer.parseInt(args[1]); + } catch (NumberFormatException e) { + sender.accept(PlayerMessage.direct("Invalid number " + args[1])); + return true; + } + } + IBoundingBox bb = player.get().getBounds().grow(new Vec3d(distance, 4, distance)); + List carsNearby = player.get().getWorld().getEntities((Freight stock) -> bb.intersects(stock.getBounds()), Freight.class); + ItemStack stack = player.get().getHeldItem(Player.Hand.PRIMARY); + + if (carsNearby.isEmpty()) { + sender.accept(PlayerMessage.direct("No rolling stock within range to fill")); + } + + for (Freight freight : carsNearby) { + sender.accept(PlayerMessage.direct(String.format("Filling %s@%s with %s", freight.getDefinition().name(), new Vec3i(freight.getPosition()), stack.getDisplayName()))); + for (int i = 0; i < freight.cargoItems.getSlotCount(); i++) { + if (stack.isEmpty() || freight.cargoItems.get(i).isEmpty()) { + freight.cargoItems.set(i, stack.copy()); + } + } + } + } else { + sender.accept(PlayerMessage.direct("This command is not supported for non-players (yet)")); + } return true; } diff --git a/src/main/java/cam72cam/immersiverailroading/entity/EntityCoupleableRollingStock.java b/src/main/java/cam72cam/immersiverailroading/entity/EntityCoupleableRollingStock.java index bd89aaf5a..3022c6cc2 100644 --- a/src/main/java/cam72cam/immersiverailroading/entity/EntityCoupleableRollingStock.java +++ b/src/main/java/cam72cam/immersiverailroading/entity/EntityCoupleableRollingStock.java @@ -100,6 +100,7 @@ public String toString() { @TagSync @TagField("hasElectricalPower") private boolean hasElectricalPower; + private boolean linkedToLocomotive; private boolean hadElectricalPower = false; private int gotElectricalPowerTick = -1; @@ -186,17 +187,23 @@ public void onTick() { if (this.getTickCount() % 5 == 0) { hasElectricalPower = false; - this.mapTrain(this, false, stock -> - hasElectricalPower = hasElectricalPower || - stock instanceof Locomotive && ((Locomotive) stock).providesElectricalPower() + linkedToLocomotive = false; + this.mapTrain(this, false, stock -> { + hasElectricalPower = hasElectricalPower || + stock instanceof Locomotive && ((Locomotive) stock).providesElectricalPower(); + linkedToLocomotive = linkedToLocomotive || stock instanceof Locomotive; + } ); } hadElectricalPower = hasElectricalPower(); if (this.getCurrentState() != null && !this.getCurrentState().atRest || ConfigDebug.keepStockLoaded) { - keepLoaded(); - } + //Then exclude stocks not linked to any locomotive + if (!ConfigDebug.excludeStandaloneWagons || this.linkedToLocomotive) { + keepLoaded(); + } + } slackFrontPercent = 0; slackRearPercent = 0; diff --git a/src/main/java/cam72cam/immersiverailroading/entity/EntityMoveableRollingStock.java b/src/main/java/cam72cam/immersiverailroading/entity/EntityMoveableRollingStock.java index 20c4e76f8..667bd7252 100644 --- a/src/main/java/cam72cam/immersiverailroading/entity/EntityMoveableRollingStock.java +++ b/src/main/java/cam72cam/immersiverailroading/entity/EntityMoveableRollingStock.java @@ -253,7 +253,7 @@ public void onTick() { for (Vec3i bp : state.trackToUpdate) { TileRailBase te = getWorld().getBlockEntity(bp, TileRailBase.class); if (te != null) { - te.cleanSnow(); + te.cleanSnow(this.getDefinition().getSnowLayers()); te.stockOverhead(this); } } diff --git a/src/main/java/cam72cam/immersiverailroading/entity/EntityRollingStock.java b/src/main/java/cam72cam/immersiverailroading/entity/EntityRollingStock.java index a7eb45a62..425c1914f 100644 --- a/src/main/java/cam72cam/immersiverailroading/entity/EntityRollingStock.java +++ b/src/main/java/cam72cam/immersiverailroading/entity/EntityRollingStock.java @@ -85,6 +85,7 @@ public String tryJoinWorld() { if (DefinitionManager.getDefinition(defID) == null) { String error = String.format("Missing definition %s, do you have all of the required resource packs?", defID); ImmersiveRailroading.error(error); + this.kill(); return error; } return null; @@ -108,8 +109,7 @@ public String getDefinitionID() { @Override public void onTick() { if (getWorld().isServer && this.getTickCount() % 5 == 0) { - EntityRollingStockDefinition def = DefinitionManager.getDefinition(defID); - if (def == null) { + if (DefinitionManager.getDefinition(defID) == null) { this.kill(); } } diff --git a/src/main/java/cam72cam/immersiverailroading/entity/Freight.java b/src/main/java/cam72cam/immersiverailroading/entity/Freight.java index 6d06e0406..b9d84abfb 100644 --- a/src/main/java/cam72cam/immersiverailroading/entity/Freight.java +++ b/src/main/java/cam72cam/immersiverailroading/entity/Freight.java @@ -158,13 +158,6 @@ protected void initContainerFilter() { @Override public double getWeight() { double fLoad = ConfigBalance.blockWeight * itemCount; - /* - for (int i = 0; i < cargoItems.getSlotCount(); i++) { - ItemStack item = Fuzzy.WOOD_PLANK.example(); - item.setCount(64); - cargoItems.set(i, item); - }*/ - fLoad = fLoad + super.getWeight(); return fLoad; } diff --git a/src/main/java/cam72cam/immersiverailroading/entity/HandCar.java b/src/main/java/cam72cam/immersiverailroading/entity/HandCar.java index c46315a2d..c61050523 100644 --- a/src/main/java/cam72cam/immersiverailroading/entity/HandCar.java +++ b/src/main/java/cam72cam/immersiverailroading/entity/HandCar.java @@ -27,7 +27,7 @@ public double getAppliedTractiveEffort(Speed speed) { } } // Same as diesel for now - double maxPower_W = this.getDefinition().getHorsePower(gauge) * 745.7d * passengers; + double maxPower_W = this.getDefinition().getWatt(gauge) * passengers; double efficiency = 0.82; // Similar to a *lot* of imperial references double speed_M_S = (Math.abs(speed.metric())/3.6); double maxPowerAtSpeed = maxPower_W * efficiency / Math.max(0.001, speed_M_S); diff --git a/src/main/java/cam72cam/immersiverailroading/entity/LocomotiveDiesel.java b/src/main/java/cam72cam/immersiverailroading/entity/LocomotiveDiesel.java index c4ba98780..d96ec72ff 100644 --- a/src/main/java/cam72cam/immersiverailroading/entity/LocomotiveDiesel.java +++ b/src/main/java/cam72cam/immersiverailroading/entity/LocomotiveDiesel.java @@ -16,8 +16,7 @@ import cam72cam.mod.fluid.FluidStack; import cam72cam.mod.serialization.TagField; -import java.util.List; -import java.util.OptionalDouble; +import java.util.*; public class LocomotiveDiesel extends Locomotive { @@ -161,7 +160,7 @@ public void setReverser(float newReverser) { @Override public double getAppliedTractiveEffort(Speed speed) { if (isRunning() && (getEngineTemperature() > 75 || !Config.isFuelRequired(gauge))) { - double maxPower_W = this.getDefinition().getHorsePower(gauge) * 745.7d; + double maxPower_W = this.getDefinition().getWatt(gauge); double efficiency = 0.82; // Similar to a *lot* of imperial references double speed_M_S = (Math.abs(speed.metric())/3.6); double maxPowerAtSpeed = maxPower_W * efficiency / Math.max(0.001, speed_M_S); @@ -221,9 +220,12 @@ public void onTick() { if (this.getLiquidAmount() > 0 && isRunning()) { float consumption = Math.abs(getThrottle()) + 0.05f; - float burnTime = BurnUtil.getBurnTime(this.getLiquid()); + float burnTime = getDefinition().getOverriddenFuels().getOrDefault(this.getLiquid(), 0); if (burnTime == 0) { - burnTime = 200; //Default to 200 for unregistered liquids + burnTime = BurnUtil.getBurnTime(this.getLiquid()); + } + if (burnTime == 0) { + burnTime = 200; } burnTime *= getDefinition().getFuelEfficiency()/100f; burnTime *= (Config.ConfigBalance.locoDieselFuelEfficiency / 100f); @@ -253,10 +255,11 @@ public void onTick() { setEngineTemperature(engineTemperature); } - + @Override public List getFluidFilter() { - return BurnUtil.burnableFluids(); + Set set = getDefinition().getOverriddenFuels().keySet(); + return set.isEmpty() ? BurnUtil.burnableFluids() : new ArrayList<>(set); } @Override diff --git a/src/main/java/cam72cam/immersiverailroading/entity/LocomotiveSteam.java b/src/main/java/cam72cam/immersiverailroading/entity/LocomotiveSteam.java index 9dff33b17..afe43db00 100644 --- a/src/main/java/cam72cam/immersiverailroading/entity/LocomotiveSteam.java +++ b/src/main/java/cam72cam/immersiverailroading/entity/LocomotiveSteam.java @@ -98,7 +98,7 @@ public double getAppliedTractiveEffort(Speed speed) { // This is terrible, but allows wheel slip for both legacy and updated hp vs te double traction_N = Math.max( this.getDefinition().getStartingTractionNewtons(gauge), - this.getDefinition().getHorsePower(gauge) * 375 / Math.max(Math.abs(speed.imperial()), 1.0) + this.getDefinition().getWatt(gauge) * 0.5 / Math.max(Math.abs(speed.imperial()), 1.0) ); if (Config.isFuelRequired(gauge)) { traction_N = traction_N / this.getDefinition().getMaxPSI(gauge) * this.getBoilerPressure(); @@ -286,7 +286,7 @@ public void onTick() { } // Pressure relief valve - int maxPSI = this.getDefinition().getMaxPSI(gauge); + int maxPSI = (int) this.getDefinition().getMaxPSI(gauge); pressureValve = boilerPressure > maxPSI; if (boilerPressure > maxPSI) { waterUsed += boilerPressure - maxPSI; diff --git a/src/main/java/cam72cam/immersiverailroading/entity/physics/SimulationState.java b/src/main/java/cam72cam/immersiverailroading/entity/physics/SimulationState.java index 8299c8fd2..821e3b406 100644 --- a/src/main/java/cam72cam/immersiverailroading/entity/physics/SimulationState.java +++ b/src/main/java/cam72cam/immersiverailroading/entity/physics/SimulationState.java @@ -286,7 +286,9 @@ public void calculateBlockCollisions(List blocksAlreadyBroken) { if (BlockUtil.isIRRail(config.world, bp)) { trackToUpdate.add(bp); } else { - if (Config.ConfigDamage.TrainsBreakBlocks && !BlockUtil.isIRRail(config.world, bp.up())) { + if (Config.ConfigDamage.TrainsBreakBlocks + && !BlockUtil.isWhitelisted(config.world, bp) + && !BlockUtil.isIRRail(config.world, bp.up())) { if (bp.y >= position.y - (position.y % 1)) { // Prevent it from breaking blocks under the pitched train (bb expanded) interferingBlocks.add(bp); interferingResistance += config.world.getBlockHardness(bp); diff --git a/src/main/java/cam72cam/immersiverailroading/gui/PaintBrushPicker.java b/src/main/java/cam72cam/immersiverailroading/gui/PaintBrushPicker.java index 4ece941b1..ad28534d3 100644 --- a/src/main/java/cam72cam/immersiverailroading/gui/PaintBrushPicker.java +++ b/src/main/java/cam72cam/immersiverailroading/gui/PaintBrushPicker.java @@ -59,29 +59,33 @@ public void onClick(String option) { } }.setVisible(true); - Slider zoom_slider = new Slider(screen, xtop + width, (int) (GUIHelpers.getScreenHeight()*0.75 - height), "Zoom: ", 0.1, 2, 1, true) { + Slider zoom_slider = new Slider(screen, xtop + width, (int) (GUIHelpers.getScreenHeight()*0.75 - height), + GuiText.SLIDER_ZOOM.toString(), 0.1, 2, 1, true) { @Override public void onSlider() { zoom = this.getValue(); } }; - width = 80; - Button random = new Button(screen, GUIHelpers.getScreenWidth() / 2 - width, ytop, width, height, "Random") { + width = 100; + Button random = new Button(screen, GUIHelpers.getScreenWidth() / 2 - width, ytop, width, height, + GuiText.SELECTOR_PAINTBRUSH_RANDOM.toString()) { @Override public void onClick(Player.Hand hand) { variant = ItemPaintBrush.nextRandomTexture(stock, variant); } }; - Button apply = new Button(screen, GUIHelpers.getScreenWidth() / 2 - width, (int) (GUIHelpers.getScreenHeight()*0.75 - height*2), width, height, "Apply to Stock") { + Button apply = new Button(screen, GUIHelpers.getScreenWidth() / 2 - width, (int) (GUIHelpers.getScreenHeight()*0.75 - height*2), + width, height, GuiText.SELECTOR_PAINTBRUSH_TO_STOCK.toString()) { @Override public void onClick(Player.Hand hand) { new ItemPaintBrush.PaintBrushPacket(stock, PaintBrushMode.GUI, variant, false).sendToServer(); screen.close(); } }; - Button apply_connected = new Button(screen, GUIHelpers.getScreenWidth() / 2 - width, (int) (GUIHelpers.getScreenHeight()*0.75 - height), width, height, "Apply to Train") { + Button apply_connected = new Button(screen, GUIHelpers.getScreenWidth() / 2 - width, (int) (GUIHelpers.getScreenHeight()*0.75 - height), + width, height, GuiText.SELECTOR_PAINTBRUSH_TO_TRAIN.toString()) { @Override public void onClick(Player.Hand hand) { new ItemPaintBrush.PaintBrushPacket(stock, PaintBrushMode.GUI, variant, true).sendToServer(); diff --git a/src/main/java/cam72cam/immersiverailroading/gui/TrackGui.java b/src/main/java/cam72cam/immersiverailroading/gui/TrackGui.java index 86ad89606..c57ee7b16 100644 --- a/src/main/java/cam72cam/immersiverailroading/gui/TrackGui.java +++ b/src/main/java/cam72cam/immersiverailroading/gui/TrackGui.java @@ -334,7 +334,8 @@ public void onClick(Player.Hand hand) { }; ytop += height; - Slider zoom_slider = new Slider(screen, GUIHelpers.getScreenWidth() / 2 - 150, (int) (GUIHelpers.getScreenHeight()*0.75 - height), "Zoom: ", 0.1, 2, 1, true) { + Slider zoom_slider = new Slider(screen, GUIHelpers.getScreenWidth() / 2 - 150, (int) (GUIHelpers.getScreenHeight()*0.75 - height), + GuiText.SLIDER_ZOOM.toString(), 0.1, 2, 1, true) { @Override public void onSlider() { zoom = this.getValue(); diff --git a/src/main/java/cam72cam/immersiverailroading/gui/components/ListSelector.java b/src/main/java/cam72cam/immersiverailroading/gui/components/ListSelector.java index 43494b5fb..894e486d7 100644 --- a/src/main/java/cam72cam/immersiverailroading/gui/components/ListSelector.java +++ b/src/main/java/cam72cam/immersiverailroading/gui/components/ListSelector.java @@ -1,6 +1,6 @@ package cam72cam.immersiverailroading.gui.components; -import cam72cam.immersiverailroading.gui.TrackGui; +import cam72cam.immersiverailroading.library.GuiText; import cam72cam.mod.entity.Player; import cam72cam.mod.gui.helpers.GUIHelpers; import cam72cam.mod.gui.screen.Button; @@ -34,20 +34,20 @@ public ListSelector(IScreenBuilder screen, int xOff, int width, int height, T cu this.rawOptions = rawOptions; this.currentValue = currentValue; visible = false; + page = 0; int xtop = -GUIHelpers.getScreenWidth() / 2 + xOff; int ytop = -GUIHelpers.getScreenHeight() / 4; search = new TextField(screen, xtop, ytop, width - 1, height); - pagination = new Button(screen, xtop, ytop + height, width + 1, height, "Page") { + pagination = new Button(screen, xtop, ytop + height, width + 1, height, "") { @Override public void onClick(Player.Hand hand) { page += hand == Player.Hand.PRIMARY ? 1 : -1; updateSearch(search.getText()); } }; - page = 0; pageSize = Math.max(1, GUIHelpers.getScreenHeight() / height - 2); @@ -109,7 +109,7 @@ void updateSearch(String search) { page = nPages - 1; } - pagination.setText(String.format("Page %s of %s", page + 1, Math.max(1, nPages))); + pagination.setText(GuiText.SELECTOR_PAGE.toString(page + 1, Math.max(1, nPages))); options.forEach(b -> { b.setText(""); diff --git a/src/main/java/cam72cam/immersiverailroading/gui/overlay/GuiBuilder.java b/src/main/java/cam72cam/immersiverailroading/gui/overlay/GuiBuilder.java index 8e30daa2f..8b381207f 100644 --- a/src/main/java/cam72cam/immersiverailroading/gui/overlay/GuiBuilder.java +++ b/src/main/java/cam72cam/immersiverailroading/gui/overlay/GuiBuilder.java @@ -364,8 +364,26 @@ private void render(EntityRollingStock stock, RenderState state, int maxx, int m if (text != null) { String out = text; for (Stat stat : Stat.values()) { - if (out.contains(stat.toString())) { - out = out.replace(stat.toString(), stat.getValue(stock)); + String statStr = stat.toString(); + int index = out.indexOf(statStr); + if (index == -1 /* !contain() */ ) continue; + + if (stat.hasDecimalSetting()) { + int decimalIndex = index + statStr.length(); + + if (decimalIndex + 1 < out.length() // Check if we have both dot and number + && out.charAt(decimalIndex) == '.' + && Character.isDigit(out.charAt(decimalIndex + 1))) { + // [stat].[digit(0~5)] + int dig = Character.getNumericValue(out.charAt(decimalIndex + 1)); + dig = Math.min(5, Math.max(0, dig)); + + out = out.replace(out.substring(index, decimalIndex + 2), stat.getValue(stock, dig)); + } else { + out = out.replace(statStr, stat.getValue(stock)); + } + } else { + out = out.replace(statStr, stat.getValue(stock)); } } for (GuiText label : new GuiText[]{GuiText.LABEL_THROTTLE, GuiText.LABEL_REVERSER, GuiText.LABEL_BRAKE}) { diff --git a/src/main/java/cam72cam/immersiverailroading/gui/overlay/Stat.java b/src/main/java/cam72cam/immersiverailroading/gui/overlay/Stat.java index 6f5fdde3b..10640f08a 100644 --- a/src/main/java/cam72cam/immersiverailroading/gui/overlay/Stat.java +++ b/src/main/java/cam72cam/immersiverailroading/gui/overlay/Stat.java @@ -28,8 +28,15 @@ public enum Stat { UNITS_CARGO_FILL, ; + private static final String[] formats = {"%.0f", "%.1f", "%.2f", "%.3f", "%。4f", "%.5f"}; + public String getValue(EntityRollingStock stock) { + return this.getValue(stock, getDefaultDecimal()); + } + + public String getValue(EntityRollingStock stock, int digit) { Float temp = null; + String format = formats[digit]; switch (this) { case SPEED: @@ -37,11 +44,11 @@ public String getValue(EntityRollingStock stock) { Speed speed = ((EntityMoveableRollingStock) stock).getCurrentSpeed(); switch (ConfigGraphics.speedUnit) { case mph: - return String.format("%.2f", Math.abs(speed.imperial())); + return String.format(format, Math.abs(speed.imperial())); case ms: - return String.format("%.2f", Math.abs(speed.metersPerSecond())); + return String.format(format, Math.abs(speed.metersPerSecond())); case kmh: - return String.format("%.2f", Math.abs(speed.metric())); + return String.format(format, Math.abs(speed.metric())); } } return ""; @@ -50,11 +57,11 @@ public String getValue(EntityRollingStock stock) { Speed speed = ((Locomotive)stock).getDefinition().getMaxSpeed(stock.gauge); switch (ConfigGraphics.speedUnit) { case mph: - return String.format("%.0f", Math.abs(speed.imperial())); + return String.format(format, Math.abs(speed.imperial())); case ms: - return String.format("%.0f", Math.abs(speed.metersPerSecond())); + return String.format(format, Math.abs(speed.metersPerSecond())); case kmh: - return String.format("%.0f", Math.abs(speed.metric())); + return String.format(format, Math.abs(speed.metric())); } } return ""; @@ -62,12 +69,12 @@ public String getValue(EntityRollingStock stock) { return ConfigGraphics.speedUnit.toUnitString(); case LIQUID: return stock instanceof FreightTank ? - String.format("%.1f", + String.format(format, ((FreightTank) stock).getLiquidAmount() / (float)Fluid.BUCKET_VOLUME) : ""; case MAX_LIQUID: return stock instanceof FreightTank ? - String.format("%.1f", + String.format(format, ((FreightTank)stock).getTankCapacity().MilliBuckets() / (float)Fluid.BUCKET_VOLUME) : ""; case UNITS_LIQUID: @@ -75,10 +82,10 @@ public String getValue(EntityRollingStock stock) { case BOILER_PRESSURE: return stock instanceof LocomotiveSteam ? - String.format("%.1f", ConfigGraphics.pressureUnit.convertFromPSI(((LocomotiveSteam) stock).getBoilerPressure())) : ""; + String.format(format, ConfigGraphics.pressureUnit.convertFromPSI(((LocomotiveSteam) stock).getBoilerPressure())) : ""; case MAX_BOILER_PRESSURE: return stock instanceof LocomotiveSteam ? - String.format("%.1f", ConfigGraphics.pressureUnit.convertFromPSI((float)((LocomotiveSteam) stock).getDefinition().getMaxPSI(stock.gauge))) + String.format(format, ConfigGraphics.pressureUnit.convertFromPSI((float)((LocomotiveSteam) stock).getDefinition().getMaxPSI(stock.gauge))) : ""; case UNITS_BOILER_PRESSURE: return ConfigGraphics.pressureUnit.toUnitString(); @@ -90,7 +97,7 @@ public String getValue(EntityRollingStock stock) { if (stock instanceof LocomotiveDiesel) { temp = ((LocomotiveDiesel) stock).getEngineTemperature(); } - return temp != null ? String.format("%.1f", ConfigGraphics.temperatureUnit.convertFromCelcius(temp)) : ""; + return temp != null ? String.format(format, ConfigGraphics.temperatureUnit.convertFromCelcius(temp)) : ""; case MAX_TEMPERATURE: if (stock instanceof LocomotiveSteam) { temp = 100f; @@ -98,7 +105,7 @@ public String getValue(EntityRollingStock stock) { if (stock instanceof LocomotiveDiesel) { temp = 150f; } - return temp != null ? String.format("%.1f", ConfigGraphics.temperatureUnit.convertFromCelcius(temp)) : ""; + return temp != null ? String.format(format, ConfigGraphics.temperatureUnit.convertFromCelcius(temp)) : ""; case UNITS_TEMPERATURE: return ConfigGraphics.temperatureUnit.toUnitString(); case BRAKE_PRESSURE: @@ -122,6 +129,39 @@ public String getValue(EntityRollingStock stock) { } return ""; } + + public boolean hasDecimalSetting() { + switch (this) { + case SPEED: + case MAX_SPEED: + case LIQUID: + case MAX_LIQUID: + case BOILER_PRESSURE: + case MAX_BOILER_PRESSURE: + case TEMPERATURE: + case MAX_TEMPERATURE: + return true; + default: + return false; + } + } + + private int getDefaultDecimal() { + switch (this) { + case LIQUID: + case MAX_LIQUID: + case BOILER_PRESSURE: + case MAX_BOILER_PRESSURE: + case TEMPERATURE: + case MAX_TEMPERATURE: + return 1; + case SPEED: + case MAX_SPEED: + default: + return 0; + } + } + @Override public String toString() { return "stat." + this.name().toLowerCase(Locale.ROOT); diff --git a/src/main/java/cam72cam/immersiverailroading/items/ItemManual.java b/src/main/java/cam72cam/immersiverailroading/items/ItemManual.java index 80543c4fe..6ef5c0038 100644 --- a/src/main/java/cam72cam/immersiverailroading/items/ItemManual.java +++ b/src/main/java/cam72cam/immersiverailroading/items/ItemManual.java @@ -1,6 +1,7 @@ package cam72cam.immersiverailroading.items; import cam72cam.immersiverailroading.ImmersiveRailroading; +import cam72cam.immersiverailroading.library.ChatText; import cam72cam.immersiverailroading.library.GuiText; import cam72cam.immersiverailroading.multiblock.Multiblock; import cam72cam.immersiverailroading.multiblock.MultiblockRegistry; @@ -48,7 +49,7 @@ public List getTooltip(ItemStack stack) { if (mb == null) { return super.getTooltip(stack); } - return Collections.singletonList(GuiText.SELECTOR_TYPE.toString(mb.getName())); + return Collections.singletonList(GuiText.SELECTOR_TYPE.toString(mb.getTranslatedName())); } @Override @@ -60,7 +61,8 @@ public void onClickAir(Player player, World world, Player.Hand hand) { List keys = MultiblockRegistry.registered(); data.multiblock = keys.get((keys.indexOf(data.multiblock) + 1) % (keys.size())); data.write(); - player.sendMessage(PlayerMessage.direct("Placing: " + data.multiblock.getName())); + + player.sendMessage(ChatText.MULTIBLOCK_SELECTING.getMessage(data.multiblock.getTranslatedName())); } } else { if (world.isClient) { diff --git a/src/main/java/cam72cam/immersiverailroading/items/ItemPaintBrush.java b/src/main/java/cam72cam/immersiverailroading/items/ItemPaintBrush.java index e34501307..8bde4e5fa 100644 --- a/src/main/java/cam72cam/immersiverailroading/items/ItemPaintBrush.java +++ b/src/main/java/cam72cam/immersiverailroading/items/ItemPaintBrush.java @@ -147,7 +147,7 @@ protected void handle() { getPlayer().sendMessage(ChatText.BRUSH_NO_VARIANTS.getMessage()); } else if (Config.ConfigDebug.debugPaintBrush) { //This is a debug log so use the untranslated Mode name - getPlayer().sendMessage(ChatText.BRUSH_NEXT.getMessage( + getPlayer().sendMessage(ChatText.BRUSH_NEXT_DEBUG.getMessage( stock.getDefinition().textureNames.getOrDefault(stock.getTexture(), "Unknown"), mode.toTranslatedString())); } diff --git a/src/main/java/cam72cam/immersiverailroading/items/ItemRadioCtrlCard.java b/src/main/java/cam72cam/immersiverailroading/items/ItemRadioCtrlCard.java index 8f0fe611a..089f126f4 100644 --- a/src/main/java/cam72cam/immersiverailroading/items/ItemRadioCtrlCard.java +++ b/src/main/java/cam72cam/immersiverailroading/items/ItemRadioCtrlCard.java @@ -1,6 +1,7 @@ package cam72cam.immersiverailroading.items; import cam72cam.immersiverailroading.ImmersiveRailroading; +import cam72cam.immersiverailroading.library.GuiText; import cam72cam.mod.item.*; import cam72cam.mod.serialization.TagField; @@ -34,7 +35,7 @@ public List getCreativeTabs() { @Override public List getTooltip(ItemStack stack) { Data d = new Data(stack); - return Collections.singletonList(d.linked == null ? "Not linked to any locomotive" : "Linked to: " + d.linked); + return Collections.singletonList(d.linked == null ? GuiText.RADIO_CARD_NOT_LINKED.toString() : GuiText.RADIO_CARD_LINKED_TO.toString(d.linked)); } public static class Data extends ItemDataSerializer { diff --git a/src/main/java/cam72cam/immersiverailroading/items/ItemTrackBlueprint.java b/src/main/java/cam72cam/immersiverailroading/items/ItemTrackBlueprint.java index fd1377efb..b01611ba2 100644 --- a/src/main/java/cam72cam/immersiverailroading/items/ItemTrackBlueprint.java +++ b/src/main/java/cam72cam/immersiverailroading/items/ItemTrackBlueprint.java @@ -104,9 +104,9 @@ public List getTooltip(ItemStack stack) { String indented = " - %s"; tooltip.add(GuiText.TRACK_TYPE.toString("")); - tooltip.add(String.format(indented, settings.type)); - tooltip.add(String.format(indented, settings.length + " Meters")); - tooltip.add(String.format(indented, settings.gauge + " Gauge")); + tooltip.add(String.format(indented, GuiText.TRACK_TYPE.toString(settings.type))); + tooltip.add(String.format(indented, GuiText.TRACK_LENGTH.toString(settings.length))); + tooltip.add(String.format(indented, GuiText.TRACK_GAUGE.toString(settings.gauge))); // TODO move checks for if applicable to enum if (settings.type.hasQuarters()) { tooltip.add(String.format(indented, GuiText.TRACK_QUARTERS.toString(settings.degrees))); diff --git a/src/main/java/cam72cam/immersiverailroading/library/ChatText.java b/src/main/java/cam72cam/immersiverailroading/library/ChatText.java index 5817697f5..302a46c58 100644 --- a/src/main/java/cam72cam/immersiverailroading/library/ChatText.java +++ b/src/main/java/cam72cam/immersiverailroading/library/ChatText.java @@ -29,13 +29,14 @@ public enum ChatText { RADIO_NOLINK("radio.nolink"), RADIO_CANT_LINK("radio.cant_link"), BRUSH_NO_VARIANTS("brush.no.variants"), - BRUSH_NEXT("brush.next"), + BRUSH_NEXT_DEBUG("brush.next_debug"), BRUSH_MODE_SET("brush.mode.set"), SWITCH_UNLOCKED("switch_state.unlocked"), SWITCH_LOCKED("switch_state.locked"), SWITCH_RESET("switch_state.reset"), SWITCH_CANT_RESET("switch_state.cant_reset"), SWITCH_ALREADY_RESET("switch_state.already_reset"), + MULTIBLOCK_SELECTING("multiblock.select"), ; private String value; diff --git a/src/main/java/cam72cam/immersiverailroading/library/GuiText.java b/src/main/java/cam72cam/immersiverailroading/library/GuiText.java index a7893c708..f46552ead 100644 --- a/src/main/java/cam72cam/immersiverailroading/library/GuiText.java +++ b/src/main/java/cam72cam/immersiverailroading/library/GuiText.java @@ -6,6 +6,8 @@ public enum GuiText { LABEL_BRAKE("label.brake"), LABEL_THROTTLE("label.throttle"), LABEL_REVERSER("label.reverser"), + SLIDER_ZOOM("slider.zoom"), //Need colon + SELECTOR_PAGE("selector.page"), SELECTOR_TYPE("selector.type"), SELECTOR_QUARTERS("selector.quarters"), SELECTOR_CURVOSITY("selector.curvosity"), @@ -24,6 +26,9 @@ public enum GuiText { SELECTOR_PLATE_BOILER("selector.plate_boiler"), SELECTOR_CAST_SINGLE("selector.cast_single"), SELECTOR_CAST_REPEAT("selector.cast_repeat"), + SELECTOR_PAINTBRUSH_RANDOM("selector.paintbrush_random"), + SELECTOR_PAINTBRUSH_TO_STOCK("selector.paintbrush_apply_to_stock"), + SELECTOR_PAINTBRUSH_TO_TRAIN("selector.paintbrush_apply_to_train"), TRACK_TYPE("track.type"), TRACK_LENGTH("track.length"), @@ -39,7 +44,8 @@ public enum GuiText { TRACK_PLACE_BLUEPRINT_FALSE("track.place_blueprint_false"), LOCO_WORKS("loco.works"), - LOCO_HORSE_POWER("loco.horse_power"), +// LOCO_HORSE_POWER("loco.horse_power"), + LOCO_POWER("loco.power"), LOCO_TRACTION("loco.tractive_effort"), LOCO_MAX_SPEED("loco.max_speed"), GAUGE_TOOLTIP("stock.gauge"), @@ -50,15 +56,20 @@ public enum GuiText { TEXTURE_TOOLTIP("stock.texture"), SWITCH_KEY_TOOLTIP("item.switch_key"), SWITCH_KEY_DATA_TOOLTIP("item.switch_key.data"), + RADIO_CARD_LINKED_TO("item.radio_card.linked_to"), + RADIO_CARD_NOT_LINKED("item.radio_card.not_linked"), MODELER_TOOLTIP("stock.modeler"), PACK_TOOLTIP("stock.pack"), TRACK_SWITCHER_TOOLTIP("item.track_exchanger"), PAINT_BRUSH_MODE_TOOLTIP("item.paint_brush.mode"), PAINT_BRUSH_DESCRIPTION_TOOLTIP("item.paint_brush.description"), + + ON("overlay.on"), + OFF("overlay.off"), NONE("none"), ; - private String value; + private final String value; GuiText(String value) { this.value = value; } diff --git a/src/main/java/cam72cam/immersiverailroading/library/ModelComponentType.java b/src/main/java/cam72cam/immersiverailroading/library/ModelComponentType.java index 7ae4180a1..ae90b75be 100644 --- a/src/main/java/cam72cam/immersiverailroading/library/ModelComponentType.java +++ b/src/main/java/cam72cam/immersiverailroading/library/ModelComponentType.java @@ -1,5 +1,9 @@ package cam72cam.immersiverailroading.library; +import cam72cam.mod.text.TextUtil; + +import java.util.Locale; + public enum ModelComponentType { // STANDARD BOGEY_POS_WHEEL_X("BOGEY_#POS#_WHEEL_#ID#"), @@ -134,7 +138,31 @@ public static boolean shouldRender(String group) { return group.contains("CHIMNEY_") || group.contains("CHIMINEY_") || group.contains("PRESSURE_VALVE_") || group.contains("EXHAUST_") || group.contains("CARGO_ITEMS"); } - public static class ModelPosition { + public String getOverlayName() { + //Get name and remove _X + String primary = this.name().substring(0, this.name().length() - 2); + switch (this) { + case CYLINDER_DRAIN_CONTROL_X: + case BELL_CONTROL_X: + case WHISTLE_CONTROL_X: + case HORN_CONTROL_X: + //Remove _CONTROL + primary = primary.substring(0, primary.length() - 8); + //Fallthrough + case TRAIN_BRAKE_X: + case INDEPENDENT_BRAKE_X: + case THROTTLE_X: + case REVERSER_X: + case THROTTLE_BRAKE_X: + case ENGINE_START_X: + return TextUtil.translate("part.immersiverailroading:controls." + primary.toLowerCase(Locale.ROOT)); + default: + //Unexpected behaviour + return ""; + } + } + + public static class ModelPosition { private static final ModelPosition INNER = new ModelPosition("INNER"); public static final ModelPosition LEFT = new ModelPosition("LEFT"); public static final ModelPosition INNER_LEFT = INNER.and(LEFT); diff --git a/src/main/java/cam72cam/immersiverailroading/library/PressureDisplayType.java b/src/main/java/cam72cam/immersiverailroading/library/PressureDisplayType.java deleted file mode 100644 index 8fd4be128..000000000 --- a/src/main/java/cam72cam/immersiverailroading/library/PressureDisplayType.java +++ /dev/null @@ -1,16 +0,0 @@ -package cam72cam.immersiverailroading.library; - -import java.util.Locale; - -public enum PressureDisplayType { - psi, - bar; - - public float convertFromPSI(float value) { - return this == psi ? value : value * 0.0689476f; - } - - public String toUnitString() { - return toString().toUpperCase(Locale.ROOT); - } -} diff --git a/src/main/java/cam72cam/immersiverailroading/library/SpeedDisplayType.java b/src/main/java/cam72cam/immersiverailroading/library/SpeedDisplayType.java deleted file mode 100644 index e5ebb348a..000000000 --- a/src/main/java/cam72cam/immersiverailroading/library/SpeedDisplayType.java +++ /dev/null @@ -1,19 +0,0 @@ -package cam72cam.immersiverailroading.library; - -public enum SpeedDisplayType { - kmh, - mph, - ms; - - public String toUnitString() { - switch (this) { - default: - case kmh: - return "km/h"; - case mph: - return "mph"; - case ms: - return "m/s"; - } - } -} diff --git a/src/main/java/cam72cam/immersiverailroading/library/TrackModelPart.java b/src/main/java/cam72cam/immersiverailroading/library/TrackModelPart.java new file mode 100644 index 000000000..fe6acf703 --- /dev/null +++ b/src/main/java/cam72cam/immersiverailroading/library/TrackModelPart.java @@ -0,0 +1,15 @@ +package cam72cam.immersiverailroading.library; + +public enum TrackModelPart { + RAIL_LEFT, + RAIL_RIGHT, + RAIL_BASE, + TABLE; + + public boolean is(String str) { + if(this != RAIL_BASE) { + return str.contains(this.name()); + } + return !(RAIL_LEFT.is(str) || RAIL_RIGHT.is(str) || TABLE.is(str)); + } +} diff --git a/src/main/java/cam72cam/immersiverailroading/library/unit/ForceDisplayType.java b/src/main/java/cam72cam/immersiverailroading/library/unit/ForceDisplayType.java new file mode 100644 index 000000000..a279ea7a5 --- /dev/null +++ b/src/main/java/cam72cam/immersiverailroading/library/unit/ForceDisplayType.java @@ -0,0 +1,33 @@ +package cam72cam.immersiverailroading.library.unit; + +public enum ForceDisplayType { + kn, + n, + lbf; + + public static final float lbfToNewton = 4.448221f; + + public float convertFromNewton(float value) { + switch (this) { + default: + case kn: + return value / 1000f; + case n: + return value; + case lbf: + return value * 0.224809f; + } + } + + public String toUnitString() { + switch (this) { + default: + case kn: + return "kN"; + case n: + return "N"; + case lbf: + return "lbf"; + } + } +} diff --git a/src/main/java/cam72cam/immersiverailroading/library/unit/PowerDisplayType.java b/src/main/java/cam72cam/immersiverailroading/library/unit/PowerDisplayType.java new file mode 100644 index 000000000..a93fc4749 --- /dev/null +++ b/src/main/java/cam72cam/immersiverailroading/library/unit/PowerDisplayType.java @@ -0,0 +1,42 @@ +package cam72cam.immersiverailroading.library.unit; + +public enum PowerDisplayType { + kw, + w, + horsepower, + ps; + + public static final float kWToHp = 1.34102f; + public static final float hpToKW = 0.745701f; + public static final float wToHp = 0.00134102f; + public static final float PSToKW = 0.735498f; + public static final float wToPS = 0.00135962f; + + public float convertFromWatt(float value) { + switch (this) { + default: + case kw: + return value / 1000f; + case w: + return value; + case horsepower: + return value * wToHp; + case ps: + return value * wToPS; + } + } + + public String toUnitString() { + switch (this) { + case w: + return "W"; + case kw: + return "kW"; + case ps: + return "PS"; + case horsepower: + default: + return "hp"; + } + } +} diff --git a/src/main/java/cam72cam/immersiverailroading/library/unit/PressureDisplayType.java b/src/main/java/cam72cam/immersiverailroading/library/unit/PressureDisplayType.java new file mode 100644 index 000000000..9ad24e9ff --- /dev/null +++ b/src/main/java/cam72cam/immersiverailroading/library/unit/PressureDisplayType.java @@ -0,0 +1,37 @@ +package cam72cam.immersiverailroading.library.unit; + +public enum PressureDisplayType { + bar, + kpa, + psi; + + public static final float psiToKPa = 6.89474f; + public static final float kPaToPsi = 0.145037f; + public static final float psiToBar = 0.0689474f; + public static final float BarToPsi = 14.5037f; + + public float convertFromPSI(float value) { + switch (this) { + // 1 bar = 100 kPa + default: + case bar: + return value * psiToBar; + case kpa: + return value * psiToKPa; + case psi: + return value; + } + } + + public String toUnitString() { + switch (this) { + default: + case bar: + return "bar"; + case kpa: + return "kPa"; + case psi: + return "psi"; + } + } +} diff --git a/src/main/java/cam72cam/immersiverailroading/library/unit/SpeedDisplayType.java b/src/main/java/cam72cam/immersiverailroading/library/unit/SpeedDisplayType.java new file mode 100644 index 000000000..a1824f8d6 --- /dev/null +++ b/src/main/java/cam72cam/immersiverailroading/library/unit/SpeedDisplayType.java @@ -0,0 +1,31 @@ +package cam72cam.immersiverailroading.library.unit; + +public enum SpeedDisplayType { + kmh, + ms, + mph; + + public double convertFromKmh(double value) { + switch (this) { + default: + case kmh: + return value; + case ms: + return value / 3.6; + case mph: + return value * 0.621371; + } + } + + public String toUnitString() { + switch (this) { + default: + case kmh: + return "km/h"; + case ms: + return "m/s"; + case mph: + return "mph"; + } + } +} diff --git a/src/main/java/cam72cam/immersiverailroading/library/TemperatureDisplayType.java b/src/main/java/cam72cam/immersiverailroading/library/unit/TemperatureDisplayType.java similarity index 74% rename from src/main/java/cam72cam/immersiverailroading/library/TemperatureDisplayType.java rename to src/main/java/cam72cam/immersiverailroading/library/unit/TemperatureDisplayType.java index 090646425..7fbc033d1 100644 --- a/src/main/java/cam72cam/immersiverailroading/library/TemperatureDisplayType.java +++ b/src/main/java/cam72cam/immersiverailroading/library/unit/TemperatureDisplayType.java @@ -1,19 +1,19 @@ -package cam72cam.immersiverailroading.library; +package cam72cam.immersiverailroading.library.unit; public enum TemperatureDisplayType { celcius, - farenheit, - kelvin,; + kelvin, + farenheit; public float convertFromCelcius(float value) { switch (this) { default: case celcius: return value; + case kelvin: + return value + 273.15f; case farenheit: return (value * 9f/5f) + 32f; - case kelvin: - return value + 270f; } } @@ -21,11 +21,11 @@ public String toUnitString() { switch (this) { default: case celcius: - return "C"; - case farenheit: - return "F"; + return "°C"; case kelvin: return "K"; + case farenheit: + return "°F"; } } } diff --git a/src/main/java/cam72cam/immersiverailroading/model/ModelState.java b/src/main/java/cam72cam/immersiverailroading/model/ModelState.java index 66a386735..3add80782 100644 --- a/src/main/java/cam72cam/immersiverailroading/model/ModelState.java +++ b/src/main/java/cam72cam/immersiverailroading/model/ModelState.java @@ -1,9 +1,12 @@ package cam72cam.immersiverailroading.model; +import cam72cam.immersiverailroading.ConfigGraphics; import cam72cam.immersiverailroading.entity.EntityMoveableRollingStock; import cam72cam.immersiverailroading.library.ModelComponentType; import cam72cam.immersiverailroading.model.components.ModelComponent; import cam72cam.mod.render.obj.OBJRender; +import cam72cam.mod.render.opengl.BlendMode; +import cam72cam.mod.render.opengl.RenderState; import org.apache.commons.lang3.tuple.Pair; import util.Matrix4; @@ -11,7 +14,6 @@ import java.util.function.Consumer; import java.util.regex.Matcher; import java.util.regex.Pattern; -import java.util.stream.Collectors; public class ModelState { private final Animator animator; @@ -225,109 +227,154 @@ private boolean hasGroupFlag(String group, String filter) { return false; } - // TODO check performance impact of streams - public void render(OBJRender.Binding vbo, EntityMoveableRollingStock stock, List available, float partialTicks) { - // Get all groups that we can render from components that are available - List groups = new ArrayList<>(); - for (ModelComponent component : components) { - if (available == null) { - groups.addAll(component.modelIDs); - } else if (available.contains(component.type)) { - available.remove(component.type); - groups.addAll(component.modelIDs); + private static class Opacity { + final List opaque = new ArrayList<>(); + final List transparent = new ArrayList<>(); + + void add(boolean isTransparent, String group) { + if (isTransparent) { + transparent.add(group); + } else { + opaque.add(group); } } + } + + private static final BlendMode ALPHA_BLEND = new BlendMode(BlendMode.GL_SRC_ALPHA, BlendMode.GL_ONE_MINUS_SRC_ALPHA); + + private static class GroupState { + Matrix4 matrix = null; + Float blockLight = null; + Float skyLight = null; + boolean transparent = false; + + boolean equals(GroupState other) { + return Objects.equals(this.matrix, other.matrix) && + Objects.equals(this.blockLight, other.blockLight) && + Objects.equals(this.skyLight, other.skyLight) && + this.transparent == other.transparent; + } - // Filter out groups that aren't currently visible - if (groupVisibility != null) { - groups = groups.stream().filter(group -> { - Boolean visible = groupVisibility.visible(stock, group); - return visible == null || visible; - }).collect(Collectors.toList()); + void copy(GroupState other) { + this.matrix = other.matrix; + this.blockLight = other.blockLight; + this.skyLight = other.skyLight; + this.transparent = other.transparent; } - Matrix4 matrix = animator != null ? animator.getMatrix(stock, partialTicks) : null; + void reset() { + this.matrix = null; + this.blockLight = null; + this.skyLight = null; + this.transparent = false; + } + } + + public void render(OBJRender.Binding vbo, EntityMoveableRollingStock stock, List available, float partialTicks) { + // Get all groups that we can render from components that are available + List groups = new ArrayList<>(); - Map animatedGroups = new HashMap<>(); - if (groupAnimator != null) { - for (String group : groups) { - Matrix4 m = groupAnimator.getMatrix(stock, group, partialTicks); - if (m != null) { - animatedGroups.put(group, m); + for (ModelComponent component : components) { + if (available == null || available.remove(component.type)) { + // Filter out groups that aren't currently visible + if (groupVisibility == null) { + groups.addAll(component.groups); + } else { + for (ModelComponent.ModelGroup g : component.groups) { + Boolean visible = groupVisibility.visible(stock, g.modelID); + if (visible == null || visible) { + groups.add(g); + } + } } } } + // Minimize draw calls by using the same comparison as OBJRender + groups.sort(Comparator.comparing(a -> a.modelID)); + + // General matrix to apply + Matrix4 matrix = animator != null ? animator.getMatrix(stock, partialTicks) : null; + // Required, TODO upstream checking or optional LightState lighting = lighter.get(stock); boolean fullBright = lighting.fullBright != null && lighting.fullBright; boolean hasInterior = lighting.hasInterior != null && lighting.hasInterior; + GroupState current = new GroupState(); + GroupState next = new GroupState(); + List currentGroups = new ArrayList<>(groups.size()); + + Consumer currentModifier = state -> { + if (matrix != null) { + state.model_view().multiply(matrix); + } + if (current.matrix != null) { + state.model_view().multiply(current.matrix); + } + if (current.blockLight != null && current.skyLight != null) { + state.lightmap(current.blockLight, current.skyLight); + } + if (current.transparent) { + state.blend(ALPHA_BLEND).depth_mask(false); + } + }; - Map, List> levels = new HashMap<>(); - for (String group : groups) { - if (!lcgCache.containsKey(group)) { - Matcher matcher = lcgPattern.matcher(group); - lcgCache.put(group, matcher.find() ? matcher.group(1) : null); + for (ModelComponent.ModelGroup group : groups) { + if (group.transparent && !ConfigGraphics.RenderSemiTransparentParts) { + // Don't render the group + continue; } - String lcg = lcgCache.get(group); - boolean invertGroup = linvertCache.computeIfAbsent(group, g -> hasGroupFlag(g, "LINVERT")); - boolean interiorGroup = interiorCache.computeIfAbsent(group, g -> hasGroupFlag(g, "INTERIOR")); - boolean fullbrightGroup = fullbrightCache.computeIfAbsent(group, g -> hasGroupFlag(g, "FULLBRIGHT")); + next.reset(); + + if (groupAnimator != null) { + next.matrix = groupAnimator.getMatrix(stock, group.modelID, partialTicks); + } - Float lcgValue = lcg != null ? stock.getControlPosition(lcg) : null; - lcgValue = lcgValue == null ? null : invertGroup ? 1 - lcgValue : lcgValue; - Pair key = null; + Float lcgValue = group.LCG != null ? stock.getControlPosition(group.LCG) : null; + lcgValue = lcgValue == null ? null : group.linvert ? 1 - lcgValue : lcgValue; // TODO additional null checks around lighting fields if (lcgValue == null || lcgValue > 0) { - if (fullBright && fullbrightGroup) { - key = Pair.of(1f, 1f); + if (fullBright && group.fullbright) { + next.blockLight = 1F; + next.skyLight = 1F; } else if (lighting.interiorLight != null) { - if (!hasInterior || interiorGroup) { + if (!hasInterior || group.interior) { + next.blockLight = lighting.interiorLight; + next.skyLight = lighting.skyLight; if (lcgValue != null) { - key = Pair.of(lighting.interiorLight * lcgValue, lighting.skyLight); - } else { - key = Pair.of(lighting.interiorLight, lighting.skyLight); + next.blockLight *= lcgValue; } } } } - levels.computeIfAbsent(key, p -> new ArrayList<>()).add(group); - } - - levels.forEach((level, litGroups) -> { - List animated = animatedGroups.isEmpty() ? Collections.emptyList() : - litGroups.stream().filter(g -> animatedGroups.containsKey(g)).collect(Collectors.toList()); - List notAnimated = animatedGroups.isEmpty() ? litGroups : - litGroups.stream().filter(g -> !animatedGroups.containsKey(g)).collect(Collectors.toList()); + next.transparent = group.transparent; - if (!notAnimated.isEmpty()) { - vbo.draw(notAnimated, state -> { - if (matrix != null) { - state.model_view().multiply(matrix); - } - if (level != null) { - state.lightmap(level.getKey(), level.getValue()); - } - }); + // See if we are still part of the current render group + if (current.equals(next)) { + // If so, add this group to the pile + currentGroups.add(group.modelID); + continue; } - if (!animated.isEmpty()) { - animated.forEach(group -> { - vbo.draw(Collections.singletonList(group), state -> { - if (matrix != null) { - state.model_view().multiply(matrix); - } - state.model_view().multiply(animatedGroups.get(group)); - if (level != null) { - state.lightmap(level.getKey(), level.getValue()); - } - }); - }); + + // Flush + if (!currentGroups.isEmpty()) { + vbo.draw(currentGroups, currentModifier); } - }); + + // Start tracking the next set of groups + currentGroups.clear(); + currentGroups.add(group.modelID); + current.copy(next); + } + + // Flush + if (!currentGroups.isEmpty()) { + vbo.draw(currentGroups, currentModifier); + } for (ModelState child : children) { child.render(vbo, stock, available, partialTicks); diff --git a/src/main/java/cam72cam/immersiverailroading/model/TrackModel.java b/src/main/java/cam72cam/immersiverailroading/model/TrackModel.java index 742d6ddca..d3344a619 100644 --- a/src/main/java/cam72cam/immersiverailroading/model/TrackModel.java +++ b/src/main/java/cam72cam/immersiverailroading/model/TrackModel.java @@ -1,45 +1,297 @@ package cam72cam.immersiverailroading.model; +import cam72cam.immersiverailroading.library.TrackModelPart; +import cam72cam.immersiverailroading.track.VecYPR; +import cam72cam.immersiverailroading.util.DataBlock; +import cam72cam.immersiverailroading.util.MathUtil; +import cam72cam.immersiverailroading.util.RailInfo; import cam72cam.mod.model.obj.OBJModel; +import cam72cam.mod.render.obj.OBJRender; +import cam72cam.mod.render.opengl.VBO; import cam72cam.mod.resource.Identifier; import trackapi.lib.Gauges; +import util.Matrix4; -import java.util.ArrayList; +import java.util.*; +import java.util.function.Function; +import java.util.function.Supplier; +import java.util.stream.Collectors; -public class TrackModel extends OBJModel { +public class TrackModel extends OBJModel{ + private TrackOrder order; + //Get randomized idents' real ident + private Map> randomMap; + //Map primitive idents to OBJModel + private final Map>> groupNamesMapper; private final String compare; private final double size; - private final double height; + private double height; public final double spacing; - public TrackModel(String condition, Identifier resource, double model_gauge_m, double spacing) throws Exception { - super(resource, 0, Gauges.STANDARD / model_gauge_m); + public TrackModel(String condition, Identifier resource, double modelGaugeM, double spacing, boolean isSingle) throws Exception { + super(resource, 0, Gauges.STANDARD / modelGaugeM); this.compare = condition.substring(0, 1); - this.size = Double.parseDouble(condition.substring(1)); - ArrayList groups = new ArrayList<>(); - for (String group : groups()) { - if (group.contains("RAIL_LEFT") || group.contains("RAIL_RIGHT")) { - groups.add(group); + this.groupNamesMapper = new HashMap<>(); + if(isSingle) { + Map> groups = new HashMap<>(); + for(TrackModelPart part : TrackModelPart.values()){ + List parts = this.groups().stream().filter(part::is).collect(Collectors.toList()); + groups.put(part, parts); } + groupNamesMapper.put("single", groups); + randomMap = Collections.singletonMap("single", () -> "single"); + this.order = new TrackOrder(Collections.singletonList("single")); + List rails = this.groups().stream() + .filter(group -> TrackModelPart.RAIL_LEFT.is(group) || TrackModelPart.RAIL_RIGHT.is(group)) + .collect(Collectors.toList()); + this.height = maxOfGroup(rails).y; } - height = maxOfGroup(groups).y; - this.spacing = spacing * (Gauges.STANDARD / model_gauge_m); + this.size = Double.parseDouble(condition.substring(1)); + this.spacing = spacing * (Gauges.STANDARD / modelGaugeM); + } + + public static TrackModel parse(String condition, DataBlock block, double modelGaugeM, double spacing) throws Exception{ + Map> mapper = new HashMap<>(); + Identifier identifier = block.getValue("model").asIdentifier(); + TrackModel model = new TrackModel(condition, identifier, modelGaugeM, spacing, false); + Function, List> toString = s -> s.stream() + .map(DataBlock.Value::asString) + .collect(Collectors.toList()); + + double[] height = {Double.MIN_VALUE}; + List groupsList = block.getBlocks("groups"); + if (groupsList == null || groupsList.isEmpty()){ + throw new IllegalArgumentException("You must have at least 1 entry in \"groups\", or you should use legacy format!"); + } else { + groupsList.forEach(groupBlock -> { + String ident = groupBlock.getValue("ident").asString(); + DataBlock parts = groupBlock.getBlock("parts"); + + Map> groups = Arrays.stream(TrackModelPart.values()) + .collect(Collectors.toMap( + part -> part, + part -> Optional.ofNullable(parts.getValues(part.name())) + .map(toString) + .orElse(Collections.emptyList()) + )); + + List rails = new ArrayList<>(); + groups.entrySet().stream() + .filter(entry -> entry.getKey() == TrackModelPart.RAIL_LEFT + || entry.getKey() == TrackModelPart.RAIL_RIGHT) + .map(Map.Entry::getValue) + .forEach(rails::addAll); + + height[0] = Math.max(height[0], model.maxOfGroup(rails).y); + model.groupNamesMapper.put(ident, groups); + mapper.put(ident, () -> ident); + }); + } + + if (height[0] != Double.MIN_VALUE) { + model.height = height[0]; + } else { + throw new IllegalArgumentException("Unable to get any rail in model groups definition!"); + } + + List randomized = block.getBlocks("randomized"); + if(randomized != null){randomized.forEach(b -> { + String ident = b.getValue("ident").asString(); + Random rand = new Random(ident.hashCode()); + Map partWeights = b.getBlock("part_weights").getValueMap().entrySet() + .stream() + .collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().asInteger())); + + int gcd = partWeights.values().stream().reduce(0, MathUtil::gcd); + int totalWeight = partWeights.values().stream().mapToInt(i -> i / gcd).sum(); + + String[] strArray = new String[totalWeight]; + int index = 0; + + for (Map.Entry entry : partWeights.entrySet()) { + int weight = entry.getValue() / gcd; + for (int j = 0; j < weight; j++) { + strArray[index++] = entry.getKey(); + } + } + + mapper.put(ident, () -> strArray[rand.nextInt(totalWeight)]); + }); + } + + //Parse order + DataBlock orderBlock = block.getBlock("order"); + List orderArray = block.getValues("order"); + TrackOrder trackOrder; + if(orderBlock != null){ + List mid = toString.apply(orderBlock.getValues("mid")); + trackOrder = new TrackOrder(mid); + Optional.ofNullable(orderBlock.getValues("near")) + .ifPresent(arr -> trackOrder.setNear(arr.stream() + .map(DataBlock.Value::asString) + .collect(Collectors.toList()))); + Optional.ofNullable(orderBlock.getValues("far")) + .ifPresent(arr -> trackOrder.setFar(arr.stream() + .map(DataBlock.Value::asString) + .collect(Collectors.toList()))); + } else if(orderArray != null) { + //A fallback for "order" in array format, take it as "mid" + List mid = toString.apply(block.getValues("order")); + trackOrder = new TrackOrder(mid); + } else { + throw new IllegalArgumentException("Must contains \"order\" field with advanced track definition"); + } + + model.order = trackOrder; + model.randomMap = mapper; + return model; } public boolean canRender(double gauge) { switch (compare) { - case ">": - return gauge > size; - case "<": - return gauge < size; - case "=": - return gauge == size; - default: - return true; + case ">": return gauge > size; + case "<": return gauge < size; + case "=": return gauge == size; + default: return true; + } + } + + public VBO getModel(RailInfo info, List data) { + if(info.settings.type.isTable()){ + return renderTable(info, data); + } + + //Otherwise use generated order to build + OBJRender.Builder builder = this.binder().builder(); + List names = order.getRenderOrder(data.size()); + for (int i = 0; i < names.size(); i++) { + String modelKey = randomMap.get(names.get(i)).get(); + Map> groups = this.groupNamesMapper.get(modelKey); + + renderPiece(info, data.get(i), builder, groups); + } + + return builder.build(); + } + + private VBO renderTable(RailInfo info, List data) { + OBJRender.Builder builder = this.binder().builder(); + Map> groupNames = this.groupNamesMapper.values().stream().findFirst().get(); + + for (VecYPR piece : data) { + renderPiece(info, piece, builder, groupNames); + } + + return builder.build(); + } + + private void renderPiece(RailInfo info, VecYPR piece, + OBJRender.Builder builder, Map> groupNames) { + Matrix4 matrix = new Matrix4(); + matrix.translate(piece.x, piece.y, piece.z); + matrix.rotate(Math.toRadians(piece.getYaw()), 0, 1, 0); + matrix.rotate(Math.toRadians(piece.getPitch()), 1, 0, 0); + matrix.rotate(Math.toRadians(-90), 0, 1, 0); + + double scale = info.settings.gauge.scale(); + matrix.scale(scale, scale, scale); + + List tables = groupNames.get(TrackModelPart.TABLE); + + if(piece.getParts().contains(TrackModelPart.TABLE)){ + builder.draw(tables, matrix.copy()); + } + + if (piece.getLength() != -1) { + matrix.scale(piece.getLength() / info.settings.gauge.scale(), 1, 1); + } + + List groups = new ArrayList<>(); + if (!piece.getParts().isEmpty()) { + groupNames.keySet().stream() + .filter(part -> part != TrackModelPart.TABLE) + .filter(part -> piece.getParts().contains(part)) + .map(groupNames::get).forEach(groups::addAll); + } else { + groupNames.keySet().stream() + .filter(part -> part != TrackModelPart.TABLE) + .map(groupNames::get).forEach(groups::addAll); + } + builder.draw(groups, matrix); + if(!piece.getChildren().isEmpty()){ + for(VecYPR vec : piece.getChildren()){ + renderPiece(info, vec, builder, groupNames); + } } } public double getHeight() { return height; } -} + + public static class TrackOrder{ + // All directions are Near -> Far + protected final List near = new ArrayList<>(); + protected final List mid = new ArrayList<>(); + protected final List far = new ArrayList<>(); + + public TrackOrder(List mid) { + this.mid.addAll(parseCounts(mid)); + } + + public void setNear(List near) { + this.near.addAll(parseCounts(near)); + } + + public void setFar(List far) { + this.far.addAll(parseCounts(far)); + } + + public List getRenderOrder(int length) { + List value = new ArrayList<>(); + + if(length < near.size() + far.size()){ + int n = 0, f = 0; + while (n + f < length){ + if(n <= near.size()){ + n++; + } + + if(n + f < length && f <= far.size()){ + f++; + } + } + + for(int i = 0; i < n; i++){ + value.add(near.get(i)); + } + for(int i = far.size() - f; i < far.size(); i++){ + value.add(far.get(i)); + } + } else { + value.addAll(near); + value.addAll(far); + for(int i = 0, j = near.size(); j < length - far.size(); i = (i+1) % mid.size(), j++){ + value.add(j, mid.get(i)); + } + } + return value; + } + + private static List parseCounts(List orig) { + // ["Str*3"] will be ["Str","Str","Str"] + List result = new ArrayList<>(); + for(String s : orig){ + String[] str = s.split("\\*"); + result.add(str[0]); + if(str.length == 2) { + int count = Integer.parseInt(str[1]); + for (int i = 1; i < count; i++) { + result.add(str[0]); + } + } + } + return result; + } + } +} \ No newline at end of file diff --git a/src/main/java/cam72cam/immersiverailroading/model/animation/StockAnimation.java b/src/main/java/cam72cam/immersiverailroading/model/animation/StockAnimation.java index dc9d692e7..255af0c6b 100644 --- a/src/main/java/cam72cam/immersiverailroading/model/animation/StockAnimation.java +++ b/src/main/java/cam72cam/immersiverailroading/model/animation/StockAnimation.java @@ -44,11 +44,9 @@ public StockAnimation(AnimationDefinition def, double internal_model_scale) thro public float getValue(EntityRollingStock stock) { float value = def.control_group != null ? stock.getControlPosition(def.control_group) : def.readout.getValue(stock); + value = Math.min(1, Math.max(0, (value - def.rangeMin) / (def.rangeMax - def.rangeMin))); value += def.offset; - if (def.invert) { - value = 1-value; - } - return value; + return def.invert ? 1 - value : value; } public float getPercent(EntityRollingStock stock, float partialTicks) { diff --git a/src/main/java/cam72cam/immersiverailroading/model/components/ModelComponent.java b/src/main/java/cam72cam/immersiverailroading/model/components/ModelComponent.java index 229e0a239..88199563c 100644 --- a/src/main/java/cam72cam/immersiverailroading/model/components/ModelComponent.java +++ b/src/main/java/cam72cam/immersiverailroading/model/components/ModelComponent.java @@ -7,8 +7,9 @@ import cam72cam.mod.model.obj.OBJGroup; import cam72cam.mod.model.obj.OBJModel; -import java.util.List; -import java.util.Set; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import java.util.stream.Collectors; public class ModelComponent { @@ -24,17 +25,64 @@ public class ModelComponent { public final boolean wooden; private final OBJModel model; + public final List groups; + + public static final Pattern lcgPattern = Pattern.compile("_LCG_([^_]+)"); + public static class ModelGroup { + public final String modelID; + public final String LCG; + public final boolean linvert; + public final boolean interior; + public final boolean fullbright; + public final boolean transparent; + + public ModelGroup(String modelID) { + Matcher m = lcgPattern.matcher(modelID); + LCG = m.find() ? m.group(1) : null; + + boolean linvert = false; + boolean interior = false; + boolean fullbright = false; + boolean transparent = false; + + for (String x : modelID.split("_")) { + switch (x) { + case "LINVERT": + linvert = true; + break; + case "INTERIOR": + interior = true; + break; + case "FULLBRIGHT": + fullbright = true; + break; + case "ALPHA": + transparent = true; + break; + } + } + + this.modelID = modelID; + this.linvert = linvert; + this.interior = interior; + this.fullbright = fullbright; + this.transparent = transparent; + } + } + public ModelComponent(ModelComponentType type, ModelPosition pos, Integer id, OBJModel model, Set modelIDs) { this.type = type; this.pos = pos; this.id = id; this.modelIDs = modelIDs; + this.groups = modelIDs.stream().map(ModelGroup::new).collect(Collectors.toList()); this.key = String.join(" ", modelIDs); this.model = model; min = model.minOfGroup(this.modelIDs); max = model.maxOfGroup(this.modelIDs); center = new Vec3d((min.x + max.x)/2, (min.y + max.y)/2, (min.z + max.z)/2); wooden = modelIDs.stream().anyMatch(g -> g.contains("WOOD")); + } public double length() { diff --git a/src/main/java/cam72cam/immersiverailroading/model/part/Control.java b/src/main/java/cam72cam/immersiverailroading/model/part/Control.java index 824708355..a22822bdb 100644 --- a/src/main/java/cam72cam/immersiverailroading/model/part/Control.java +++ b/src/main/java/cam72cam/immersiverailroading/model/part/Control.java @@ -3,6 +3,7 @@ import cam72cam.immersiverailroading.ConfigGraphics; import cam72cam.immersiverailroading.entity.EntityMoveableRollingStock; import cam72cam.immersiverailroading.entity.EntityRollingStock; +import cam72cam.immersiverailroading.library.GuiText; import cam72cam.immersiverailroading.library.ModelComponentType; import cam72cam.immersiverailroading.library.ModelComponentType.ModelPosition; import cam72cam.immersiverailroading.model.ModelState; @@ -19,6 +20,7 @@ import cam72cam.mod.render.GlobalRender; import cam72cam.mod.render.opengl.RenderState; import cam72cam.mod.text.TextColor; +import cam72cam.mod.text.TextUtil; import cam72cam.mod.util.Axis; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.text.WordUtils; @@ -297,7 +299,7 @@ public void postRender(T stock, RenderState state, float partialTicks) { percent *= -2; } if (toggle || press) { - labelstate = percent == 1 ? " (On)" : " (Off)"; + labelstate = percent == 1 ? " ("+ GuiText.ON +")" : " ("+ GuiText.OFF +")"; } else { labelstate = String.format(" (%d%%)", (int)(percent * 100)); } @@ -307,12 +309,25 @@ public void postRender(T stock, RenderState state, float partialTicks) { return; } if (toggle || press) { - labelstate = percent == 1 ? " (On)" : " (Off)"; + labelstate = percent == 1 ? " ("+ GuiText.ON +")" : " ("+ GuiText.OFF +")"; } else { labelstate = String.format(" (%d%%)", (int)(percent * 100)); } } - String str = (label != null ? label : formatLabel(part.type)) + labelstate; + //Try to translate label + String str; + if (this.label != null) { + String[] parts = stock.getDefinitionID().split("/"); + String key1 = "label.immersiverailroading:" + parts[1] + "." + parts[2].replace(".json", "") + "." + label; + str = TextUtil.translate(key1); + if (str.equals(key1)) { + String key2 = "label.immersiverailroading:" + label; + str = TextUtil.translate(key2).equals(key2) ? label : TextUtil.translate(key2); + } + } else { + str = part.type.getOverlayName(); + } + str += labelstate; if (isPressed) { str = TextColor.BOLD.wrap(str); } diff --git a/src/main/java/cam72cam/immersiverailroading/model/part/LightFlare.java b/src/main/java/cam72cam/immersiverailroading/model/part/LightFlare.java index 57a4af92e..df9e43045 100644 --- a/src/main/java/cam72cam/immersiverailroading/model/part/LightFlare.java +++ b/src/main/java/cam72cam/immersiverailroading/model/part/LightFlare.java @@ -1,5 +1,6 @@ package cam72cam.immersiverailroading.model.part; +import cam72cam.immersiverailroading.ConfigGraphics; import cam72cam.immersiverailroading.entity.EntityMoveableRollingStock; import cam72cam.immersiverailroading.entity.EntityRollingStock; import cam72cam.immersiverailroading.library.ModelComponentType; @@ -11,6 +12,7 @@ import cam72cam.immersiverailroading.registry.EntityRollingStockDefinition.LightDefinition; import cam72cam.immersiverailroading.util.VecUtil; import cam72cam.mod.MinecraftClient; +import cam72cam.mod.math.Rotation; import cam72cam.mod.math.Vec3d; import cam72cam.mod.math.Vec3i; import cam72cam.mod.render.Light; @@ -23,6 +25,7 @@ import java.util.*; import java.util.function.Function; +import java.util.function.Predicate; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -42,6 +45,7 @@ public class LightFlare { private final int blinkOffsetTicks; private final boolean castsLights; private final boolean blinkFullBright; + private final Rotation direction; private final String controlGroup; private final boolean invert; private final Function location; @@ -61,7 +65,6 @@ public static List> get(Ent private LightFlare(EntityRollingStockDefinition def, ModelState state, ModelComponent component) { this.component = component; - this.forward = component.center.x < 0; Matcher rgbValues = component.modelIDs.stream() .map(rgb::matcher) .filter(Matcher::matches) @@ -81,8 +84,15 @@ private LightFlare(EntityRollingStockDefinition def, ModelState state, ModelComp this.controlGroup = component.modelIDs.stream() .map(lcgPattern::matcher).filter(Matcher::find).map(m -> m.group(1)).findFirst().orElse(null); - this.invert = component.modelIDs.stream().anyMatch(g -> g.contains("_LINVERT_") || g.startsWith("LINVERT_") || g.endsWith("_LINVERT")); - + Predicate checker = s -> component.modelIDs.stream().anyMatch(g -> g.contains ("_" + s + "_") + || g.startsWith(s + "_") + || g.endsWith ("_" + s)); + this.invert = checker.test("LINVERT"); + this.direction = checker.test("FORWARD") + ? Rotation.NONE + : checker.test("REVERSE") + ? Rotation.COUNTERCLOCKWISE_90 + : null; // This is bad... LightDefinition config = def.getLight(component.type.toString() .replace("_X", "_" + component.id) @@ -90,6 +100,9 @@ private LightFlare(EntityRollingStockDefinition def, ModelState state, ModelComp ); if (config != null) { + this.forward = config.revertDirection + ? !(component.center.x < 0) + : component.center.x < 0; this.lightTex = config.lightTex; this.blinkIntervalTicks = (int)(config.blinkIntervalSeconds * 20); this.blinkOffsetTicks = (int)(config.blinkOffsetSeconds * 20); @@ -104,6 +117,7 @@ private LightFlare(EntityRollingStockDefinition def, ModelState state, ModelComp } } } else { + this.forward = component.center.x < 0; this.lightTex = LightDefinition.default_light_tex; this.blinkIntervalTicks = 0; this.blinkOffsetTicks = 0; @@ -121,13 +135,21 @@ private LightFlare(EntityRollingStockDefinition def, ModelState state, ModelComp } private boolean isLightOff(EntityRollingStock stock) { - return !stock.hasElectricalPower() || (controlGroup != null && stock.getControlPosition(controlGroup) == (invert ? 1 : 0)); + EntityMoveableRollingStock moveable = (EntityMoveableRollingStock) stock; + return !stock.hasElectricalPower() + || (controlGroup != null && stock.getControlPosition(controlGroup) == (invert ? 1 : 0)) + || direction != null && ((direction == Rotation.NONE && moveable.getCurrentSpeed().minecraft() < 0) + || (direction == Rotation.CLOCKWISE_180 && moveable.getCurrentSpeed().minecraft() >= 0)); } private boolean isBlinkOff(EntityRollingStock stock) { return isLightOff(stock) || blinkIntervalTicks > 0 && (stock.getTickCount() + blinkOffsetTicks) % (blinkIntervalTicks*2) > blinkIntervalTicks; } public void postRender(T stock, RenderState state) { + if(ConfigGraphics.DisableLightTextureRender){ + return; + } + //GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR); //GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR); boolean reverse = stock.getCurrentSpeed().minecraft() < 0; @@ -143,7 +165,7 @@ public void postRender(T stock, RenderState state) { return; } - Vec3d flareOffset = new Vec3d(forward ? component.min.x - 0.02 : component.max.x + 0.02, (component.min.y + component.max.y) / 2, (component.min.z + component.max.z) / 2);; + Vec3d flareOffset = new Vec3d(forward ? component.min.x - 0.02 : component.max.x + 0.02, (component.min.y + component.max.y) / 2, (component.min.z + component.max.z) / 2); if (location != null) { // TODO this does not actually work Matrix4 m = location.apply(stock); diff --git a/src/main/java/cam72cam/immersiverailroading/model/part/PartSound.java b/src/main/java/cam72cam/immersiverailroading/model/part/PartSound.java index 021e1b549..52d427ed1 100644 --- a/src/main/java/cam72cam/immersiverailroading/model/part/PartSound.java +++ b/src/main/java/cam72cam/immersiverailroading/model/part/PartSound.java @@ -56,12 +56,7 @@ public void terminate() { } } - private final ExpireableMap entitySounds = new ExpireableMap() { - @Override - public void onRemove(UUID key, Sounds value) { - value.terminate(); - } - }; + private final ExpireableMap entitySounds = new ExpireableMap<>((key, value) -> value.terminate()); public void effects(EntityMoveableRollingStock stock, boolean enabled) { effects(stock, enabled ? 1 : 0, 1); @@ -181,4 +176,4 @@ public void removed(EntityMoveableRollingStock stock) { entitySounds.remove(stock.getUUID()); } -} +} \ No newline at end of file diff --git a/src/main/java/cam72cam/immersiverailroading/model/part/PressureValve.java b/src/main/java/cam72cam/immersiverailroading/model/part/PressureValve.java index 9ae035a5c..4ad806526 100644 --- a/src/main/java/cam72cam/immersiverailroading/model/part/PressureValve.java +++ b/src/main/java/cam72cam/immersiverailroading/model/part/PressureValve.java @@ -31,12 +31,7 @@ public PressureValve(List valves, Identifier sndFile) { this.sndFile = sndFile; } - private final ExpireableMap sounds = new ExpireableMap() { - @Override - public void onRemove(UUID key, ISound value) { - value.stop(); - } - }; + private final ExpireableMap sounds = new ExpireableMap<>((k, v) -> v.stop()); public void effects(EntityMoveableRollingStock stock, boolean isBlowingOff) { ISound sound = sounds.get(stock.getUUID()); diff --git a/src/main/java/cam72cam/immersiverailroading/model/part/ValveGear.java b/src/main/java/cam72cam/immersiverailroading/model/part/ValveGear.java index e7f3a71ea..a63383eee 100644 --- a/src/main/java/cam72cam/immersiverailroading/model/part/ValveGear.java +++ b/src/main/java/cam72cam/immersiverailroading/model/part/ValveGear.java @@ -24,6 +24,7 @@ import java.util.List; public abstract class ValveGear { + private static final ExpireableMap chuffSounds = new ExpireableMap<>((k, v) -> v.free()); protected final WheelSet wheels; private final ModelState state; @@ -291,11 +292,4 @@ void free() { cylinder_drain.stop(); } } - - private static ExpireableMap chuffSounds = new ExpireableMap() { - @Override - public void onRemove(String key, ChuffSound value) { - value.free(); - } - }; } diff --git a/src/main/java/cam72cam/immersiverailroading/model/part/Whistle.java b/src/main/java/cam72cam/immersiverailroading/model/part/Whistle.java index 53b6f6800..ee985bc5e 100644 --- a/src/main/java/cam72cam/immersiverailroading/model/part/Whistle.java +++ b/src/main/java/cam72cam/immersiverailroading/model/part/Whistle.java @@ -123,12 +123,7 @@ public void terminate() { } } - private final ExpireableMap sounds = new ExpireableMap() { - @Override - public void onRemove(UUID key, SoundEffects value) { - value.terminate(); - } - }; + private final ExpireableMap sounds = new ExpireableMap<>((k, v) -> v.terminate()); public void effects(EntityMoveableRollingStock stock, int hornTime, float hornPull) { // Particles and Sound diff --git a/src/main/java/cam72cam/immersiverailroading/multiblock/Multiblock.java b/src/main/java/cam72cam/immersiverailroading/multiblock/Multiblock.java index 1774d72cd..8afeaea75 100644 --- a/src/main/java/cam72cam/immersiverailroading/multiblock/Multiblock.java +++ b/src/main/java/cam72cam/immersiverailroading/multiblock/Multiblock.java @@ -1,7 +1,6 @@ package cam72cam.immersiverailroading.multiblock; import java.util.*; -import java.util.function.Supplier; import java.util.stream.Collectors; import cam72cam.immersiverailroading.IRBlocks; @@ -20,6 +19,7 @@ import cam72cam.mod.math.Vec3d; import cam72cam.mod.math.Vec3i; import cam72cam.mod.text.PlayerMessage; +import cam72cam.mod.text.TextUtil; import cam72cam.mod.world.BlockInfo; import cam72cam.mod.world.World; @@ -85,8 +85,8 @@ private boolean checkValid(World world, Vec3i origin, Vec3i offset, Rotation rot Vec3i pos = origin.add(offset.rotate(rot)); Fuzzy component = lookup(offset); return component.matches(world.getItemStack(pos)); - } - + } + public boolean tryCreate(World world, Vec3i pos) { for (Vec3i activationLocation : this.componentPositions) { for (Rotation rot : Rotation.values()) { @@ -108,7 +108,7 @@ public boolean tryCreate(World world, Vec3i pos) { public abstract Vec3i placementPos(); public void place(World world, Player player, Vec3i pos, Rotation rot) { - Map missing = new HashMap(); + Map missing = new HashMap<>(); Vec3i origin = pos.subtract(this.placementPos().rotate(rot)); for (Vec3i offset : this.componentPositions) { Fuzzy component = lookup(offset); @@ -143,7 +143,7 @@ public void place(World world, Player player, Vec3i pos, Rotation rot) { } } - if (missing.size() != 0) { + if (!missing.isEmpty()) { player.sendMessage(ChatText.BUILD_MISSING.getMessage("", "")); for (String name : missing.keySet()) { player.sendMessage(PlayerMessage.direct(String.format(" - %d x %s", missing.get(name), name))); @@ -203,6 +203,10 @@ public String getName() { return name; } + public String getTranslatedName() { + return TextUtil.translate("multiblock.immersiverailroading:"+getName().toLowerCase(Locale.ROOT)); + } + public abstract class MultiblockInstance { protected final World world; protected final Vec3i origin; diff --git a/src/main/java/cam72cam/immersiverailroading/physics/MovementTrack.java b/src/main/java/cam72cam/immersiverailroading/physics/MovementTrack.java index 204478685..3b2bff221 100644 --- a/src/main/java/cam72cam/immersiverailroading/physics/MovementTrack.java +++ b/src/main/java/cam72cam/immersiverailroading/physics/MovementTrack.java @@ -3,10 +3,10 @@ import cam72cam.immersiverailroading.ImmersiveRailroading; import cam72cam.immersiverailroading.library.Gauge; import cam72cam.immersiverailroading.library.TrackItems; +import cam72cam.immersiverailroading.track.VecYPR; import cam72cam.immersiverailroading.tile.TileRail; import cam72cam.immersiverailroading.tile.TileRailBase; import cam72cam.immersiverailroading.track.IIterableTrack; -import cam72cam.immersiverailroading.track.PosStep; import cam72cam.immersiverailroading.util.VecUtil; import cam72cam.immersiverailroading.thirdparty.trackapi.ITrack; import cam72cam.mod.math.Rotation; @@ -172,7 +172,7 @@ public static Vec3d nextPositionDirect(World world, Vec3d currentPosition, TileR * trying to move. Instead we should probably calculate the vector between the closest pos * and the current pos and move distance along that. How would that work for slopes at the ends? just fine? */ - List positions = ((IIterableTrack) rail.info.getBuilder(world)).getPath(0.25 * rail.info.settings.gauge.scale()); + List positions = ((IIterableTrack) rail.info.getBuilder(world)).getPath(0.25 * rail.info.settings.gauge.scale()); Vec3d center = rail.info.placementInfo.placementPosition.add(rail.getPos()).add(0, heightOffset, 0); Vec3d target = currentPosition.add(delta); Vec3d relative = target.subtract(center); @@ -183,8 +183,8 @@ public static Vec3d nextPositionDirect(World world, Vec3d currentPosition, TileR } if (positions.size() == 1) { // track with length == 1 - PosStep pos = positions.get(0); - Vec3d offset = VecUtil.fromYaw(delta.length(), pos.yaw); + VecYPR pos = positions.get(0); + Vec3d offset = VecUtil.fromYaw(delta.length(), pos.getYaw()); Vec3d result = currentPosition.add(offset); Vec3d resultOpposite = currentPosition.subtract(offset); if (result.distanceToSquared(target) < resultOpposite.distanceToSquared(target)) { @@ -226,8 +226,8 @@ public static Vec3d nextPositionDirect(World world, Vec3d currentPosition, TileR } } - PosStep leftPos = positions.get(left); - PosStep rightPos = positions.get(right); + VecYPR leftPos = positions.get(left); + VecYPR rightPos = positions.get(right); if (leftDistance < 0.000001) { return center.add(leftPos); diff --git a/src/main/java/cam72cam/immersiverailroading/registry/EntityRollingStockDefinition.java b/src/main/java/cam72cam/immersiverailroading/registry/EntityRollingStockDefinition.java index e18762440..b6132e2f8 100644 --- a/src/main/java/cam72cam/immersiverailroading/registry/EntityRollingStockDefinition.java +++ b/src/main/java/cam72cam/immersiverailroading/registry/EntityRollingStockDefinition.java @@ -31,7 +31,6 @@ import java.awt.geom.Rectangle2D; import java.io.IOException; import java.io.InputStream; -import java.nio.file.Files; import java.util.*; import java.util.function.Function; import java.util.function.Supplier; @@ -83,6 +82,7 @@ public abstract class EntityRollingStockDefinition { private double passengerCompartmentWidth; private double weight; private int maxPassengers; + private int snowLayers; private float interiorLightLevel; private boolean hasIndependentBrake; private boolean hasPressureBrake; @@ -161,6 +161,8 @@ public enum AnimationMode { public final Identifier animatrix; public final float offset; public final boolean invert; + public final float rangeMin; + public final float rangeMax; public final float frames_per_tick; public final SoundDefinition sound; @@ -175,6 +177,8 @@ public AnimationDefinition(DataBlock obj) { mode = AnimationMode.valueOf(obj.getValue("mode").asString().toUpperCase(Locale.ROOT)); offset = obj.getValue("offset").asFloat(0f); invert = obj.getValue("invert").asBoolean(false); + rangeMin = obj.getValue("range_min").asFloat(0f); + rangeMax = obj.getValue("range_max").asFloat(1f); frames_per_tick = obj.getValue("frames_per_tick").asFloat(1f); sound = SoundDefinition.getOrDefault(obj, "sound"); } @@ -190,6 +194,7 @@ public static class LightDefinition { public final float blinkIntervalSeconds; public final float blinkOffsetSeconds; public final boolean blinkFullBright; + public final boolean revertDirection; public final String reverseColor; public final Identifier lightTex; public final boolean castsLight; @@ -198,6 +203,7 @@ private LightDefinition(DataBlock data) { blinkIntervalSeconds = data.getValue("blinkIntervalSeconds").asFloat(0f); blinkOffsetSeconds = data.getValue("blinkOffsetSeconds").asFloat(0f); blinkFullBright = data.getValue("blinkFullBright").asBoolean(true); + revertDirection = data.getValue("revertDirection").asBoolean(false); reverseColor = data.getValue("reverseColor").asString(); lightTex = data.getValue("texture").asIdentifier(default_light_tex); castsLight = data.getValue("castsLight").asBoolean(true); @@ -496,6 +502,8 @@ public void loadData(DataBlock data) throws Exception { lights.getBlockMap().forEach((key, block) -> this.lights.put(key, new LightDefinition(block))); } + snowLayers = properties.getValue("snow_layers").asInteger(); + DataBlock sounds = data.getBlock("sounds"); wheel_sound = sounds.getValue("wheels").asIdentifier(); clackFront = clackRear = sounds.getValue("clack").asIdentifier(); @@ -899,5 +907,8 @@ public double getTiltMultiplier() { public double getBrakeShoeFriction() { return brakeCoefficient; } + public int getSnowLayers() { + return snowLayers; + } } diff --git a/src/main/java/cam72cam/immersiverailroading/registry/LocomotiveDefinition.java b/src/main/java/cam72cam/immersiverailroading/registry/LocomotiveDefinition.java index f7ef650ad..514899fe7 100644 --- a/src/main/java/cam72cam/immersiverailroading/registry/LocomotiveDefinition.java +++ b/src/main/java/cam72cam/immersiverailroading/registry/LocomotiveDefinition.java @@ -1,7 +1,10 @@ package cam72cam.immersiverailroading.registry; +import cam72cam.immersiverailroading.ConfigGraphics; import cam72cam.immersiverailroading.ImmersiveRailroading; import cam72cam.immersiverailroading.entity.EntityRollingStock; +import cam72cam.immersiverailroading.library.unit.ForceDisplayType; +import cam72cam.immersiverailroading.library.unit.PowerDisplayType; import cam72cam.immersiverailroading.util.DataBlock; import cam72cam.immersiverailroading.library.Gauge; import cam72cam.immersiverailroading.library.GuiText; @@ -16,8 +19,8 @@ public abstract class LocomotiveDefinition extends FreightDefinition { public boolean toggleBell; public SoundDefinition bell; private String works; - private double power; - private double traction; + private double power_kW; + private double traction_N; private Speed maxSpeed; private boolean hasRadioEquipment; public boolean muliUnitCapable; @@ -47,14 +50,32 @@ public void loadData(DataBlock data) throws Exception { isCabCar = readCabCarFlag(data); if (isCabCar) { - power = 0; - traction = 0; + power_kW = 0; + traction_N = 0; maxSpeed = Speed.ZERO; muliUnitCapable = true; factorOfAdhesion = 0; } else { - power = properties.getValue("horsepower").asInteger() * internal_inv_scale; - traction = properties.getValue("tractive_effort_lbf").asInteger() * internal_inv_scale; + if (properties.getValue("horsepower").asFloat() != null) { + power_kW = properties.getValue("horsepower").asFloat() * PowerDisplayType.hpToKW * internal_inv_scale; + } else if (properties.getValue("power_hp").asFloat() != null) { + power_kW = properties.getValue("power_hp").asFloat() * PowerDisplayType.hpToKW * internal_inv_scale; + } else if (properties.getValue("power_ps").asFloat() != null) { + power_kW = properties.getValue("power_ps").asFloat() * PowerDisplayType.PSToKW * internal_inv_scale; + } else if (properties.getValue("power_kw").asFloat() != null) { + power_kW = properties.getValue("power_kw").asFloat() * internal_inv_scale; + } else { + power_kW = properties.getValue("power_w").asFloat() / 1000 * internal_inv_scale; + } + + if (properties.getValue("tractive_effort_lbf").asFloat() != null) { + traction_N = properties.getValue("tractive_effort_lbf").asFloat() * ForceDisplayType.lbfToNewton * internal_inv_scale; + } else if (properties.getValue("tractive_effort_kn").asFloat() != null) { + traction_N = properties.getValue("tractive_effort_kn").asFloat() * 1000 * internal_inv_scale; + } else { + traction_N = properties.getValue("tractive_effort_n").asFloat() * internal_inv_scale; + } + factorOfAdhesion = properties.getValue("factor_of_adhesion").asDouble(4); maxSpeed = Speed.fromMetric(properties.getValue("max_speed_kmh").asDouble() * internal_inv_scale); muliUnitCapable = properties.getValue("multi_unit_capable").asBoolean(); @@ -78,22 +99,32 @@ public List getTooltip(Gauge gauge) { List tips = super.getTooltip(gauge); tips.add(GuiText.LOCO_WORKS.toString(this.works)); if (!isCabCar) { - tips.add(GuiText.LOCO_HORSE_POWER.toString(this.getHorsePower(gauge))); - tips.add(GuiText.LOCO_TRACTION.toString(this.getStartingTractionNewtons(gauge))); - tips.add(GuiText.LOCO_MAX_SPEED.toString(this.getMaxSpeed(gauge).metricString())); + float power = ConfigGraphics.powerUnit.convertFromWatt(this.getWatt(gauge)); + String p = String.format("%.0f", power); + tips.add(GuiText.LOCO_POWER.toString(p) + " " + ConfigGraphics.powerUnit.toUnitString()); + float force = ConfigGraphics.forceUnit.convertFromNewton(this.getStartingTractionNewtons(gauge)); + String f = String.format("%.0f", force); + tips.add(GuiText.LOCO_TRACTION.toString(f) + " " + ConfigGraphics.forceUnit.toUnitString()); + float speed = (float) ConfigGraphics.speedUnit.convertFromKmh(this.getMaxSpeed(gauge).metric()); + String v = String.format("%.0f", speed); + tips.add(GuiText.LOCO_MAX_SPEED.toString(v) + " " + ConfigGraphics.speedUnit.toUnitString()); } return tips; } - public int getHorsePower(Gauge gauge) { - return (int) Math.ceil(gauge.scale() * this.power); + public float getHorsePower(Gauge gauge) { + return (float) (gauge.scale() * this.power_kW * PowerDisplayType.kWToHp); + } + + public float getWatt(Gauge gauge) { + return (float) (gauge.scale() * this.power_kW * 1000); } /** * @return tractive effort in newtons */ - public int getStartingTractionNewtons(Gauge gauge) { - return (int) Math.ceil(gauge.scale() * this.traction * 4.44822); + public float getStartingTractionNewtons(Gauge gauge) { + return (float) (gauge.scale() * this.traction_N); } public Speed getMaxSpeed(Gauge gauge) { diff --git a/src/main/java/cam72cam/immersiverailroading/registry/LocomotiveDieselDefinition.java b/src/main/java/cam72cam/immersiverailroading/registry/LocomotiveDieselDefinition.java index 2b77ddd95..ef7e4ca67 100644 --- a/src/main/java/cam72cam/immersiverailroading/registry/LocomotiveDieselDefinition.java +++ b/src/main/java/cam72cam/immersiverailroading/registry/LocomotiveDieselDefinition.java @@ -10,9 +10,11 @@ import cam72cam.immersiverailroading.model.DieselLocomotiveModel; import cam72cam.immersiverailroading.model.StockModel; import cam72cam.immersiverailroading.util.FluidQuantity; +import cam72cam.mod.fluid.Fluid; import cam72cam.mod.resource.Identifier; import java.io.IOException; +import java.util.*; public class LocomotiveDieselDefinition extends LocomotiveDefinition { public SoundDefinition idle; @@ -20,6 +22,7 @@ public class LocomotiveDieselDefinition extends LocomotiveDefinition { public SoundDefinition horn; private double fuelCapacity_l; private int fuelEfficiency; + private Map overriddenFuels; private boolean hornSus; private int notches; private float enginePitchRange; @@ -42,9 +45,33 @@ public void loadData(DataBlock data) throws Exception { if (!isCabCar()) { fuelCapacity_l = properties.getValue("fuel_capacity_l").asInteger() * internal_inv_scale * Config.ConfigBalance.DieselLocomotiveTankMultiplier; fuelEfficiency = properties.getValue("fuel_efficiency_%").asInteger(); + List override = properties.getValues("fuel_override"); + if (override != null) { + Map filter = new HashMap<>(); + for (DataBlock.Value value : override) { + String s = value.asString(""); + if (s.contains(":")) { + // [fluid_name]:[burn_time] + String[] split = s.split(":"); + Fluid fluid = Fluid.getFluid(split[0]); + if(fluid != null){ + filter.put(fluid, Integer.valueOf(split[1])); + } + } else if (Config.ConfigBalance.dieselFuels.containsKey(s)) { + Fluid fluid = Fluid.getFluid(s); + if(fluid != null){ + filter.put(fluid, Config.ConfigBalance.dieselFuels.get(s)); + } + } + } + overriddenFuels = filter; + } else { + overriddenFuels = Collections.emptyMap(); + } hasDynamicTractionControl = properties.getValue("dynamic_traction_control").asBoolean(); } else { fuelCapacity_l = 0; + overriddenFuels = Collections.emptyMap(); } notches = properties.getValue("throttle_notches").asInteger(); @@ -101,4 +128,8 @@ public int getThrottleNotches() { public float getEnginePitchRange() { return enginePitchRange; } + + public Map getOverriddenFuels() { + return overriddenFuels; + } } diff --git a/src/main/java/cam72cam/immersiverailroading/registry/LocomotiveSteamDefinition.java b/src/main/java/cam72cam/immersiverailroading/registry/LocomotiveSteamDefinition.java index 843860e2f..72008eb4f 100644 --- a/src/main/java/cam72cam/immersiverailroading/registry/LocomotiveSteamDefinition.java +++ b/src/main/java/cam72cam/immersiverailroading/registry/LocomotiveSteamDefinition.java @@ -3,6 +3,7 @@ import cam72cam.immersiverailroading.Config; import cam72cam.immersiverailroading.ImmersiveRailroading; import cam72cam.immersiverailroading.entity.LocomotiveSteam; +import cam72cam.immersiverailroading.library.unit.PressureDisplayType; import cam72cam.immersiverailroading.util.DataBlock; import cam72cam.immersiverailroading.gui.overlay.GuiBuilder; import cam72cam.immersiverailroading.library.Gauge; @@ -51,7 +52,15 @@ public void loadData(DataBlock data) throws Exception { DataBlock firebox = data.getBlock("firebox"); tankCapacity_l = properties.getValue("water_capacity_l").asInteger() * internal_inv_scale; - maxPSI = Math.ceil(properties.getValue("max_psi").asInteger() * internal_inv_scale); + if (properties.getValue("max_psi").asFloat() != null) { + maxPSI = properties.getValue("max_psi").asFloat() * internal_inv_scale; + } else if (properties.getValue("max_pressure_psi").asFloat() != null) { + maxPSI = properties.getValue("max_pressure_psi").asFloat() * internal_inv_scale; + } else if (properties.getValue("max_pressure_bar").asFloat() != null) { + maxPSI = properties.getValue("max_pressure_bar").asFloat() * PressureDisplayType.BarToPsi * internal_inv_scale; + } else { + maxPSI = properties.getValue("max_pressure_kpa").asFloat() * PressureDisplayType.kPaToPsi * internal_inv_scale; + } numSlots = Math.ceil(firebox.getValue("slots").asInteger() * internal_inv_scale); width = Math.ceil(firebox.getValue("width").asInteger() * internal_inv_scale); tender_auto_feed = properties.getValue("tender_auto_feed").asBoolean(true); @@ -97,8 +106,8 @@ public FluidQuantity getTankCapacity(Gauge gauge) { return Config.ConfigBalance.RoundStockTankToNearestBucket ? cap.roundBuckets() : cap; } - public int getMaxPSI(Gauge gauge) { - return (int) Math.ceil(this.maxPSI * gauge.scale()); + public float getMaxPSI(Gauge gauge) { + return (float) (this.maxPSI * gauge.scale()); } public int getInventorySize(Gauge gauge) { diff --git a/src/main/java/cam72cam/immersiverailroading/registry/TrackDefinition.java b/src/main/java/cam72cam/immersiverailroading/registry/TrackDefinition.java index d572bc53e..a90163392 100644 --- a/src/main/java/cam72cam/immersiverailroading/registry/TrackDefinition.java +++ b/src/main/java/cam72cam/immersiverailroading/registry/TrackDefinition.java @@ -9,7 +9,6 @@ import cam72cam.immersiverailroading.model.TrackModel; import cam72cam.mod.item.Fuzzy; import cam72cam.mod.item.ItemStack; -import org.apache.commons.lang3.tuple.Pair; import trackapi.lib.Gauges; import java.util.*; @@ -40,9 +39,14 @@ public class TrackDefinition { double spacing = object.getValue("model_spacing_m").asDouble( model_gauge_m / Gauges.STANDARD); this.models = new ArrayList<>(); + DataBlock models = object.getBlock("models"); + for (Map.Entry entry : models.getBlockMap().entrySet()) { + this.models.add(TrackModel.parse(entry.getKey(), entry.getValue(), model_gauge_m, spacing)); + } + for (Map.Entry entry : models.getValueMap().entrySet()) { - this.models.add(new TrackModel(entry.getKey(), entry.getValue().asIdentifier(), model_gauge_m, spacing)); + this.models.add(new TrackModel(entry.getKey(), entry.getValue().asIdentifier(), model_gauge_m, spacing, true)); } DataBlock mats = object.getBlock("materials"); @@ -56,7 +60,7 @@ public class TrackDefinition { part.getValue("cost").asFloat() )); } - if (parts.size() > 0) { + if (!parts.isEmpty()) { materials.put(comp, parts); } } @@ -118,7 +122,7 @@ public static class TrackMaterial { private List items; public final float cost; TrackMaterial(String item, float cost) { - this.items = Arrays.stream(item.split(",")).map(s -> s.trim()).map(ItemType::new).collect(Collectors.toList()); + this.items = Arrays.stream(item.split(",")).map(String::trim).map(ItemType::new).collect(Collectors.toList()); this.cost = cost; } diff --git a/src/main/java/cam72cam/immersiverailroading/render/ExpireableMap.java b/src/main/java/cam72cam/immersiverailroading/render/ExpireableMap.java index 6257f1860..c73ab7126 100644 --- a/src/main/java/cam72cam/immersiverailroading/render/ExpireableMap.java +++ b/src/main/java/cam72cam/immersiverailroading/render/ExpireableMap.java @@ -1,37 +1,51 @@ package cam72cam.immersiverailroading.render; import java.util.*; +import java.util.function.BiConsumer; public class ExpireableMap { - - public int lifespan() { - return 10; + private final Map map = new HashMap<>(); + private final Map mapUsage = new HashMap<>(); + private long lastTime = timeS(); + + private final int lifeSpan; + private final boolean refreshAtAccess; + private final BiConsumer removal; + + public ExpireableMap() { + this(10, true, (k, v) -> {}); } - public boolean sliding() { - return true; + + public ExpireableMap(int lifeSpan) { + this(lifeSpan, true, (k, v) -> {}); } - - public void onRemove(K key, V value) { - + + public ExpireableMap(BiConsumer removal){ + this(10, true, removal); + } + + public ExpireableMap(int lifeSpan, boolean refreshAtAccess){ + this(lifeSpan, refreshAtAccess, (k, v) -> {}); + } + + public ExpireableMap(int lifeSpan, boolean refreshAtAccess, BiConsumer removal){ + this.lifeSpan = lifeSpan; + this.refreshAtAccess = refreshAtAccess; + this.removal = removal; } private static long timeS() { return System.currentTimeMillis() / 1000L; } - private Map map = new HashMap(); - private Map mapUsage = new HashMap(); - private long lastTime = timeS(); - public V get(K key) { synchronized(this) { - if (lastTime + lifespan() < timeS()) { + if (lastTime + lifeSpan < timeS()) { // clear unused - Set ks = new HashSet(); - ks.addAll(map.keySet()); + Set ks = new HashSet<>(map.keySet()); for (K dk : ks) { - if (dk != key && mapUsage.get(dk) + lifespan() < timeS()) { - onRemove(dk, map.get(dk)); + if (dk != key && mapUsage.get(dk) + lifeSpan < timeS()) { + removal.accept(dk, map.get(dk)); map.remove(dk); mapUsage.remove(dk); } @@ -41,7 +55,7 @@ public V get(K key) { if (map.containsKey(key)) { - if (sliding()) { + if (refreshAtAccess) { mapUsage.put(key, timeS()); } return map.get(key); @@ -64,7 +78,7 @@ public void put(K key, V displayList) { public void remove(K key) { synchronized(this) { if(map.containsKey(key)) { - onRemove(key, map.get(key)); + removal.accept(key, map.get(key)); map.remove(key); mapUsage.remove(key); } @@ -73,13 +87,12 @@ public void remove(K key) { public Collection values() { synchronized(this) { - if (lastTime + lifespan() < timeS()) { + if (lastTime + lifeSpan < timeS()) { // clear unused - Set ks = new HashSet(); - ks.addAll(map.keySet()); + Set ks = new HashSet<>(map.keySet()); for (K dk : ks) { - if (mapUsage.get(dk) + lifespan() < timeS()) { - onRemove(dk, map.get(dk)); + if (mapUsage.get(dk) + lifeSpan < timeS()) { + removal.accept(dk, map.get(dk)); map.remove(dk); mapUsage.remove(dk); } diff --git a/src/main/java/cam72cam/immersiverailroading/render/rail/RailBaseOverlayRender.java b/src/main/java/cam72cam/immersiverailroading/render/rail/RailBaseOverlayRender.java index 801d3b702..d85e12f5a 100644 --- a/src/main/java/cam72cam/immersiverailroading/render/rail/RailBaseOverlayRender.java +++ b/src/main/java/cam72cam/immersiverailroading/render/rail/RailBaseOverlayRender.java @@ -11,16 +11,7 @@ import java.util.List; public class RailBaseOverlayRender { - private static final ExpireableMap cache = new ExpireableMap() { - @Override - public int lifespan() { - return 1; - } - @Override - public boolean sliding() { - return false; - } - }; + private static final ExpireableMap cache = new ExpireableMap<>(1, false); private static DirectDraw doDraw(RailInfo info, List tracks, Vec3i pos) { DirectDraw draw = new DirectDraw(); diff --git a/src/main/java/cam72cam/immersiverailroading/render/rail/RailBuilderRender.java b/src/main/java/cam72cam/immersiverailroading/render/rail/RailBuilderRender.java index 10179a23e..42271a439 100644 --- a/src/main/java/cam72cam/immersiverailroading/render/rail/RailBuilderRender.java +++ b/src/main/java/cam72cam/immersiverailroading/render/rail/RailBuilderRender.java @@ -3,26 +3,18 @@ import cam72cam.immersiverailroading.model.TrackModel; import cam72cam.immersiverailroading.registry.DefinitionManager; import cam72cam.immersiverailroading.render.ExpireableMap; +import cam72cam.immersiverailroading.track.VecYPR; import cam72cam.mod.MinecraftClient; -import cam72cam.mod.render.opengl.VBO; -import cam72cam.mod.render.obj.OBJRender; -import cam72cam.immersiverailroading.track.BuilderBase.VecYawPitch; import cam72cam.immersiverailroading.util.RailInfo; import cam72cam.mod.render.opengl.RenderState; -import util.Matrix4; +import cam72cam.mod.render.opengl.VBO; import java.util.List; -import java.util.stream.Collectors; public class RailBuilderRender { - private static final ExpireableMap cache = new ExpireableMap() { - @Override - public void onRemove(String key, VBO value) { - value.free(); - } - }; + private static final ExpireableMap cache = new ExpireableMap<>((k, v) -> v.free()); - public static void renderRailBuilder(RailInfo info, List renderData, RenderState state) { + public static void renderRailBuilder(RailInfo info, List renderData, RenderState state) { TrackModel model = DefinitionManager.getTrack(info.settings.track, info.settings.gauge.value()); if (model == null) { return; @@ -30,32 +22,7 @@ public static void renderRailBuilder(RailInfo info, List renderData VBO cached = cache.get(info.uniqueID); if (cached == null) { - OBJRender.Builder builder = model.binder().builder(); - - for (VecYawPitch piece : renderData) { - Matrix4 m = new Matrix4(); - //m.rotate(Math.toRadians(info.placementInfo.yaw), 0, 1, 0); - m.translate(piece.x, piece.y, piece.z); - m.rotate(Math.toRadians(piece.getYaw()), 0, 1, 0); - m.rotate(Math.toRadians(piece.getPitch()), 1, 0, 0); - m.rotate(Math.toRadians(-90), 0, 1, 0); - - if (piece.getLength() != -1) { - m.scale(piece.getLength() / info.settings.gauge.scale(), 1, 1); - } - double scale = info.settings.gauge.scale(); - m.scale(scale, scale, scale); - - if (piece.getGroups().size() != 0) { - List groups = model.groups().stream() - .filter(group -> piece.getGroups().stream().anyMatch(group::contains)) - .collect(Collectors.toList()); - builder.draw(groups, m); - } else { - builder.draw(m); - } - } - cached = builder.build(); + cached = model.getModel(info, renderData); cache.put(info.uniqueID, cached); } diff --git a/src/main/java/cam72cam/immersiverailroading/render/rail/RailRender.java b/src/main/java/cam72cam/immersiverailroading/render/rail/RailRender.java index 734e14507..24441724d 100644 --- a/src/main/java/cam72cam/immersiverailroading/render/rail/RailRender.java +++ b/src/main/java/cam72cam/immersiverailroading/render/rail/RailRender.java @@ -1,6 +1,7 @@ package cam72cam.immersiverailroading.render.rail; import cam72cam.immersiverailroading.render.ExpireableMap; +import cam72cam.immersiverailroading.track.VecYPR; import cam72cam.immersiverailroading.track.BuilderBase; import cam72cam.immersiverailroading.track.TrackBase; import cam72cam.immersiverailroading.util.RailInfo; @@ -30,7 +31,7 @@ public class RailRender { private final RailInfo info; private boolean isLoaded; private boolean isLoading; - private List renderData; + private List renderData; private List tracks; private RailRender(RailInfo info) { diff --git a/src/main/java/cam72cam/immersiverailroading/tile/TileRailBase.java b/src/main/java/cam72cam/immersiverailroading/tile/TileRailBase.java index c205ef59b..ae616156c 100644 --- a/src/main/java/cam72cam/immersiverailroading/tile/TileRailBase.java +++ b/src/main/java/cam72cam/immersiverailroading/tile/TileRailBase.java @@ -251,11 +251,28 @@ public void load(TagCompound nbt) { if (!nbt.hasKey("railHeight")) { railHeight = bedHeight; } + case 4: + if (this instanceof TileRail) { + TileRail tr = ((TileRail) this); + if (tr.info.settings.type == TrackItems.SLOPE && tr.info.customInfo != null && tr.info.customInfo.placementPosition != null) { + // Force to 1 block offset + tr.info = tr.info.with(mod -> { + Vec3d placement = mod.customInfo.placementPosition; + Vec3d control = mod.customInfo.control; + mod.customInfo = new PlacementInfo( + new Vec3d(placement.x, mod.placementInfo.placementPosition.y+1, placement.z), + mod.customInfo.direction, + mod.customInfo.yaw, + control == null ? null : new Vec3d(control.x, mod.placementInfo.placementPosition.y+1, control.z) + ); + }); + } + } } } @Override public void save(TagCompound nbt) { - nbt.setInteger("version", 4); + nbt.setInteger("version", 5); } public TileRail getParentTile() { @@ -300,10 +317,10 @@ public boolean getWillBeReplaced() { return this.willBeReplaced; } - public void cleanSnow() { + public void cleanSnow(int snowLevel) { int snow = this.getSnowLayers(); - if (snow > 1) { - this.setSnowLayers(1); + if (snow > snowLevel) { + this.setSnowLayers(snowLevel); int snowDown = snow -1; for (int i = 1; i <= 3; i ++) { Facing[] horiz = Facing.values().clone(); @@ -943,7 +960,7 @@ public boolean onClick(Player player, Player.Hand hand, Facing facing, Vec3d hit } if (stack.isValidTool(ToolType.SHOVEL)) { if (this.getWorld().isServer) { - this.cleanSnow(); + this.cleanSnow(1); this.setSnowLayers(0); stack.damageItem(1, player); } diff --git a/src/main/java/cam72cam/immersiverailroading/tile/TileRailPreview.java b/src/main/java/cam72cam/immersiverailroading/tile/TileRailPreview.java index ed7cfe248..bbad44966 100644 --- a/src/main/java/cam72cam/immersiverailroading/tile/TileRailPreview.java +++ b/src/main/java/cam72cam/immersiverailroading/tile/TileRailPreview.java @@ -4,11 +4,13 @@ import cam72cam.immersiverailroading.items.nbt.RailSettings; import cam72cam.immersiverailroading.library.GuiTypes; import cam72cam.immersiverailroading.library.TrackDirection; +import cam72cam.immersiverailroading.library.TrackItems; import cam72cam.immersiverailroading.net.PreviewRenderPacket; import cam72cam.immersiverailroading.track.IIterableTrack; import cam72cam.immersiverailroading.util.BlockUtil; import cam72cam.immersiverailroading.util.PlacementInfo; import cam72cam.immersiverailroading.util.RailInfo; +import cam72cam.immersiverailroading.util.VecUtil; import cam72cam.mod.block.BlockEntityTickable; import cam72cam.mod.entity.Player; import cam72cam.mod.entity.boundingbox.IBoundingBox; @@ -71,19 +73,36 @@ public void setCustomInfo(PlacementInfo info) { this.customInfo = info; if (customInfo != null) { RailSettings settings = RailSettings.from(item); - double lx = Math.abs(customInfo.placementPosition.x - placementInfo.placementPosition.x); - double lz = Math.abs(customInfo.placementPosition.z - placementInfo.placementPosition.z); - switch (settings.type) { - case TURN: - settings = settings.with(b -> { - double length = (lx + lz )/2+1; - length *= 90/b.degrees; - b.length = (int) Math.round(length); - }); - break; - case STRAIGHT: - case SLOPE: - settings = settings.with(b -> b.length = (int) Math.round(Math.max(lx, lz) + 1)); + if(settings.type ==TrackItems.TURN + || settings.type == TrackItems.STRAIGHT + || settings.type == TrackItems.SLOPE){ + Vec3d placeOffset = new Vec3d( + customInfo.placementPosition.x - placementInfo.placementPosition.x, + 0, + customInfo.placementPosition.z - placementInfo.placementPosition.z + ); + float yaw = settings.type == TrackItems.TURN + ? placementInfo.yaw + ((settings.direction == TrackDirection.LEFT ? -1 : 1) * (settings.degrees / 2)) //Calculate arc direction for turn + : placementInfo.yaw; //Simply use its yaw + Vec3d unit = new Vec3d(0, 0, 1).rotateYaw(yaw); + int shadowLength = (int) Math.round(VecUtil.dotProduct(placeOffset, unit)); + int length; + + switch (settings.type) { + case TURN: + //Transform it back to radius + double sin = Math.sin(Math.toRadians(settings.degrees / 2)); + length = sin != 0d + ? Math.max(1, (int) ((shadowLength / 2d) / sin)) + 1 + : 2; + break; + case STRAIGHT: + case SLOPE: + default: + length = Math.max(0, shadowLength) + 1; + break; + } + settings = settings.with(b -> b.length = length); } settings.write(item); diff --git a/src/main/java/cam72cam/immersiverailroading/track/BuilderBase.java b/src/main/java/cam72cam/immersiverailroading/track/BuilderBase.java index bb05b01c7..be75a6669 100644 --- a/src/main/java/cam72cam/immersiverailroading/track/BuilderBase.java +++ b/src/main/java/cam72cam/immersiverailroading/track/BuilderBase.java @@ -8,14 +8,12 @@ import cam72cam.immersiverailroading.util.BlockUtil; import cam72cam.immersiverailroading.util.RailInfo; import cam72cam.mod.item.ItemStack; -import cam72cam.mod.math.Vec3d; import cam72cam.mod.math.Vec3i; import cam72cam.mod.util.Facing; import cam72cam.immersiverailroading.thirdparty.trackapi.ITrack; import cam72cam.mod.world.World; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; //TODO @cam72cam use Vec3i and Vec3i @@ -41,40 +39,7 @@ public BuilderBase(RailInfo info, World world, Vec3i pos) { parent_pos = pos; } - public class VecYawPitch extends Vec3d { - public final float yaw; - public final float pitch; - public final float length; - public final List groups; - - public VecYawPitch(double xIn, double yIn, double zIn, float yaw, String... groups) { - this(xIn, yIn, zIn, yaw, 0, groups); - } - public VecYawPitch(double xIn, double yIn, double zIn, float yaw, float pitch, String... groups) { - this(xIn, yIn, zIn, yaw, pitch, -1, groups); - } - public VecYawPitch(double xIn, double yIn, double zIn, float yaw, float pitch, float length, String... groups) { - super(xIn, yIn, zIn); - this.yaw = yaw; - this.groups = Arrays.asList(groups); - this.pitch = pitch; - this.length = length; - } - public float getYaw() { - return this.yaw; - } - public float getPitch() { - return this.pitch; - } - public float getLength() { - return this.length; - } - public List getGroups() { - return this.groups; - } - } - - public abstract List getRenderData(); + public abstract List getRenderData(); public boolean canBuild() { for(TrackBase track : tracks) { diff --git a/src/main/java/cam72cam/immersiverailroading/track/BuilderCrossing.java b/src/main/java/cam72cam/immersiverailroading/track/BuilderCrossing.java index 848d50783..80f329221 100644 --- a/src/main/java/cam72cam/immersiverailroading/track/BuilderCrossing.java +++ b/src/main/java/cam72cam/immersiverailroading/track/BuilderCrossing.java @@ -3,6 +3,7 @@ import java.util.ArrayList; import java.util.List; +import cam72cam.immersiverailroading.library.TrackModelPart; import cam72cam.immersiverailroading.util.RailInfo; import cam72cam.immersiverailroading.util.VecUtil; import cam72cam.mod.math.Vec3d; @@ -32,27 +33,27 @@ public BuilderCrossing(RailInfo info, World world, Vec3i pos) { } @Override - public List getRenderData() { + public List getRenderData() { - List data = new ArrayList(); + List data = new ArrayList<>(); float angle = 0; double trackOffset = (1-info.settings.gauge.scale())/4; Vec3d pos = VecUtil.rotateWrongYaw(Vec3d.ZERO, angle-90); - data.add(new VecYawPitch(pos.x, pos.y, pos.z, -angle, 0, info.settings.length, "RAIL_RIGHT", "RAIL_LEFT")); + data.add(new VecYPR(pos.x, pos.y, pos.z, -angle, 0, 0, info.settings.length, TrackModelPart.RAIL_RIGHT, TrackModelPart.RAIL_LEFT)); for (double i = -trackOffset; i < info.settings.length - trackOffset; i+=info.settings.gauge.scale()) { pos = VecUtil.rotateWrongYaw(new Vec3d(0, 0, i-0.25), angle-90); - data.add(new VecYawPitch(pos.x, pos.y, pos.z-1, -angle, "RAIL_BASE")); + data.add(new VecYPR(pos.x, pos.y, pos.z-1, -angle, TrackModelPart.RAIL_BASE)); } angle -= 90; pos = VecUtil.rotateWrongYaw(new Vec3d(0, 0, 0), angle-90); - data.add(new VecYawPitch(pos.x, pos.y, pos.z, -angle, 0, info.settings.length, "RAIL_RIGHT", "RAIL_LEFT")); + data.add(new VecYPR(pos.x, pos.y, pos.z, -angle, 0, 0, info.settings.length, TrackModelPart.RAIL_RIGHT, TrackModelPart.RAIL_LEFT)); for (double i = -trackOffset; i < info.settings.length - trackOffset; i+=info.settings.gauge.scale()) { pos = VecUtil.rotateWrongYaw(new Vec3d(0, 0, i-0.25), angle-90); - data.add(new VecYawPitch(pos.x-1, pos.y, pos.z, -angle, "RAIL_BASE")); + data.add(new VecYPR(pos.x-1, pos.y, pos.z, -angle, TrackModelPart.RAIL_BASE)); } return data; diff --git a/src/main/java/cam72cam/immersiverailroading/track/BuilderCubicCurve.java b/src/main/java/cam72cam/immersiverailroading/track/BuilderCubicCurve.java index 958da6f6c..aa7d03675 100644 --- a/src/main/java/cam72cam/immersiverailroading/track/BuilderCubicCurve.java +++ b/src/main/java/cam72cam/immersiverailroading/track/BuilderCubicCurve.java @@ -9,6 +9,7 @@ import cam72cam.mod.math.Vec3d; import cam72cam.mod.math.Vec3i; import cam72cam.mod.world.World; +import org.apache.commons.lang3.tuple.Pair; import java.util.ArrayList; import java.util.Collections; @@ -47,7 +48,7 @@ public BuilderCubicCurve(RailInfo info, World world, Vec3i pos, boolean endOfTra RailInfo subInfo = new RailInfo(info.settings.with(b -> b.type = TrackItems.CUSTOM), startPos, endPos, SwitchState.NONE, SwitchState.NONE, 0); BuilderCubicCurve subBuilder = new BuilderCubicCurve(subInfo, world, sPos); - if (subBuilders.size() != 0) { + if (!subBuilders.isEmpty()) { for (TrackBase track : subBuilder.tracks) { if (track instanceof TrackRail) { track.overrideParent(subBuilders.get(0).getParentPos()); @@ -61,7 +62,7 @@ public BuilderCubicCurve(RailInfo info, World world, Vec3i pos, boolean endOfTra } } - private HashMap> cache; + private HashMap>> cache; public CubicCurve getCurve() { Vec3d nextPos = new Vec3d(new Vec3i(VecUtil.fromYaw(info.settings.length, info.placementInfo.yaw + 45))); @@ -98,23 +99,42 @@ public CubicCurve getCurve() { } @Override - public List getPath(double stepSize) { + public List getPath(double stepSize) { + return getPathForRender(stepSize).getRight(); + } + + @Override + public Pair> getPathForRender(double targetStepSize) { if (cache == null) { cache = new HashMap<>(); } - if (cache.containsKey(stepSize)) { - return cache.get(stepSize); + if (cache.containsKey(targetStepSize)) { + return cache.get(targetStepSize); } - List res = new ArrayList<>(); + List res = new ArrayList<>(); CubicCurve curve = getCurve(); // HACK for super long curves // Skip the super long calculation since it'll be overridden anyways curve = curve.subsplit(200).get(0); + double length = curve.lengthWithCache(1000); + int count = (int) (length / targetStepSize);//Adapt the length + double mod = (length / targetStepSize) % 1; + if(mod > 0.6){ + count += 1; + } + double stepSize = length / count; + if (count * 3 > 1000){//There may be over 1 pieces in the same cache section, rebuild cache + curve.lengthWithCache(count * 3); + } + List points = curve.toList(stepSize); + if(count == 0){//Meaning stepSize must be NaN, caused by curve length == 0 + stepSize = targetStepSize; + } for(int i = 0; i < points.size(); i++) { Vec3d p = points.get(i); float yaw; @@ -125,7 +145,7 @@ public List getPath(double stepSize) { } else if (i == points.size()-1) { Vec3d next = points.get(i-1); pitch = (float) Math.toDegrees(Math.atan2(next.y - p.y, next.distanceTo(p))); - yaw = curve.angleStop(); + yaw = curve.angleStop(); } else if (i == 0) { Vec3d next = points.get(i+1); pitch = (float) -Math.toDegrees(Math.atan2(next.y - p.y, next.distanceTo(p))); @@ -136,10 +156,10 @@ public List getPath(double stepSize) { pitch = (float) -Math.toDegrees(Math.atan2(next.y - prev.y, next.distanceTo(prev))); yaw = VecUtil.toYaw(points.get(i+1).subtract(points.get(i-1))); } - res.add(new PosStep(p, yaw, pitch)); + res.add(new VecYPR(p, yaw, pitch)); } - cache.put(stepSize, res); - return cache.get(stepSize); + cache.put(targetStepSize, Pair.of(stepSize, res)); + return cache.get(targetStepSize); } /* OVERRIDES */ @@ -235,17 +255,14 @@ public List getTracksForFloating() { } @Override - public List getRenderData() { + public List getRenderData() { if (subBuilders == null) { return super.getRenderData(); } else { - List data = new ArrayList<>(); + List data = new ArrayList<>(); for (BuilderBase curve : subBuilders.subList(0, Math.min(subBuilders.size(), 3))) { Vec3d offset = new Vec3d(curve.pos.subtract(pos)); - for (VecYawPitch rd : curve.getRenderData()) { - rd = new VecYawPitch(rd.x + offset.x, rd.y + offset.y, rd.z + offset.z, rd.yaw, rd.pitch, rd.length); - data.add(rd); - } + curve.getRenderData().stream().map(rd -> rd.add(offset)).forEach(data::add); } return data; } diff --git a/src/main/java/cam72cam/immersiverailroading/track/BuilderIterator.java b/src/main/java/cam72cam/immersiverailroading/track/BuilderIterator.java index 8487f0e67..0ec0fadff 100644 --- a/src/main/java/cam72cam/immersiverailroading/track/BuilderIterator.java +++ b/src/main/java/cam72cam/immersiverailroading/track/BuilderIterator.java @@ -8,6 +8,7 @@ import cam72cam.immersiverailroading.Config; import cam72cam.immersiverailroading.library.SwitchState; import cam72cam.immersiverailroading.library.TrackDirection; +import cam72cam.immersiverailroading.library.TrackModelPart; import cam72cam.immersiverailroading.util.MathUtil; import cam72cam.mod.math.Vec3d; import cam72cam.mod.math.Vec3i; @@ -28,7 +29,11 @@ public BuilderIterator(RailInfo info, World world, Vec3i pos) { this(info, world, pos, false); } - public abstract List getPath(double stepSize); + //Not sensitive to dynamic stepSize, like physics system + public abstract List getPath(double stepSize); + + //Sensitive to dynamic stepSize, return the changed stepSize as well + public abstract Pair> getPathForRender(double targetStepSize); public BuilderIterator(RailInfo info, World world, Vec3i pos, boolean endOfTrack) { super(info, world, pos); @@ -49,9 +54,9 @@ public BuilderIterator(RailInfo info, World world, Vec3i pos, boolean endOfTrack double clamp = 0.17 * info.settings.gauge.scale(); float heightOffset = (float) ((info.placementInfo.placementPosition.y) % 1); - List path = getPath(0.25); - PosStep start = path.get(0); - PosStep end = path.get(path.size()-1); + List path = getPath(0.25); + VecYPR start = path.get(0); + VecYPR end = path.get(path.size()-1); Vec3d placeOff = new Vec3d( Math.abs(MathUtil.trueModulus(info.placementInfo.placementPosition.x, 1)), @@ -62,7 +67,7 @@ public BuilderIterator(RailInfo info, World world, Vec3i pos, boolean endOfTrack int mainZ = (int) Math.floor(path.get(path.size()/2).z+placeOff.z); int flexDist = (int) Math.max(1, 3 * (0.5 + info.settings.gauge.scale()/2)); - for (PosStep cur : path) { + for (VecYPR cur : path) { Vec3d gagPos = cur; boolean isFlex = gagPos.distanceTo(start) < flexDist || gagPos.distanceTo(end) < flexDist; @@ -70,7 +75,7 @@ public BuilderIterator(RailInfo info, World world, Vec3i pos, boolean endOfTrack gagPos = gagPos.add(0, heightOffset, 0); for (double q = -horiz; q <= horiz; q+=0.1) { - Vec3d nextUp = VecUtil.fromYaw(q, 90 + cur.yaw); + Vec3d nextUp = VecUtil.fromYaw(q, 90 + cur.getYaw()); int posX = (int)Math.floor(gagPos.x+nextUp.x+placeOff.x); int posZ = (int)Math.floor(gagPos.z+nextUp.z+placeOff.z); double height = 0; @@ -120,7 +125,7 @@ public BuilderIterator(RailInfo info, World world, Vec3i pos, boolean endOfTrack } catch (SerializationException e) { throw new RuntimeException("Invalid track builder", e); } - throw new RuntimeException("Invalid track builder " + debug.toString()); + throw new RuntimeException("Invalid track builder " + debug); } Vec3i mainPos = new Vec3i(mainX, yOffset.get(Pair.of(mainX, mainZ)), mainZ); @@ -147,8 +152,8 @@ public BuilderIterator(RailInfo info, World world, Vec3i pos, boolean endOfTrack @Override public List getTracksForRender() { - return this.tracks; - } + return super.getTracksForRender(); + } private static float delta(float a, float b) { float angle = (float) Math.toDegrees(Math.toRadians(a) - Math.toRadians(b)); @@ -162,18 +167,21 @@ private static float delta(float a, float b) { } @Override - public List getRenderData() { - List data = new ArrayList(); + public List getRenderData() { + List data = new ArrayList<>(); double scale = info.settings.gauge.scale(); - List points = getPath(scale * info.getTrackModel().spacing); + Pair> pair = getPathForRender(scale * info.getTrackModel().spacing); + List points = pair.getRight(); + float renderScale = (float) (pair.getLeft() / info.getTrackModel().spacing); + renderScale *= 1.005f;//Avoid some gaps boolean switchStraight = info.switchState == SwitchState.STRAIGHT; int switchSize = 0; TrackDirection direction = info.placementInfo.direction; if (switchStraight ) { for (int i = 0; i < points.size(); i++) { - PosStep cur = points.get(i); + VecYPR cur = points.get(i); Vec3d flatPos = VecUtil.rotateYaw(cur, -info.placementInfo.yaw); if (Math.abs(flatPos.z) >= 0.5 * scale) { switchSize = i; @@ -183,18 +191,18 @@ public List getRenderData() { } for (int i = 0; i < points.size(); i++) { - PosStep cur = points.get(i); - PosStep switchPos = cur; + VecYPR cur = points.get(i); + VecYPR switchPos = cur; if (switchStraight ) { double switchOffset = 1 - (i / (double)switchSize); if (switchOffset > 0) { double dist = 0.2 * switchOffset * scale * info.getTrackModel().spacing; - Vec3d offset = VecUtil.fromYaw(dist, cur.yaw + 90 + info.placementInfo.direction.toYaw()); + Vec3d offset = VecUtil.fromYaw(dist, cur.getYaw() + 90 + info.placementInfo.direction.toYaw()); double offsetAngle = Math.toDegrees(0.2/switchSize); // This line took a whole page of scribbled math if (direction == TrackDirection.RIGHT) { offsetAngle = -offsetAngle; } - switchPos = new PosStep(cur.add(offset), cur.yaw + (float)offsetAngle, cur.pitch); + switchPos = new VecYPR(cur.add(offset), cur.getYaw() + (float)offsetAngle, cur.getPitch()); } } @@ -202,29 +210,30 @@ public List getRenderData() { if (points.size() == 1) { angle = 0; } else if (i+1 == points.size()) { - PosStep next = points.get(i-1); - angle = delta(next.yaw, cur.yaw); + VecYPR next = points.get(i-1); + angle = delta(next.getYaw(), cur.getYaw()); angle *= 2; } else if (i == 0) { - PosStep next = points.get(i+1); - angle = delta(cur.yaw, next.yaw); + VecYPR next = points.get(i+1); + angle = delta(cur.getYaw(), next.getYaw()); angle *= 2; } else { - PosStep prev = points.get(i-1); - PosStep next = points.get(i+1); - angle = delta(prev.yaw, next.yaw); + VecYPR prev = points.get(i-1); + VecYPR next = points.get(i+1); + angle = delta(prev.getYaw(), next.getYaw()); } if (angle != 0) { + VecYPR vec = new VecYPR(cur, renderScale, TrackModelPart.RAIL_BASE); if (direction == TrackDirection.RIGHT) { - data.add(new VecYawPitch(switchPos.x, switchPos.y, switchPos.z, switchPos.yaw, switchPos.pitch, (1 - angle / 180) * (float) info.settings.gauge.scale(), "RAIL_LEFT")); - data.add(new VecYawPitch(cur.x, cur.y, cur.z, cur.yaw, cur.pitch, (1 + angle / 180) * (float) info.settings.gauge.scale(), "RAIL_RIGHT")); + vec.addChild(new VecYPR(switchPos, (1 - angle / 180) * renderScale, TrackModelPart.RAIL_LEFT)); + vec.addChild(new VecYPR(cur, (1 + angle / 180) * renderScale, TrackModelPart.RAIL_RIGHT)); } else { - data.add(new VecYawPitch(cur.x, cur.y, cur.z, cur.yaw, cur.pitch, (1 - angle / 180) * (float) info.settings.gauge.scale(), "RAIL_LEFT")); - data.add(new VecYawPitch(switchPos.x, switchPos.y, switchPos.z, switchPos.yaw, switchPos.pitch, (1 + angle / 180) * (float) info.settings.gauge.scale(), "RAIL_RIGHT")); + vec.addChild(new VecYPR(cur, (1 - angle / 180) * renderScale, TrackModelPart.RAIL_LEFT)); + vec.addChild(new VecYPR(switchPos, (1 + angle / 180) * renderScale, TrackModelPart.RAIL_RIGHT)); } - data.add(new VecYawPitch(cur.x, cur.y, cur.z, cur.yaw, cur.pitch, "RAIL_BASE")); + data.add(vec); } else { - data.add(new VecYawPitch(cur.x, cur.y, cur.z, cur.yaw, cur.pitch)); + data.add(new VecYPR(cur, renderScale)); } } diff --git a/src/main/java/cam72cam/immersiverailroading/track/BuilderSlope.java b/src/main/java/cam72cam/immersiverailroading/track/BuilderSlope.java index 673809b09..844e53299 100644 --- a/src/main/java/cam72cam/immersiverailroading/track/BuilderSlope.java +++ b/src/main/java/cam72cam/immersiverailroading/track/BuilderSlope.java @@ -12,7 +12,11 @@ public BuilderSlope(RailInfo info, World world, Vec3i pos) { @Override public CubicCurve getCurve() { CubicCurve curve = super.getCurve(); - curve = new CubicCurve(curve.p1, curve.ctrl1, curve.ctrl2.add(0, 1, 0), curve.p2.add(0, 1, 0)); + double delta = 1; + if (info.customInfo != null && info.customInfo.placementPosition != null && info.customInfo != info.placementInfo) { + delta = -info.placementInfo.placementPosition.subtract(info.customInfo.placementPosition).y; + } + curve = new CubicCurve(curve.p1, curve.ctrl1, curve.ctrl2.add(0, delta, 0), curve.p2.add(0, delta, 0)); return curve.linearize(info.settings.smoothing); } } diff --git a/src/main/java/cam72cam/immersiverailroading/track/BuilderSwitch.java b/src/main/java/cam72cam/immersiverailroading/track/BuilderSwitch.java index cd0eb6d3d..aa611010c 100644 --- a/src/main/java/cam72cam/immersiverailroading/track/BuilderSwitch.java +++ b/src/main/java/cam72cam/immersiverailroading/track/BuilderSwitch.java @@ -135,14 +135,14 @@ public List getTracksForRender() { } @Override - public List getRenderData() { - List data = straightBuilder.getRenderData(); + public List getRenderData() { + List data = straightBuilder.getRenderData(); data.addAll(turnBuilder.getRenderData()); return data; } @Override - public List getPath(double stepSize) { + public List getPath(double stepSize) { return realStraightBuilder.getPath(stepSize); } } \ No newline at end of file diff --git a/src/main/java/cam72cam/immersiverailroading/track/BuilderTransferTable.java b/src/main/java/cam72cam/immersiverailroading/track/BuilderTransferTable.java index 96736beb0..7a79bdbc0 100644 --- a/src/main/java/cam72cam/immersiverailroading/track/BuilderTransferTable.java +++ b/src/main/java/cam72cam/immersiverailroading/track/BuilderTransferTable.java @@ -2,6 +2,7 @@ import cam72cam.immersiverailroading.Config; import cam72cam.immersiverailroading.library.Gauge; +import cam72cam.immersiverailroading.library.TrackModelPart; import cam72cam.immersiverailroading.util.BlockUtil; import cam72cam.immersiverailroading.util.RailInfo; import cam72cam.mod.math.Rotation; @@ -63,23 +64,24 @@ public List getTracksForRender() { } @Override - public List getRenderData() { - List list = new ArrayList<>(); + public List getRenderData() { + List list = new ArrayList<>(); if (info.itemHeld) { for (int i = 0; i < info.settings.transfertableEntryCount; i++) { Vec3i head = new Vec3i(-i * info.settings.transfertableEntrySpacing, 1, 0) .rotate(Rotation.from(info.placementInfo.facing())); - list.add(new VecYawPitch(head.x, head.y, head.z, info.placementInfo.facing().getAngle())); + list.add(new VecYPR(head.x, head.y, head.z, info.placementInfo.facing().getAngle())); Vec3i tail = new Vec3i(-i * info.settings.transfertableEntrySpacing, 1, info.settings.length - 1) .rotate(Rotation.from(info.placementInfo.facing())); - list.add(new VecYawPitch(tail.x, tail.y, tail.z, info.placementInfo.facing().getAngle())); + list.add(new VecYPR(tail.x, tail.y, tail.z, info.placementInfo.facing().getAngle())); } } Vec3d center = new Vec3d(-info.tablePos, 1, info.settings.length / 2d - 0.5).rotateYaw(-info.placementInfo.facing().getAngle() + 180); - list.add(new VecYawPitch(center.x, center.y, center.z, info.placementInfo.facing().getAngle(), 0, info.settings.length, "RAIL_RIGHT", "RAIL_LEFT")); + list.add(new VecYPR(center.x, center.y, center.z, info.placementInfo.facing().getAngle(), 0, 0, info.settings.length, + TrackModelPart.RAIL_LEFT, TrackModelPart.RAIL_RIGHT, TrackModelPart.TABLE)); return list; } diff --git a/src/main/java/cam72cam/immersiverailroading/track/BuilderTurnTable.java b/src/main/java/cam72cam/immersiverailroading/track/BuilderTurnTable.java index 1f68c44aa..06430ef46 100644 --- a/src/main/java/cam72cam/immersiverailroading/track/BuilderTurnTable.java +++ b/src/main/java/cam72cam/immersiverailroading/track/BuilderTurnTable.java @@ -5,7 +5,8 @@ import java.util.List; import cam72cam.immersiverailroading.library.Gauge; -import cam72cam.immersiverailroading.util.PlacementInfo; +import cam72cam.immersiverailroading.library.TrackModelPart; +import cam72cam.immersiverailroading.util.*; import cam72cam.mod.math.Rotation; import cam72cam.mod.math.Vec3d; import cam72cam.mod.math.Vec3i; @@ -13,9 +14,6 @@ import org.apache.commons.lang3.tuple.Pair; import cam72cam.immersiverailroading.Config.ConfigBalance; -import cam72cam.immersiverailroading.util.BlockUtil; -import cam72cam.immersiverailroading.util.RailInfo; -import cam72cam.immersiverailroading.util.VecUtil; public class BuilderTurnTable extends BuilderBase { protected HashSet> positions; @@ -77,19 +75,20 @@ public List getTracksForRender() { } @Override - public List getRenderData() { - List data = new ArrayList<>(); + public List getRenderData() { + List data = new ArrayList<>(); if (info.itemHeld) { for (float angle = 0; angle < 360; angle += (90f / PlacementInfo.segmentation())) { Vec3d gagPos = VecUtil.rotateWrongYaw(new Vec3d(0, 0, info.settings.length), angle - 90); - data.add(new VecYawPitch(gagPos.x + offset.x, gagPos.y + offset.y, gagPos.z + offset.z, -angle)); + data.add(new VecYPR(gagPos.x + offset.x, gagPos.y + offset.y, gagPos.z + offset.z, -angle)); } } float angle = (float)info.tablePos - info.placementInfo.facing().getAngle(); - data.add(new VecYawPitch(offset.x, offset.y, offset.z, -angle, 0, info.settings.length * 2, "RAIL_RIGHT", "RAIL_LEFT")); - + data.add(new VecYPR(offset.x, offset.y, offset.z, -angle, 0, 0, info.settings.length * 2, + TrackModelPart.RAIL_LEFT, TrackModelPart.RAIL_RIGHT, TrackModelPart.TABLE)); + return data; } diff --git a/src/main/java/cam72cam/immersiverailroading/track/CubicCurve.java b/src/main/java/cam72cam/immersiverailroading/track/CubicCurve.java index 699c1e27f..6b73c21e0 100644 --- a/src/main/java/cam72cam/immersiverailroading/track/CubicCurve.java +++ b/src/main/java/cam72cam/immersiverailroading/track/CubicCurve.java @@ -7,7 +7,6 @@ import util.Matrix4; import java.util.ArrayList; -import java.util.Collections; import java.util.List; public class CubicCurve { @@ -16,6 +15,10 @@ public class CubicCurve { public final Vec3d ctrl2; public final Vec3d p2; + public double[] t; + public double[] len; + public int segment; + //http://spencermortensen.com/articles/bezier-circle/ public final static double c = 0.55191502449; @@ -73,69 +76,123 @@ public Pair split(double t) { } public Vec3d position(double t) { - Vec3d pt = Vec3d.ZERO; - pt = pt.add(p1. scale(1 * Math.pow(1-t, 3) * Math.pow(t, 0))); - pt = pt.add(ctrl1. scale(3 * Math.pow(1-t, 2) * Math.pow(t, 1))); - pt = pt.add(ctrl2. scale(3 * Math.pow(1-t, 1) * Math.pow(t, 2))); - pt = pt.add(p2. scale(1 * Math.pow(1-t, 0) * Math.pow(t, 3))); - return pt; + //Using Vec3d will cause almost 2850% performance decrease + double u = 1 - t; + + double d1 = u * u * u; + double d2 = 3 * u * u * t; + double d3 = 3 * u * t * t; + double d4 = t * t * t; + + double x = p1.x * d1 + ctrl1.x * d2 + ctrl2.x * d3 + p2.x * d4; + double y = p1.y * d1 + ctrl1.y * d2 + ctrl2.y * d3 + p2.y * d4; + double z = p1.z * d1 + ctrl1.z * d2 + ctrl2.z * d3 + p2.z * d4; + return new Vec3d(x, y, z); } - public List toList(double stepSize) { - List res = new ArrayList<>(); - List resRev = new ArrayList<>(); - res.add(p1); - if (p1.equals(p2)) { - return res; + public Vec3d derivative(double t){ + //WILL CAUSE 1000%+ decrease if using Vec3d + double u = 1 - t; + double d1 = 3 * u * u; + double d2 = 6 * u * t; + double d3 = 3 * t * t; + + double dx = d1 * (ctrl1.x - p1.x) + d2 * (ctrl2.x - ctrl1.x) + d3 * (p2.x - ctrl2.x); + double dy = d1 * (ctrl1.y - p1.y) + d2 * (ctrl2.y - ctrl1.y) + d3 * (p2.y - ctrl2.y); + double dz = d1 * (ctrl1.z - p1.z) + d2 * (ctrl2.z - ctrl1.z) + d3 * (p2.z - ctrl2.z); + + return new Vec3d(dx, dy, dz); + } + + public double lengthWithCache(int iterations){ + this.segment = iterations; + this.t = new double[segment + 10]; + this.len = new double[segment + 10]; + double length = 0.0; + double tStep = 1.0 / (double) iterations; + Vec3d prevDeriv = derivative(0); + double prevSpeed = prevDeriv.length(); + //Cache it + t[0] = 0.0; + len[0] = 0.0; + + for (int i = 1; i <= (double) iterations; i++) { + double pos = i * tStep; + Vec3d deriv = derivative(pos); + double speed = deriv.length(); + + length += (prevSpeed + speed) * tStep / 2.0; + t[i] = pos; + len[i] = length; + prevSpeed = speed; } + t[segment] = 1;//The final index + return length; + } - resRev.add(p2); - double precision = 5; + public double lengthInBetween(double start, double end, double iter){ + if(start == end){ + return 0; + } + double length = 0.0; + double tStep = (end - start) / iter; + Vec3d prevDeriv = derivative(start); + double prevSpeed = prevDeriv.length(); - double t = 0; - while (t <= 0.5) { - for (double i = 1; i < precision; i++) { - Vec3d prev = res.get(res.size()-1); + for (double i = start + tStep; i <= end; i+=tStep) { + Vec3d deriv = derivative(i); + double speed = deriv.length(); - double delta = (Math.pow(10, -i)); + length += (prevSpeed + speed) * tStep / 2.0; + prevSpeed = speed; + } + return length; + } - for (;t < 1 + delta; t+=delta) { - Vec3d pos = position(t); - if (pos.distanceTo(prev) > stepSize) { - // We passed it, just barely - t -= delta; - break; - } - } - } - res.add(position(t)); + public List toList(double stepSize) { + List result = new ArrayList<>(); + result.add(p1); + if(p1.equals(p2)){ + return result; } - double lt = t; - t = 1; + double lastLength = 0; + double error = 0.001 * stepSize; - while (t > lt) { - for (double i = 1; i < precision; i++) { - Vec3d prev = resRev.get(resRev.size()-1); + for (int i = 0; i < segment; i++) { + if(len[i] - lastLength <= stepSize && len[i+1] - lastLength > stepSize){ + double low = t[i]; + double high = t[i+1]; + double currentLen = len[i]; + double mid = (low + high) / 2; - double delta = (Math.pow(10, -i)); + for(int j = 1; j <= 7; j++){ + mid = (low + high) / 2; + double test = lengthInBetween(low, mid, 10); + if(Math.abs(currentLen + test - lastLength - stepSize) < error){ + break; + } - for (;t > lt - delta; t-=delta) { - Vec3d pos = position(t); - if (pos.distanceTo(prev) > stepSize) { - // We passed it, just barely - t += delta; + if(currentLen + test < lastLength + stepSize){ + low = mid; + currentLen += test; + } else if (currentLen + test > lastLength + stepSize) { + high = mid; + } else { break; } } - } - if (t > lt) { - resRev.add(position(t)); + + result.add(position(mid)); + lastLength = currentLen + lengthInBetween(low, mid, 10); } } - Collections.reverse(resRev); - res.addAll(resRev); - return res; + + if(len[segment] - lastLength >= 0.8 * stepSize){ + result.add(p2); + } + + return result; } public float angleStop() { diff --git a/src/main/java/cam72cam/immersiverailroading/track/IIterableTrack.java b/src/main/java/cam72cam/immersiverailroading/track/IIterableTrack.java index bb5223ed6..cb42da277 100644 --- a/src/main/java/cam72cam/immersiverailroading/track/IIterableTrack.java +++ b/src/main/java/cam72cam/immersiverailroading/track/IIterableTrack.java @@ -1,6 +1,5 @@ package cam72cam.immersiverailroading.track; -import cam72cam.immersiverailroading.ImmersiveRailroading; import cam72cam.immersiverailroading.util.RailInfo; import cam72cam.mod.math.Vec3d; import cam72cam.mod.math.Vec3i; @@ -8,7 +7,7 @@ import java.util.List; public interface IIterableTrack { - List getPath(double stepSize); + List getPath(double stepSize); List getSubBuilders(); @@ -18,7 +17,7 @@ default double offsetFromTrack(RailInfo info, Vec3i pos, Vec3d position) { Vec3d relative = position.subtract(info.placementInfo.placementPosition).subtract(pos); relative = relative.add(0, -(relative.y % 1), 0); - List positions = getPath(info.settings.gauge.scale() / 8); + List positions = getPath(info.settings.gauge.scale() / 8); /*double distSquared = 100 * 100; for (Vec3d gagPos : positions) { diff --git a/src/main/java/cam72cam/immersiverailroading/track/PosStep.java b/src/main/java/cam72cam/immersiverailroading/track/PosStep.java deleted file mode 100644 index f9a9ae813..000000000 --- a/src/main/java/cam72cam/immersiverailroading/track/PosStep.java +++ /dev/null @@ -1,18 +0,0 @@ -package cam72cam.immersiverailroading.track; - -import cam72cam.mod.math.Vec3d; - -public class PosStep extends Vec3d { - public final float yaw; - public final float pitch; - - public PosStep(double xIn, double yIn, double zIn, float yaw, float pitch) { - super(xIn, yIn, zIn); - this.yaw = yaw; - this.pitch = pitch; - } - - public PosStep(Vec3d orig, float angle, float pitch) { - this(orig.x, orig.y, orig.z, angle, pitch); - } -} diff --git a/src/main/java/cam72cam/immersiverailroading/track/VecYPR.java b/src/main/java/cam72cam/immersiverailroading/track/VecYPR.java new file mode 100644 index 000000000..6deb6a7a8 --- /dev/null +++ b/src/main/java/cam72cam/immersiverailroading/track/VecYPR.java @@ -0,0 +1,92 @@ +package cam72cam.immersiverailroading.track; + +import cam72cam.immersiverailroading.library.TrackModelPart; +import cam72cam.mod.math.Vec3d; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class VecYPR extends Vec3d { + private final float yaw; + private final float pitch; + private final float roll; + private final float length; + private final List parts; + private final List children; + + //Yaw + public VecYPR(Vec3d orig, float yaw, TrackModelPart... parts) { + this(orig.x, orig.y, orig.z, yaw, parts); + } + + public VecYPR(double xIn, double yIn, double zIn, float yaw, TrackModelPart... parts) { + this(xIn, yIn, zIn, yaw, 0, parts); + } + + //Pitch + public VecYPR(Vec3d orig, float yaw, float pitch, TrackModelPart... parts) { + this(orig.x, orig.y, orig.z, yaw, pitch, -1, parts); + } + + public VecYPR(double xIn, double yIn, double zIn, float yaw, float pitch, TrackModelPart... parts) { + this(xIn, yIn, zIn, yaw, pitch, -1, parts); + } + + //Length + public VecYPR(VecYPR other, float length, TrackModelPart... parts) { + this(other, other.yaw, other.pitch, length, parts); + } + + public VecYPR(Vec3d orig, float yaw, float pitch, float length, TrackModelPart... parts) { + this(orig.x, orig.y, orig.z, yaw, pitch, length, parts); + } + + public VecYPR(double xIn, double yIn, double zIn, float yaw, float pitch, float length, TrackModelPart... parts) { + this(xIn, yIn, zIn, yaw, pitch, length, 0, parts); + } + + //Roll + public VecYPR(double xIn, double yIn, double zIn, float yaw, float pitch, float length, float roll, TrackModelPart... parts) { + super(xIn, yIn, zIn); + this.yaw = yaw; + this.parts = Arrays.asList(parts); + this.pitch = pitch; + this.roll = roll; + this.length = length; + this.children = new ArrayList<>(); + } + + @Override + public VecYPR add(Vec3d other) { + return new VecYPR(this.x + other.x, this.y + other.y, this.z + other.z, this.yaw, this.pitch, this.length); + } + + public void addChild(VecYPR another) { + this.children.add(another); + } + + public float getYaw() { + return this.yaw; + } + + public float getPitch() { + return this.pitch; + } + + public float getRoll() { + return roll; + } + + public float getLength() { + return this.length; + } + + public List getParts() { + return this.parts; + } + + public List getChildren() { + return children; + } +} diff --git a/src/main/java/cam72cam/immersiverailroading/util/BlockUtil.java b/src/main/java/cam72cam/immersiverailroading/util/BlockUtil.java index 812d62c26..183254bae 100644 --- a/src/main/java/cam72cam/immersiverailroading/util/BlockUtil.java +++ b/src/main/java/cam72cam/immersiverailroading/util/BlockUtil.java @@ -1,11 +1,20 @@ package cam72cam.immersiverailroading.util; +import cam72cam.immersiverailroading.Config; import cam72cam.immersiverailroading.IRBlocks; import cam72cam.immersiverailroading.tile.TileRailBase; +import cam72cam.mod.item.Fuzzy; +import cam72cam.mod.item.ItemStack; import cam72cam.mod.math.Vec3i; import cam72cam.mod.world.World; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + public class BlockUtil { + private static List whitelist; + public static boolean canBeReplaced(World world, Vec3i pos, boolean allowFlex) { if (world.isReplaceable(pos)) { return true; @@ -25,4 +34,14 @@ public static boolean isIRRail(World world, Vec3i pos) { return world.isBlock(pos, IRBlocks.BLOCK_RAIL_GAG) || world.isBlock(pos, IRBlocks.BLOCK_RAIL); } + public static boolean isWhitelisted(World world, Vec3i pos) { + if (whitelist == null) { + whitelist = new ArrayList<>(); + Arrays.stream(Config.ConfigDamage.TrainsIgnoreBlocks).forEach(s -> whitelist.add(Fuzzy.get(s))); + } + + ItemStack stack = world.getItemStack(pos); + + return whitelist.stream().anyMatch(fuzzy -> fuzzy.matches(stack)); + } } diff --git a/src/main/java/cam72cam/immersiverailroading/util/MathUtil.java b/src/main/java/cam72cam/immersiverailroading/util/MathUtil.java index 1eb461f94..59140d932 100644 --- a/src/main/java/cam72cam/immersiverailroading/util/MathUtil.java +++ b/src/main/java/cam72cam/immersiverailroading/util/MathUtil.java @@ -37,4 +37,11 @@ public static int deltaMod(int source, int target, int mod) { a += a < -mod ? mod : 0; return a; } + + public static int gcd(int a, int b) { + if (b == 0) { + return a; + } + return gcd(b, a % b); + } } diff --git a/src/main/java/cam72cam/immersiverailroading/util/PlacementInfo.java b/src/main/java/cam72cam/immersiverailroading/util/PlacementInfo.java index b15ef2dc9..f0f03505f 100644 --- a/src/main/java/cam72cam/immersiverailroading/util/PlacementInfo.java +++ b/src/main/java/cam72cam/immersiverailroading/util/PlacementInfo.java @@ -6,7 +6,6 @@ import cam72cam.mod.item.ItemStack; import cam72cam.mod.math.Vec3d; import cam72cam.mod.math.Vec3i; -import cam72cam.mod.serialization.SerializationException; import cam72cam.mod.serialization.TagField; import cam72cam.mod.serialization.TagMapped; import cam72cam.mod.util.Facing; @@ -46,57 +45,56 @@ public PlacementInfo(ItemStack stack, float yawHead, Vec3d hit) { double hitX = hit.x % 1; double hitZ = hit.z % 1; - switch(settings.posType) { - case FIXED: - hitX = 0.5f; - hitZ = 0.5f; - break; - case PIXELS: - hitX = ((int)(hitX * 16)) / 16f; - hitZ = ((int)(hitZ * 16)) / 16f; - break; - case PIXELS_LOCKED: - hitX = ((int)(hitX * 16)) / 16f; - hitZ = ((int)(hitZ * 16)) / 16f; - - if (quarter != 0) { - break; - } - - switch (facing()) { - case EAST: - case WEST: - hitZ = 0.5f; - break; - case NORTH: - case SOUTH: + switch (settings.posType) { + case FIXED: hitX = 0.5f; - break; - default: - break; - } - break; - case SMOOTH: - // NOP - break; - case SMOOTH_LOCKED: - if (quarter != 0) { - break; - } - - switch (facing()) { - case EAST: - case WEST: hitZ = 0.5f; break; - case NORTH: - case SOUTH: - hitX = 0.5f; + case PIXELS: + hitX = ((int) (hitX * 16)) / 16f; + hitZ = ((int) (hitZ * 16)) / 16f; + //Fall through + case SMOOTH: + if (hit.z < 0) { + hitZ += 1; + } + if (hit.x < 0) { + hitX += 1; + } break; - default: + case PIXELS_LOCKED: + hitX = ((int) (hitX * 16)) / 16f; + hitZ = ((int) (hitZ * 16)) / 16f; + //Fall through + case SMOOTH_LOCKED: + if (quarter != 0) { + if (hit.z < 0) { + hitZ += 1; + } + if (hit.x < 0) { + hitX += 1; + } + break; + } + + switch (facing()) { + case EAST: + case WEST: + hitZ = 0.5f; + if (hit.x < 0) { + hitX += 1; + } + break; + case NORTH: + case SOUTH: + hitX = 0.5f; + if (hit.z < 0) { + hitZ += 1; + } + break; + default: + } break; - } - break; } this.placementPosition = new Vec3d(new Vec3i(hit)).add(hitX, 0, hitZ); diff --git a/src/main/java/cam72cam/immersiverailroading/util/RailInfo.java b/src/main/java/cam72cam/immersiverailroading/util/RailInfo.java index f8a696b7b..cd9cbfaf8 100644 --- a/src/main/java/cam72cam/immersiverailroading/util/RailInfo.java +++ b/src/main/java/cam72cam/immersiverailroading/util/RailInfo.java @@ -44,6 +44,10 @@ public RailInfo(RailSettings settings, PlacementInfo placementInfo, PlacementInf public RailInfo(RailSettings settings, PlacementInfo placementInfo, PlacementInfo customInfo, SwitchState switchState, SwitchState switchForced, double tablePos, boolean itemHeld) { if (customInfo == null) { customInfo = placementInfo; + //#1566: Use customInfo to adjust slope height + if (settings.type == TrackItems.SLOPE) { + customInfo = customInfo.offset(new Vec3i(0,1,0)); + } } this.settings = settings; diff --git a/src/main/java/cam72cam/immersiverailroading/util/VecUtil.java b/src/main/java/cam72cam/immersiverailroading/util/VecUtil.java index c34b312bc..c44745ee0 100644 --- a/src/main/java/cam72cam/immersiverailroading/util/VecUtil.java +++ b/src/main/java/cam72cam/immersiverailroading/util/VecUtil.java @@ -61,4 +61,8 @@ public static Vec3d fromWrongYawPitch(float distance, float rotationYaw, float r public static Vec3d between(Vec3d front, Vec3d rear) { return new Vec3d((front.x + rear.x) / 2, (front.y + rear.y) / 2, (front.z + rear.z) / 2); } + + public static double dotProduct(Vec3d a, Vec3d b) { + return a.x * b.x + a.y * b.y + a.z * b.z; + } } diff --git a/src/main/resources/assets/immersiverailroading/gui/default/cab_car.caml b/src/main/resources/assets/immersiverailroading/gui/default/cab_car.caml index 807bc4bb9..d93a3dc7a 100644 --- a/src/main/resources/assets/immersiverailroading/gui/default/cab_car.caml +++ b/src/main/resources/assets/immersiverailroading/gui/default/cab_car.caml @@ -62,7 +62,7 @@ element: element: # speed readout text = - value = "stat.speed stat.units_speed" + value = "stat.speed.2 stat.units_speed" height = 6 x = 30 y = 8 diff --git a/src/main/resources/assets/immersiverailroading/gui/default/diesel.caml b/src/main/resources/assets/immersiverailroading/gui/default/diesel.caml index c88068884..9c46837c4 100644 --- a/src/main/resources/assets/immersiverailroading/gui/default/diesel.caml +++ b/src/main/resources/assets/immersiverailroading/gui/default/diesel.caml @@ -91,7 +91,7 @@ element: element: # speed readout text = - value = "stat.speed stat.units_speed" + value = "stat.speed.2 stat.units_speed" height = 6 x = 38 y = 8 diff --git a/src/main/resources/assets/immersiverailroading/gui/default/handcar.caml b/src/main/resources/assets/immersiverailroading/gui/default/handcar.caml index 21539f93f..392401589 100644 --- a/src/main/resources/assets/immersiverailroading/gui/default/handcar.caml +++ b/src/main/resources/assets/immersiverailroading/gui/default/handcar.caml @@ -33,7 +33,7 @@ element: element: # speed readout text = - value = "stat.speed stat.units_speed" + value = "stat.speed.2 stat.units_speed" height = 6 x = 30 y = 8 diff --git a/src/main/resources/assets/immersiverailroading/gui/default/steam.caml b/src/main/resources/assets/immersiverailroading/gui/default/steam.caml index 943e49b03..8ffd5e3c1 100644 --- a/src/main/resources/assets/immersiverailroading/gui/default/steam.caml +++ b/src/main/resources/assets/immersiverailroading/gui/default/steam.caml @@ -103,7 +103,7 @@ element: element: # speed readout text = - value = "stat.speed stat.units_speed" + value = "stat.speed.2 stat.units_speed" height = 6 x = 50 y = 8 diff --git a/src/main/resources/assets/immersiverailroading/lang/de_de.lang b/src/main/resources/assets/immersiverailroading/lang/de_de.lang index 9b38fbda7..61b338345 100644 --- a/src/main/resources/assets/immersiverailroading/lang/de_de.lang +++ b/src/main/resources/assets/immersiverailroading/lang/de_de.lang @@ -1,5 +1,6 @@ item.immersiverailroading:item_large_wrench.name=Großer Schraubenschlüssel item.immersiverailroading:item_hook.name=Kupplungshaken +item.immersiverailroading:item_paint_brush.name=[Need translate] item.immersiverailroading:item_augment.SPEED_RETARDER.name=Retarder item.immersiverailroading:item_augment.WATER_TROUGH.name=Wasserbelader item.immersiverailroading:item_augment.LOCO_CONTROL.name=Fahrschalter @@ -9,11 +10,16 @@ item.immersiverailroading:item_augment.FLUID_LOADER.name=Flüssigkeitsbelader item.immersiverailroading:item_augment.FLUID_UNLOADER.name=Flüssigkeitsentlader item.immersiverailroading:item_augment.DETECTOR.name=Sensor item.immersiverailroading:item_augment.COUPLER.name=Koppler +item.immersiverailroading:item_augment.ACTUATOR.name=[Need translate] item.immersiverailroading:item_rail_part.name=Schienensegment item.immersiverailroading:item_cast_rail.name=Schienenguss item.immersiverailroading:item_manual.name=Immersive Railroading Handbuch item.immersiverailroading:item_rail.name=Schienenplan item.immersiverailroading:item_conductor_whistle.name=Pfeife +item.immersiverailroading:item_golden_spike.name=[Need translate] +item.immersiverailroading:item_radio_control_card.name=[Need translate] +item.immersiverailroading:item_switch_key.name=[Need translate] +item.immersiverailroading:item_track_exchanger.name=[Need translate] tile.immersiverailroading:block_rail.name=Schiene tile.immersiverailroading:block_rail_gag.name=Schiene (Gag) @@ -40,29 +46,69 @@ chat.immersiverailroading:augment.set=Erweitung reagiert nun nur noch auf %s chat.immersiverailroading:augment.reset=Erweiterung reagiert nun auf alle Fahrzeuge chat.immersiverailroading:misc.wood_planks=Holzbretter chat.immersiverailroading:build.invalid_block=Ungültiger Block: x=%s y=%s z=%s +chat.immersiverailroading:radio.link=[Need translate] +chat.immersiverailroading:radio.relink=[Need translate] +chat.immersiverailroading:radio.unlink=[Need translate] +chat.immersiverailroading:radio.nolink=[Need translate] +chat.immersiverailroading:radio.cant_link=[Need translate] chat.immersiverailroading:brush.no.variants= +chat.immersiverailroading:brush.next_debug=[Need translate] +chat.immersiverailroading:brush.mode.set=[Need translate] +chat.immersiverailroading:brush.mode.gui=[Need translate] +chat.immersiverailroading:brush.mode.random_single=[Need translate] +chat.immersiverailroading:brush.mode.random_coupled=[Need translate] +chat.immersiverailroading:switch_state.unlocked=[Need translate] +chat.immersiverailroading:switch_state.locked=[Need translate] +chat.immersiverailroading:switch_state.reset=[Need translate] +chat.immersiverailroading:switch_state.cant_reset=[Need translate] +chat.immersiverailroading:switch_state.already_reset=[Need translate] +chat.immersiverailroading:multiblock.select=[Need translate] gui.immersiverailroading:label.brake=Bremse gui.immersiverailroading:label.throttle=Fahrschalter +gui.immersiverailroading:label.reverser=[Need translate] +gui.immersiverailroading:slider.zoom=[Need translate] +gui.immersiverailroading:selector.page=[Need translate] gui.immersiverailroading:selector.type=Typ: %s gui.immersiverailroading:selector.gauge=Spurweite: %s +gui.immersiverailroading:selector.track=[Need translate] gui.immersiverailroading:selector.quarters=%s Grad Kurve +gui.immersiverailroading:selector.curvosity=[Need translate] gui.immersiverailroading:selector.rail_bed=Schienenbett: %s gui.immersiverailroading:selector.rail_bed_fill=Schienenbettfüllung: %s gui.immersiverailroading:selector.position=Position: %s +gui.immersiverailroading:selector.smoothing=[Need translate] gui.immersiverailroading:selector.direction=Richtung: %s +gui.immersiverailroading:selector.transfer_table_entry_count=[Need translate] +gui.immersiverailroading:selector.transfer_table_entry_spacing=[Need translate] gui.immersiverailroading:selector.place_blueprint=Entwurf platzieren +gui.immersiverailroading:selector.grade_crossing=[Need translate] gui.immersiverailroading:selector.plate_type=Plattentyp: %s gui.immersiverailroading:selector.plate_boiler=Kesselplatte: %s gui.immersiverailroading:selector.cast_single=Einmalige Fertigung gui.immersiverailroading:selector.cast_repeat=Mehrfache Fertigung +gui.immersiverailroading:selector.paintbrush_random=[Need translate] +gui.immersiverailroading:selector.paintbrush_apply_to_stock=[Need translate] +gui.immersiverailroading:selector.paintbrush_apply_to_train=[Need translate] + +gui.immersiverailroading:item.switch_key=[Need translate] +gui.immersiverailroading:item.switch_key.data=[Need translate] + +gui.immersiverailroading:item.radio_card.linked_to=[Need translate] +gui.immersiverailroading:item.radio_card.not_linked=[Need translate] + +gui.immersiverailroading:item.track_exchanger=[Need translate] +gui.immersiverailroading:item.paint_brush.mode=[Need translate] +gui.immersiverailroading:item.paint_brush.description=[Need translate] gui.immersiverailroading:none=kein gui.immersiverailroading:track.type=Typ: %s gui.immersiverailroading:track.length= Länge: %s gui.immersiverailroading:track.gauge=Spurweite: %s gui.immersiverailroading:track.quarters=%s Grad Kurve +gui.immersiverailroading:track.curvosity=[Need translate] gui.immersiverailroading:track.position=Platzierung: %s +gui.immersiverailroading:track.smoothing=[Need translate] gui.immersiverailroading:track.direction=Richtung: %s gui.immersiverailroading:track.rail_bed=Bett: %s gui.immersiverailroading:track.rail_bed_fill=Schienenbettfüllung: %s @@ -70,14 +116,20 @@ gui.immersiverailroading:track.place_blueprint_true=Platziere: Entwu gui.immersiverailroading:track.place_blueprint_false=Platziere: Schiene gui.immersiverailroading:loco.works=Werke: %s -gui.immersiverailroading:loco.horse_power=Kraft: %s Ps -gui.immersiverailroading:loco.tractive_effort=Traktion: %s Newton +gui.immersiverailroading:loco.power=[Need translate] +gui.immersiverailroading:loco.tractive_effort=[Need translate] gui.immersiverailroading:loco.max_speed=Maximale Geschwindigkeit: %s gui.immersiverailroading:stock.gauge=Spurweite: %s +gui.immersiverailroading:stock.texture=[Need translate] gui.immersiverailroading:cast.raw=Muss vor Nutzung erst in einem Dampfhammer weiterverarbeitet werden! gui.immersiverailroading:stock.tank_capacity=Kapazität: %s Eimer gui.immersiverailroading:stock.freight_capacity=Kapazität: %s Stapel gui.immersiverailroading:stock.weight=Gewicht: %s kg +gui.immersiverailroading:stock.modeler=[Need translate] +gui.immersiverailroading:stock.pack=[Need translate] + +gui.immersiverailroading:overlay.on=[Need translate] +gui.immersiverailroading:overlay.off=[Need translate] immersiverailroading:gauge.brunel=Breitspur immersiverailroading:gauge.standard=Normalspur @@ -97,6 +149,7 @@ track.immersiverailroading:class.turn=Kurve track.immersiverailroading:class.turntable=Drehscheibe track.immersiverailroading:class.transfertable=Schiebebühne track.immersiverailroading:class.switch=Weiche +track.immersiverailroading:class.custom=[Need translate] track.immersiverailroading:position.fixed=Fixiert track.immersiverailroading:position.pixels=Pixel @@ -104,12 +157,18 @@ track.immersiverailroading:position.pixels_locked=Pixel (fest) track.immersiverailroading:position.smooth=Fein track.immersiverailroading:position.smooth_locked=Fein (fest) +track.immersiverailroading:smoothing.both=[Need translate] +track.immersiverailroading:smoothing.near=[Need translate] +track.immersiverailroading:smoothing.far=[Need translate] +track.immersiverailroading:smoothing.neither=[Need translate] + track.immersiverailroading:direction.none=Flexibel track.immersiverailroading:direction.left=Sperre rechts track.immersiverailroading:direction.right=Sperre links part.immersiverailroading:component.frame=Rahmen part.immersiverailroading:component.front_frame=Vorderer Rahmen +part.immersiverailroading:component.rear_frame=[Need translate] part.immersiverailroading:component.bogey_wheel=Drehgestellrad part.immersiverailroading:component.bogey=Drehgestell part.immersiverailroading:component.bogey_front_wheel=Vorderes Drehgestellrad @@ -125,16 +184,22 @@ part.immersiverailroading:component.horn=Signalhorn part.immersiverailroading:component.fuel_tank=Kraftstofftank part.immersiverailroading:component.alternator=Generator part.immersiverailroading:component.engine_block=Motorblock +part.immersiverailroading:component.crankshaft=[Need translate] part.immersiverailroading:component.piston=Kolben +part.immersiverailroading:component.fan=[Need translate] +part.immersiverailroading:component.drive_shaft=[Need translate] +part.immersiverailroading:component.gearbox=[Need translate] +part.immersiverailroading:component.fluid_coupling=[Need translate] +part.immersiverailroading:component.final_drive=[Need translate] +part.immersiverailroading:component.torque_converter=[Need translate] part.immersiverailroading:component.firebox=Feuerbüchse +part.immersiverailroading:component.smokebox=Rauchkammer part.immersiverailroading:component.steam_chest=Schieberkasten -part.immersiverailroading:component.steam_chest_front=Vorderer Schieberkasten -part.immersiverailroading:component.steam_chest_rear=Hinterer Schieberkasten +part.immersiverailroading:component.steam_chest_pos=[Need translate] part.immersiverailroading:component.boiler_segment=Kesselsegment part.immersiverailroading:component.piping=Rohrleitungen part.immersiverailroading:component.wheel_driver=Radantrieb -part.immersiverailroading:component.wheel_driver_front=Vorderer Radantrieb -part.immersiverailroading:component.wheel_driver_rear=Hinterer Radantrieb +part.immersiverailroading:component.wheel_driver_pos=[Need translate] part.immersiverailroading:component.cylinder=Dampfzylinder part.immersiverailroading:component.side_rod=Seitenstange part.immersiverailroading:component.main_rod=Hauptstange @@ -150,7 +215,24 @@ part.immersiverailroading:component.reversing_arm=Reversing Arm part.immersiverailroading:component.lifting_link=Lifting Link part.immersiverailroading:component.reach_rod=Steuerstange part.immersiverailroading:component.walcherts_linkage=Walcherts Linkage -part.immersiverailroading:component.smokebox=Rauchkammer +part.immersiverailroading:component.valve_rod=[Need translate] + +part.immersiverailroading:controls.cylinder_drain=[Need translate] +part.immersiverailroading:controls.bell=[Need translate] +part.immersiverailroading:controls.whistle=[Need translate] +part.immersiverailroading:controls.horn=[Need translate] +part.immersiverailroading:controls.train_brake=[Need translate] +part.immersiverailroading:controls.independent_brake=[Need translate] +part.immersiverailroading:controls.throttle=[Need translate] +part.immersiverailroading:controls.reverser=[Need translate] +part.immersiverailroading:controls.throttle_brake=[Need translate] +part.immersiverailroading:controls.engine_start=[Need translate] + +multiblock.immersiverailroading:boiler_machine=[Need translate] +multiblock.immersiverailroading:casting=[Need translate] +multiblock.immersiverailroading:plate_machine=[Need translate] +multiblock.immersiverailroading:rail_machine=[Need translate] +multiblock.immersiverailroading:steam_hammer=[Need translate] immersiverailroading:crafting_type.casting=Gießen immersiverailroading:crafting_type.casting_hammer=Gießen, Dampfhammer @@ -167,6 +249,7 @@ itemGroup.immersiverailroading.components=Immersive Railroading Bauteile death.attack.immersiverailroading:casting=%s hat herausgefunden, dass sich geschmolzenes Metall nicht so gut zum schwimmen eignet. death.attack.immersiverailroading:hitByTrain=%s versagte bei dem Versuch vor einem Zug wegzurennen. +death.attack.immersiverailroading:hitByTrainInDarkness=[Need translate] immersiverailroading:detector_mode.simple=Fahrzeuge erkennen immersiverailroading:detector_mode.speed=Geschwindigkeit erkennen @@ -174,22 +257,96 @@ immersiverailroading:detector_mode.passengers=Anzahl der Passagiere erkennen immersiverailroading:detector_mode.cargo=Volle Güterwagen erkennen immersiverailroading:detector_mode.liquid=Volle Tankwagen erkennen immersiverailroading:detector_mode.computer=Computer -immersiverailroading:loco_control_mode.throttle_forward=Vorwärts -immersiverailroading:loco_control_mode.throttle_reverse=Rückwärts +immersiverailroading:loco_control_mode.throttle=[Need translate] +immersiverailroading:loco_control_mode.reverser=[Need translate] immersiverailroading:loco_control_mode.brake=Bremse immersiverailroading:loco_control_mode.horn=Signalhorn immersiverailroading:loco_control_mode.computer=Computer +immersiverailroading:loco_control_mode.bell=[Need translate] immersiverailroading:coupler_augment_mode.engaged=Koppeln immersiverailroading:coupler_augment_mode.disengaged=Entkoppeln +immersiverailroading:redstone_mode.enabled=[Need translate] +immersiverailroading:redstone_mode.required=[Need translate] +immersiverailroading:redstone_mode.inverted=[Need translate] +immersiverailroading:redstone_mode.disabled=[Need translate] + +immersiverailroading:switch_state.none=[Need translate] +immersiverailroading:switch_state.straight=[Need translate] +immersiverailroading:switch_state.turn=[Need translate] key.categories.immersiverailroading=Immersive Railroading ir_keys.increase_throttle=Fahrschalter erhöhen ir_keys.zero_throttle=Fahrschalter zurücksetzen ir_keys.decrease_throttle=Fahrschalter reduzieren +ir_keys.increase_reverser=[Need translate] +ir_keys.zero_reverser=[Need translate] +ir_keys.decrease_reverser=[Need translate] ir_keys.increase_brake=Bremse erhöhen ir_keys.zero_brake=Bremse zurücksetzen ir_keys.decrease_brake=Bremse reduzieren +ir_keys.increase_independent_brake=[Need translate] +ir_keys.zero_independent_brake=[Need translate] +ir_keys.decrease_independent_brake=[Need translate] ir_keys.horn=Signalhorn +ir_keys.bell=[Need translate] ir_keys.dead_mans_switch=Sicherheitsfahrschalter ir_keys.start_stop_engine=Antrieb an-/ausschalten ir_keys.config=Config + +# Default pack's train name. Translation is optional. +immersiverailroading:entity.locomotives.a1_peppercorn=A1 Peppercorn +immersiverailroading:entity.locomotives.a5_switcher=A5 Switcher +immersiverailroading:entity.locomotives.alco_rs1=RS-1 +immersiverailroading:entity.locomotives.big_boy=Big Boy (4000 class) +immersiverailroading:entity.locomotives.br01=br01 +immersiverailroading:entity.locomotives.class_38=Class 38 +immersiverailroading:entity.locomotives.cooke_mogul=DSP&P Mogul +immersiverailroading:entity.locomotives.e6_atlantic=E6 Atlantic +immersiverailroading:entity.locomotives.emd_sd40-2=EMD SD40-2 +immersiverailroading:entity.locomotives.emd_sw1500=SW1500 +immersiverailroading:entity.locomotives.firefly=Firefly +immersiverailroading:entity.locomotives.ge_40_ton_boxcab=Class B-B-70/70-4HM829 Boxcab +immersiverailroading:entity.locomotives.ge_b40_8=GE B40-8 +immersiverailroading:entity.locomotives.ge_b40_8w=GE B40-8w +immersiverailroading:entity.locomotives.ge_c44_9cw=GE C44-9CW +immersiverailroading:entity.locomotives.iron_duke=Iron Duke +immersiverailroading:entity.locomotives.k36=D&RGW K36 +immersiverailroading:entity.locomotives.k4_pacific=K4 Pacific +immersiverailroading:entity.locomotives.rodgers_460=Rodgers Ten Wheeler +immersiverailroading:entity.locomotives.skookum=Skookum 2-4-4-2 +immersiverailroading:entity.tender.a1_peppercorn_tender=A1 Peppercorn Tender +immersiverailroading:entity.tender.a5_tender=A5 Slope Tender +immersiverailroading:entity.tender.big_boy_tender=Big Boy (4000 class) Tender +immersiverailroading:entity.tender.br01_tender=drg class 01 tender +immersiverailroading:entity.tender.class_38_tender=Class 38 Tender +immersiverailroading:entity.tender.cooke_tender=Cooke Tender +immersiverailroading:entity.tender.e6_tender=E6 Atlantic Tender +immersiverailroading:entity.tender.k4_tender=K4 Pacific Tender +immersiverailroading:entity.tender.k36_tender=K36 Tender +immersiverailroading:entity.tender.rodgers_460_tender=Rodgers Ten Wheeler Tender +immersiverailroading:entity.tender.skookum_tender=Skookum Tender + +immersiverailroading:entity.hand_car.hand_car_1=Hand Car + +immersiverailroading:entity.passenger.b70baggage=PRR B70 Baggage +immersiverailroading:entity.passenger.br_coach_mk1=BR Coach MK1 +immersiverailroading:entity.passenger.p70coach1=PRR P70 Coach 1 + +immersiverailroading:entity.freight.70t_hopper_slsf=70T Hopper SLSF +immersiverailroading:entity.freight.attx_flatcar_1=ATTX Flatcar 1 +immersiverailroading:entity.freight.boxcar_x26=Box Car X26 +immersiverailroading:entity.freight.drgw_1000class_gondola=1000 Series Gondola +immersiverailroading:entity.freight.drgw_3000class_boxcar=3000 Series Boxcar +immersiverailroading:entity.freight.drgw_5500class_stockcar=5500 Series Stockcar +immersiverailroading:entity.freight.drgw_rail_and_tie_outfit=Rail & Tie Car +immersiverailroading:entity.freight.dw_gondola=DW Gondola +immersiverailroading:entity.freight.n5c_cabin_car=N5c Caboose +immersiverailroading:entity.freight.prr_flatcar_1=PRR Flatcar 1 +immersiverailroading:entity.freight.russell_snow_plow=Russell Snow Plow +immersiverailroading:entity.freight.usra_boxcar_classrr40=USRA Boxcar Class RR-40 +immersiverailroading:entity.freight.usra_hopper_55t=USRA Hopper 55T +immersiverailroading:entity.freight.waycar=Waycar + +immersiverailroading:entity.tank.kamx_t=Kamx T +immersiverailroading:entity.tank.slag_car_1=Slag Car 1 +immersiverailroading:entity.tank.tank_us2=Tank US 2 diff --git a/src/main/resources/assets/immersiverailroading/lang/en_us.lang b/src/main/resources/assets/immersiverailroading/lang/en_us.lang index c1b6bb018..4fea764f4 100644 --- a/src/main/resources/assets/immersiverailroading/lang/en_us.lang +++ b/src/main/resources/assets/immersiverailroading/lang/en_us.lang @@ -52,7 +52,7 @@ chat.immersiverailroading:radio.unlink=Card unlinked from its locomotive chat.immersiverailroading:radio.nolink=Card has no linked locomotive chat.immersiverailroading:radio.cant_link=Locomotive %s does not have radio control equipment chat.immersiverailroading:brush.no.variants=This stock has no livery variants -chat.immersiverailroading:brush.next=This stock's livery has been set to %s using %s +chat.immersiverailroading:brush.next_debug=This stock's livery has been set to %s using %s chat.immersiverailroading:brush.mode.set=Mode changed to: %s chat.immersiverailroading:brush.mode.gui=Picker Menu chat.immersiverailroading:brush.mode.random_single=Random (stock) @@ -62,10 +62,13 @@ chat.immersiverailroading:switch_state.locked=Switch locked to %s chat.immersiverailroading:switch_state.reset=The last-locked switch has been wirelessly unlocked! chat.immersiverailroading:switch_state.cant_reset=You haven't locked any switches with this key! chat.immersiverailroading:switch_state.already_reset=The last-locked switch is already unlocked! +chat.immersiverailroading:multiblock.select=Select multiblock: %s gui.immersiverailroading:label.brake=Brake gui.immersiverailroading:label.throttle=Throttle gui.immersiverailroading:label.reverser=Reverser +gui.immersiverailroading:slider.zoom=Zoom: +gui.immersiverailroading:selector.page=Page %s of %s gui.immersiverailroading:selector.type=Type: %s gui.immersiverailroading:selector.gauge=Gauge: %s gui.immersiverailroading:selector.track=Track Style: %s @@ -84,10 +87,16 @@ gui.immersiverailroading:selector.plate_type=Plate Type: %s gui.immersiverailroading:selector.plate_boiler=Plate Boiler: %s gui.immersiverailroading:selector.cast_single=Single Casting gui.immersiverailroading:selector.cast_repeat=Repeat Casting +gui.immersiverailroading:selector.paintbrush_random=Apply random variant +gui.immersiverailroading:selector.paintbrush_apply_to_stock=Apply to single stock +gui.immersiverailroading:selector.paintbrush_apply_to_train=Apply to whole train gui.immersiverailroading:item.switch_key=Right-Click a switch to cycle between: [ locked straight, locked turn, unlocked ]. Redstone is ignored when locked! gui.immersiverailroading:item.switch_key.data=Last locked switch: %s in %s +gui.immersiverailroading:item.radio_card.linked_to=Linked to %s +gui.immersiverailroading:item.radio_card.not_linked=Not linked to any locomotive + gui.immersiverailroading:item.track_exchanger=Right-Click in air to open the selection gui. Right-Click on a track to change it's track type to the one defined in the gui gui.immersiverailroading:item.paint_brush.mode=Current mode: %s gui.immersiverailroading:item.paint_brush.description=Sneak-Right-Click cycle modes @@ -107,18 +116,21 @@ gui.immersiverailroading:track.place_blueprint_true=Place: Blueprint gui.immersiverailroading:track.place_blueprint_false=Place: Track gui.immersiverailroading:loco.works=Works: %s -gui.immersiverailroading:loco.horse_power=Horse Power: %s -gui.immersiverailroading:loco.tractive_effort=Traction %s Newtons +gui.immersiverailroading:loco.power=Power: %s +gui.immersiverailroading:loco.tractive_effort=Tractive Eff: %s gui.immersiverailroading:loco.max_speed=Max Speed: %s gui.immersiverailroading:stock.gauge=Gauge: %s gui.immersiverailroading:stock.texture=Variant: %s gui.immersiverailroading:cast.raw=Requires processing in the steam hammer before use! gui.immersiverailroading:stock.tank_capacity=Capacity: %s Buckets gui.immersiverailroading:stock.freight_capacity=Capacity: %s Stacks -gui.immersiverailroading:stock.weight=Weight: %s Kg +gui.immersiverailroading:stock.weight=Weight: %s kg gui.immersiverailroading:stock.modeler=Modeler: %s gui.immersiverailroading:stock.pack=Pack: %s +gui.immersiverailroading:overlay.on=On +gui.immersiverailroading:overlay.off=Off + immersiverailroading:gauge.brunel=Brunel immersiverailroading:gauge.standard=Standard immersiverailroading:gauge.narrow=Narrow @@ -205,6 +217,22 @@ part.immersiverailroading:component.reach_rod=Reach Rod part.immersiverailroading:component.walcherts_linkage=Walcherts Linkage part.immersiverailroading:component.valve_rod=Valve Gear Component +part.immersiverailroading:controls.cylinder_drain=Cylinder Drain +part.immersiverailroading:controls.bell=Bell +part.immersiverailroading:controls.whistle=Whistle +part.immersiverailroading:controls.horn=Horn +part.immersiverailroading:controls.train_brake=Train Brake +part.immersiverailroading:controls.independent_brake=Independent Brake +part.immersiverailroading:controls.throttle=Throttle +part.immersiverailroading:controls.reverser=Reverser +part.immersiverailroading:controls.throttle_brake=Throttle Brake +part.immersiverailroading:controls.engine_start=Engine Start + +multiblock.immersiverailroading:boiler_machine=Boiler Machine +multiblock.immersiverailroading:casting=Casting Basin +multiblock.immersiverailroading:plate_machine=Plate Machine +multiblock.immersiverailroading:rail_machine=Rail Machine +multiblock.immersiverailroading:steam_hammer=Steam Hammer immersiverailroading:crafting_type.casting=Casting immersiverailroading:crafting_type.casting_hammer=Casting,Power Hammer @@ -250,6 +278,9 @@ key.categories.immersiverailroading=Immersive Railroading ir_keys.increase_throttle=Increase Throttle ir_keys.zero_throttle=Zero Throttle ir_keys.decrease_throttle=Decrease Throttle +ir_keys.increase_reverser=Increase Reverser +ir_keys.zero_reverser=Zero Reverser +ir_keys.decrease_reverser=Decrease Reverser ir_keys.increase_brake=Increase Air Brake ir_keys.zero_brake=Zero Air Brake ir_keys.decrease_brake=Decrease Air Brake @@ -261,3 +292,61 @@ ir_keys.bell=Sound Bell ir_keys.dead_mans_switch=Deadman's Switch ir_keys.start_stop_engine=Start/Stop engine ir_keys.config=Config + +# Default pack's train name +immersiverailroading:entity.locomotives.a1_peppercorn=A1 Peppercorn +immersiverailroading:entity.locomotives.a5_switcher=A5 Switcher +immersiverailroading:entity.locomotives.alco_rs1=RS-1 +immersiverailroading:entity.locomotives.big_boy=Big Boy (4000 class) +immersiverailroading:entity.locomotives.br01=br01 +immersiverailroading:entity.locomotives.class_38=Class 38 +immersiverailroading:entity.locomotives.cooke_mogul=DSP&P Mogul +immersiverailroading:entity.locomotives.e6_atlantic=E6 Atlantic +immersiverailroading:entity.locomotives.emd_sd40-2=EMD SD40-2 +immersiverailroading:entity.locomotives.emd_sw1500=SW1500 +immersiverailroading:entity.locomotives.firefly=Firefly +immersiverailroading:entity.locomotives.ge_40_ton_boxcab=Class B-B-70/70-4HM829 Boxcab +immersiverailroading:entity.locomotives.ge_b40_8=GE B40-8 +immersiverailroading:entity.locomotives.ge_b40_8w=GE B40-8w +immersiverailroading:entity.locomotives.ge_c44_9cw=GE C44-9CW +immersiverailroading:entity.locomotives.iron_duke=Iron Duke +immersiverailroading:entity.locomotives.k36=D&RGW K36 +immersiverailroading:entity.locomotives.k4_pacific=K4 Pacific +immersiverailroading:entity.locomotives.rodgers_460=Rodgers Ten Wheeler +immersiverailroading:entity.locomotives.skookum=Skookum 2-4-4-2 +immersiverailroading:entity.tender.a1_peppercorn_tender=A1 Peppercorn Tender +immersiverailroading:entity.tender.a5_tender=A5 Slope Tender +immersiverailroading:entity.tender.big_boy_tender=Big Boy (4000 class) Tender +immersiverailroading:entity.tender.br01_tender=drg class 01 tender +immersiverailroading:entity.tender.class_38_tender=Class 38 Tender +immersiverailroading:entity.tender.cooke_tender=Cooke Tender +immersiverailroading:entity.tender.e6_tender=E6 Atlantic Tender +immersiverailroading:entity.tender.k4_tender=K4 Pacific Tender +immersiverailroading:entity.tender.k36_tender=K36 Tender +immersiverailroading:entity.tender.rodgers_460_tender=Rodgers Ten Wheeler Tender +immersiverailroading:entity.tender.skookum_tender=Skookum Tender + +immersiverailroading:entity.hand_car.hand_car_1=Hand Car + +immersiverailroading:entity.passenger.b70baggage=PRR B70 Baggage +immersiverailroading:entity.passenger.br_coach_mk1=BR Coach MK1 +immersiverailroading:entity.passenger.p70coach1=PRR P70 Coach 1 + +immersiverailroading:entity.freight.70t_hopper_slsf=70T Hopper SLSF +immersiverailroading:entity.freight.attx_flatcar_1=ATTX Flatcar 1 +immersiverailroading:entity.freight.boxcar_x26=Box Car X26 +immersiverailroading:entity.freight.drgw_1000class_gondola=1000 Series Gondola +immersiverailroading:entity.freight.drgw_3000class_boxcar=3000 Series Boxcar +immersiverailroading:entity.freight.drgw_5500class_stockcar=5500 Series Stockcar +immersiverailroading:entity.freight.drgw_rail_and_tie_outfit=Rail & Tie Car +immersiverailroading:entity.freight.dw_gondola=DW Gondola +immersiverailroading:entity.freight.n5c_cabin_car=N5c Caboose +immersiverailroading:entity.freight.prr_flatcar_1=PRR Flatcar 1 +immersiverailroading:entity.freight.russell_snow_plow=Russell Snow Plow +immersiverailroading:entity.freight.usra_boxcar_classrr40=USRA Boxcar Class RR-40 +immersiverailroading:entity.freight.usra_hopper_55t=USRA Hopper 55T +immersiverailroading:entity.freight.waycar=Waycar + +immersiverailroading:entity.tank.kamx_t=Kamx T +immersiverailroading:entity.tank.slag_car_1=Slag Car 1 +immersiverailroading:entity.tank.tank_us2=Tank US 2 diff --git a/src/main/resources/assets/immersiverailroading/lang/fr_fr.lang b/src/main/resources/assets/immersiverailroading/lang/fr_fr.lang index 4bb42c79a..0e7ce9bb7 100644 --- a/src/main/resources/assets/immersiverailroading/lang/fr_fr.lang +++ b/src/main/resources/assets/immersiverailroading/lang/fr_fr.lang @@ -10,6 +10,7 @@ item.immersiverailroading:item_augment.FLUID_LOADER.name=Chargeur de liquide item.immersiverailroading:item_augment.FLUID_UNLOADER.name=Déchargeur de liquide item.immersiverailroading:item_augment.DETECTOR.name=Détecteur item.immersiverailroading:item_augment.COUPLER.name=Coupleur +item.immersiverailroading:item_augment.ACTUATOR.name=[Need translate] item.immersiverailroading:item_rail_part.name=Segment de rail item.immersiverailroading:item_cast_rail.name=Rail moulé item.immersiverailroading:item_manual.name=Manuel d'Immersive Railroading @@ -51,12 +52,23 @@ chat.immersiverailroading:radio.unlink=Carte déliée de sa locomotive chat.immersiverailroading:radio.nolink=La carte n'a lié aucune locomotive chat.immersiverailroading:radio.cant_link=La locomotive %s ne possède pas l'équipement permettant la radiocommande chat.immersiverailroading:brush.no.variants=Ce matériel n'a pas d'autres livrées +chat.immersiverailroading:brush.next_debug=[Need translate] +chat.immersiverailroading:brush.mode.set=[Need translate] +chat.immersiverailroading:brush.mode.gui=[Need translate] +chat.immersiverailroading:brush.mode.random_single=[Need translate] +chat.immersiverailroading:brush.mode.random_coupled=[Need translate] chat.immersiverailroading:switch_state.unlocked=Aiguillage déverrouillé chat.immersiverailroading:switch_state.locked=Aiguillage verrouillé sur %s +chat.immersiverailroading:switch_state.reset=[Need translate] +chat.immersiverailroading:switch_state.cant_reset=[Need translate] +chat.immersiverailroading:switch_state.already_reset=[Need translate] +chat.immersiverailroading:multiblock.select=[Need translate] gui.immersiverailroading:label.brake=Frein gui.immersiverailroading:label.throttle=Régulateur gui.immersiverailroading:label.reverser=Inverseur +gui.immersiverailroading:slider.zoom=[Need translate] +gui.immersiverailroading:selector.page=[Need translate] gui.immersiverailroading:selector.type=Type: %s gui.immersiverailroading:selector.gauge=Ecartement: %s gui.immersiverailroading:selector.track=Style de voie: %s @@ -67,15 +79,27 @@ gui.immersiverailroading:selector.rail_bed_fill=Remplissage sous ballast: %s gui.immersiverailroading:selector.position=Position: %s gui.immersiverailroading:selector.smoothing=Lissage de la rampe: %s gui.immersiverailroading:selector.direction=Direction: %s +gui.immersiverailroading:selector.transfer_table_entry_count=[Need translate] +gui.immersiverailroading:selector.transfer_table_entry_spacing=[Need translate] gui.immersiverailroading:selector.place_blueprint=Montrer un aperçu gui.immersiverailroading:selector.grade_crossing=Passage à niveau gui.immersiverailroading:selector.plate_type=Type de plaque: %s gui.immersiverailroading:selector.plate_boiler=Plaque de chaudière: %s gui.immersiverailroading:selector.cast_single=Coulage unique gui.immersiverailroading:selector.cast_repeat=Coulage répété +gui.immersiverailroading:selector.paintbrush_random=[Need translate] +gui.immersiverailroading:selector.paintbrush_apply_to_stock=[Need translate] +gui.immersiverailroading:selector.paintbrush_apply_to_train=[Need translate] + +gui.immersiverailroading:item.switch_key=[Need translate] +gui.immersiverailroading:item.switch_key.data=[Need translate] + +gui.immersiverailroading:item.radio_card.linked_to=[Need translate] +gui.immersiverailroading:item.radio_card.not_linked=[Need translate] -gui.immersiverailroading:item.switch_hammer=Clic droit sur un aiguillage pour choisir un verrouillage sur: [ Voie directe, Voie déviée, déverrouillé ]. La redstone ne fonctionne plus lorsque c'est verrouillé!! gui.immersiverailroading:item.track_exchanger=Clic droit dans le vide pour ouvrir l'interface de sélection. Clic droit sur la voie pour changer son type par celui sélectionné dans l'interface +gui.immersiverailroading:item.paint_brush.mode=[Need translate] +gui.immersiverailroading:item.paint_brush.description=[Need translate] gui.immersiverailroading:none=Aucun gui.immersiverailroading:track.type=Type: %s @@ -92,18 +116,21 @@ gui.immersiverailroading:track.place_blueprint_true=Poser: Aperçu gui.immersiverailroading:track.place_blueprint_false=Poser: Voie gui.immersiverailroading:loco.works=Constructeur: %s -gui.immersiverailroading:loco.horse_power=Puissance: %s Hp -gui.immersiverailroading:loco.tractive_effort=Traction: %s Newtons +gui.immersiverailroading:loco.power=[Need translate] +gui.immersiverailroading:loco.tractive_effort=[Need translate] gui.immersiverailroading:loco.max_speed=Vitesse Max: %s gui.immersiverailroading:stock.gauge=Ecartement: %s gui.immersiverailroading:stock.texture=Livrée: %s gui.immersiverailroading:cast.raw=Doit subir une transformation par le marteau-pilon avant de pouvoir être utilisé! gui.immersiverailroading:stock.tank_capacity=Capacité: %s seaux gui.immersiverailroading:stock.freight_capacity=Capacité: %s piles -gui.immersiverailroading:stock.weight=Masse: %s Kg +gui.immersiverailroading:stock.weight=Masse: %s kg gui.immersiverailroading:stock.modeler=Modeleur: %s gui.immersiverailroading:stock.pack=Pack: %s +gui.immersiverailroading:overlay.on=[Need translate] +gui.immersiverailroading:overlay.off=[Need translate] + immersiverailroading:gauge.brunel=Brunel immersiverailroading:gauge.standard=Standard immersiverailroading:gauge.narrow=Etroite @@ -141,6 +168,7 @@ track.immersiverailroading:direction.right=Verrouillée vers la gauche part.immersiverailroading:component.frame=Châssis part.immersiverailroading:component.front_frame=Châssis avant +part.immersiverailroading:component.rear_frame=[Need translate] part.immersiverailroading:component.bogey_wheel=Essieu de bogie part.immersiverailroading:component.bogey=Bogie part.immersiverailroading:component.bogey_front_wheel=Essieu de bogie avant @@ -156,16 +184,22 @@ part.immersiverailroading:component.horn=Avertisseur sonore part.immersiverailroading:component.fuel_tank=Réservoir de carburant part.immersiverailroading:component.alternator=Alternateur part.immersiverailroading:component.engine_block=Bloc-moteur +part.immersiverailroading:component.crankshaft=[Need translate] part.immersiverailroading:component.piston=Piston +part.immersiverailroading:component.fan=[Need translate] +part.immersiverailroading:component.drive_shaft=[Need translate] +part.immersiverailroading:component.gearbox=Boite de vitesse +part.immersiverailroading:component.fluid_coupling=[Need translate] +part.immersiverailroading:component.final_drive=[Need translate] +part.immersiverailroading:component.torque_converter=[Need translate] part.immersiverailroading:component.firebox=Boite à feu +part.immersiverailroading:component.smokebox=Boite à fumée part.immersiverailroading:component.steam_chest=Boite à vapeur -part.immersiverailroading:component.steam_chest_front=Boite à vapeur avant -part.immersiverailroading:component.steam_chest_rear=Boite à vapeur arrière +part.immersiverailroading:component.steam_chest_pos=[Need translate] part.immersiverailroading:component.boiler_segment=Partie de chaudière part.immersiverailroading:component.piping=Tuyauterie part.immersiverailroading:component.wheel_driver=Essieu moteur -part.immersiverailroading:component.wheel_driver_front=Essieu moteur avant -part.immersiverailroading:component.wheel_driver_rear=Essieu moteur arrière +part.immersiverailroading:component.wheel_driver_pos=[Need translate] part.immersiverailroading:component.cylinder=Cylindre part.immersiverailroading:component.side_rod=Bielle d'accouplement part.immersiverailroading:component.main_rod=Bielle motrice @@ -181,9 +215,24 @@ part.immersiverailroading:component.reversing_arm=Arbre de relevage part.immersiverailroading:component.lifting_link=Biellette de relevage part.immersiverailroading:component.reach_rod=Arbre de changement de marche part.immersiverailroading:component.walcherts_linkage=Distribution Walschaerts -part.immersiverailroading:component.smokebox=Boite à fumée -part.immersiverailroading:component.gearbox=Boite de vitesse +part.immersiverailroading:component.valve_rod=[Need translate] +part.immersiverailroading:controls.cylinder_drain=[Need translate] +part.immersiverailroading:controls.bell=[Need translate] +part.immersiverailroading:controls.whistle=[Need translate] +part.immersiverailroading:controls.horn=[Need translate] +part.immersiverailroading:controls.train_brake=[Need translate] +part.immersiverailroading:controls.independent_brake=[Need translate] +part.immersiverailroading:controls.throttle=[Need translate] +part.immersiverailroading:controls.reverser=[Need translate] +part.immersiverailroading:controls.throttle_brake=[Need translate] +part.immersiverailroading:controls.engine_start=[Need translate] + +multiblock.immersiverailroading:boiler_machine=[Need translate] +multiblock.immersiverailroading:casting=[Need translate] +multiblock.immersiverailroading:plate_machine=[Need translate] +multiblock.immersiverailroading:rail_machine=[Need translate] +multiblock.immersiverailroading:steam_hammer=[Need translate] immersiverailroading:crafting_type.casting=Coulage immersiverailroading:crafting_type.casting_hammer=Coulage, Marteau-pilon @@ -200,6 +249,7 @@ itemGroup.immersiverailroading.components=Composants de véhicules death.attack.immersiverailroading:casting=%s a découvert que faire un plongeon dans la cuve de métaux fondus n'était pas l'idée du siècle death.attack.immersiverailroading:hitByTrain=%s n'a pas réussi à semer le train +death.attack.immersiverailroading:hitByTrainInDarkness=[Need translate] immersiverailroading:detector_mode.simple=Détecte les matériels roulants immersiverailroading:detector_mode.speed=Détecte la vitesse @@ -228,17 +278,75 @@ key.categories.immersiverailroading=Immersive Railroading ir_keys.increase_throttle=Ouvrir progressivement le régulateur ir_keys.zero_throttle=Fermer immédiatement le régulateur ir_keys.decrease_throttle=Fermer progressivement le régulateur +ir_keys.increase_reverser=Régler l'inverseur vers la marche avant +ir_keys.zero_reverser=Mettre l'inverseur en position neutre +ir_keys.decrease_reverser=Régler l'inverseur vers la marche arrière ir_keys.increase_brake=Serrage progressif du frein continu ir_keys.zero_brake=Desserrage immédiat du frein continu ir_keys.decrease_brake=Desserrage progressif du frein continu +ir_keys.increase_independent_brake=Serrage progressif du frein direct +ir_keys.zero_independent_brake=Desserrage immédiat du frein direct +ir_keys.decrease_independent_brake=Desserrage progressif du frein direct ir_keys.horn=Faire sonner le sifflet/klaxon ir_keys.bell=Faire sonner la cloche ir_keys.dead_mans_switch=Veille automatique ir_keys.start_stop_engine=Démarrer/Arrêter le moteur ir_keys.config=Configuration -ir_keys.increase_independent_brake=Serrage progressif du frein direct -ir_keys.zero_independent_brake=Desserrage immédiat du frein direct -ir_keys.decrease_independent_brake=Desserrage progressif du frein direct -ir_keys.increase_reverser=Régler l'inverseur vers la marche avant -ir_keys.zero_reverser=Mettre l'inverseur en position neutre -ir_keys.decrease_reverser=Régler l'inverseur vers la marche arrière + +# Default pack's train name. Translation is optional. +immersiverailroading:entity.locomotives.a1_peppercorn=A1 Peppercorn +immersiverailroading:entity.locomotives.a5_switcher=A5 Switcher +immersiverailroading:entity.locomotives.alco_rs1=RS-1 +immersiverailroading:entity.locomotives.big_boy=Big Boy (4000 class) +immersiverailroading:entity.locomotives.br01=br01 +immersiverailroading:entity.locomotives.class_38=Class 38 +immersiverailroading:entity.locomotives.cooke_mogul=DSP&P Mogul +immersiverailroading:entity.locomotives.e6_atlantic=E6 Atlantic +immersiverailroading:entity.locomotives.emd_sd40-2=EMD SD40-2 +immersiverailroading:entity.locomotives.emd_sw1500=SW1500 +immersiverailroading:entity.locomotives.firefly=Firefly +immersiverailroading:entity.locomotives.ge_40_ton_boxcab=Class B-B-70/70-4HM829 Boxcab +immersiverailroading:entity.locomotives.ge_b40_8=GE B40-8 +immersiverailroading:entity.locomotives.ge_b40_8w=GE B40-8w +immersiverailroading:entity.locomotives.ge_c44_9cw=GE C44-9CW +immersiverailroading:entity.locomotives.iron_duke=Iron Duke +immersiverailroading:entity.locomotives.k36=D&RGW K36 +immersiverailroading:entity.locomotives.k4_pacific=K4 Pacific +immersiverailroading:entity.locomotives.rodgers_460=Rodgers Ten Wheeler +immersiverailroading:entity.locomotives.skookum=Skookum 2-4-4-2 +immersiverailroading:entity.tender.a1_peppercorn_tender=A1 Peppercorn Tender +immersiverailroading:entity.tender.a5_tender=A5 Slope Tender +immersiverailroading:entity.tender.big_boy_tender=Big Boy (4000 class) Tender +immersiverailroading:entity.tender.br01_tender=drg class 01 tender +immersiverailroading:entity.tender.class_38_tender=Class 38 Tender +immersiverailroading:entity.tender.cooke_tender=Cooke Tender +immersiverailroading:entity.tender.e6_tender=E6 Atlantic Tender +immersiverailroading:entity.tender.k4_tender=K4 Pacific Tender +immersiverailroading:entity.tender.k36_tender=K36 Tender +immersiverailroading:entity.tender.rodgers_460_tender=Rodgers Ten Wheeler Tender +immersiverailroading:entity.tender.skookum_tender=Skookum Tender + +immersiverailroading:entity.hand_car.hand_car_1=Hand Car + +immersiverailroading:entity.passenger.b70baggage=PRR B70 Baggage +immersiverailroading:entity.passenger.br_coach_mk1=BR Coach MK1 +immersiverailroading:entity.passenger.p70coach1=PRR P70 Coach 1 + +immersiverailroading:entity.freight.70t_hopper_slsf=70T Hopper SLSF +immersiverailroading:entity.freight.attx_flatcar_1=ATTX Flatcar 1 +immersiverailroading:entity.freight.boxcar_x26=Box Car X26 +immersiverailroading:entity.freight.drgw_1000class_gondola=1000 Series Gondola +immersiverailroading:entity.freight.drgw_3000class_boxcar=3000 Series Boxcar +immersiverailroading:entity.freight.drgw_5500class_stockcar=5500 Series Stockcar +immersiverailroading:entity.freight.drgw_rail_and_tie_outfit=Rail & Tie Car +immersiverailroading:entity.freight.dw_gondola=DW Gondola +immersiverailroading:entity.freight.n5c_cabin_car=N5c Caboose +immersiverailroading:entity.freight.prr_flatcar_1=PRR Flatcar 1 +immersiverailroading:entity.freight.russell_snow_plow=Russell Snow Plow +immersiverailroading:entity.freight.usra_boxcar_classrr40=USRA Boxcar Class RR-40 +immersiverailroading:entity.freight.usra_hopper_55t=USRA Hopper 55T +immersiverailroading:entity.freight.waycar=Waycar + +immersiverailroading:entity.tank.kamx_t=Kamx T +immersiverailroading:entity.tank.slag_car_1=Slag Car 1 +immersiverailroading:entity.tank.tank_us2=Tank US 2 diff --git a/src/main/resources/assets/immersiverailroading/lang/ja_jp.lang b/src/main/resources/assets/immersiverailroading/lang/ja_jp.lang index 8e1654e4c..eafa019cf 100644 --- a/src/main/resources/assets/immersiverailroading/lang/ja_jp.lang +++ b/src/main/resources/assets/immersiverailroading/lang/ja_jp.lang @@ -1,199 +1,352 @@ -item.immersiverailroading:item_large_wrench.name=大きいレンチ +item.immersiverailroading:item_large_wrench.name=大型レンチ item.immersiverailroading:item_hook.name=連結フック item.immersiverailroading:item_paint_brush.name=ペイントブラシ -item.immersiverailroading:item_augment.SPEED_RETARDER.name=減速機 -item.immersiverailroading:item_augment.WATER_TROUGH.name=水船 -item.immersiverailroading:item_augment.LOCO_CONTROL.name=列車制御装置 +item.immersiverailroading:item_augment.SPEED_RETARDER.name=減速装置 +item.immersiverailroading:item_augment.WATER_TROUGH.name=ウォーター・スクープ +item.immersiverailroading:item_augment.LOCO_CONTROL.name=機関車制御装置 item.immersiverailroading:item_augment.ITEM_LOADER.name=アイテム搬入機 item.immersiverailroading:item_augment.ITEM_UNLOADER.name=アイテム搬出機 item.immersiverailroading:item_augment.FLUID_LOADER.name=液体搬入機 item.immersiverailroading:item_augment.FLUID_UNLOADER.name=液体搬出機 item.immersiverailroading:item_augment.DETECTOR.name=列車検出器 item.immersiverailroading:item_augment.COUPLER.name=連結器 -item.immersiverailroading:item_rail_part.name=レール -item.immersiverailroading:item_cast_rail.name=レール鋳造機 -item.immersiverailroading:item_manual.name=IRマニュアル +item.immersiverailroading:item_augment.ACTUATOR.name=ドア制御装置 +item.immersiverailroading:item_rail_part.name=軌条 +item.immersiverailroading:item_cast_rail.name=鋳造中の軌条 +item.immersiverailroading:item_manual.name=IRマニュアル本 item.immersiverailroading:item_rail.name=線路設計図 item.immersiverailroading:item_conductor_whistle.name=車掌の笛 -item.immersiverailroading:item_golden_spike.name=金のスパイク +item.immersiverailroading:item_golden_spike.name=ゴールデン・スパイク +item.immersiverailroading:item_radio_control_card.name=無線コントローラ +item.immersiverailroading:item_switch_key.name=スイッチキー +item.immersiverailroading:item_track_exchanger.name=レール変換装置 tile.immersiverailroading:block_rail.name=レール -tile.immersiverailroading:block_rail_gag.name=レール (ギャグ) +tile.immersiverailroading:block_rail_gag.name=レール(ダミー) tile.immersiverailroading:block_rail_preview.name=レールプレビュー -tile.immersiverailroading:block_steam_hammer.name=パワーハンマー - -chat.immersiverailroading:stock.built=%s が完成しました! -chat.immersiverailroading:stock.dissasembled=%s が破壊されました! -chat.immersiverailroading:stock.missing=以下の部品が不足しています: %s -chat.immersiverailroading:stock.invalid=エラー: 車両がサーバーに存在していません、設置できませんchat.immersiverailroading:stock.wrong_gauge=誤った線路規格です! -chat.immersiverailroading:stock.placement=車両は直線線路上に設置しなければなりません -chat.immersiverailroading:stock.deadmans_switch_enabled=デッドマンスイッチが有効になりました -chat.immersiverailroading:stock.deadmans_switch_disabled=デッドマンスイッチが無効になりました -chat.immersiverailroading:coupler.front=前 -chat.immersiverailroading:coupler.back=後 -chat.immersiverailroading:coupler.engaged=連結器 %s を通常モードに設定しました -chat.immersiverailroading:coupler.disengaged=連結器 %s を車両入れ替えモードに設定しました -chat.immersiverailroading:coupler.status.coupled=%s 連結器は %s (%s, %s, %s) に連結されました -chat.immersiverailroading:coupler.status.decoupled.engaged=%s 連結器が通常モードで解結されました -chat.immersiverailroading:coupler.status.decoupled.disengaged=%s 連結器が列車入れ替えモードで解結されました -chat.immersiverailroading:build.missing=%s 個のレールが不足しています -chat.immersiverailroading:augment.set=%s に対してのみ動作します -chat.immersiverailroading:augment.reset=全ての車両に対して動作します +tile.immersiverailroading:block_steam_hammer.name=蒸気ハンマー + +chat.immersiverailroading:stock.built=%s が完成しました! +chat.immersiverailroading:stock.dissasembled=%s が解体されました! +chat.immersiverailroading:stock.missing=以下の部品が不足しています: %s +chat.immersiverailroading:stock.invalid=エラー: 車両がサーバーに存在しない為、設置できません。リソースパックをサーバーの config/immersiverailroading に入れてください +chat.immersiverailroading:stock.wrong_gauge=軌間を間違えています! +chat.immersiverailroading:stock.placement=車両は直線上で設置しなければなりません +chat.immersiverailroading:stock.deadmans_switch_enabled=デッドマン装置が有効になりました +chat.immersiverailroading:stock.deadmans_switch_disabled=デッドマン装置が無効になりました +chat.immersiverailroading:coupler.front=前部 +chat.immersiverailroading:coupler.back=後部 +chat.immersiverailroading:coupler.engaged=%s 連結器を通常モードに設定しました +chat.immersiverailroading:coupler.disengaged=%s 連結器を入換モードに設定しました +chat.immersiverailroading:coupler.status.coupled=%s 連結器は %s (%s,%s,%s)に連結されました +chat.immersiverailroading:coupler.status.decoupled.engaged=%s 連結器が通常モードで切り離されました +chat.immersiverailroading:coupler.status.decoupled.disengaged=%s 連結器が入換モードで切り離されました +chat.immersiverailroading:build.missing=%s %s が不足しています +chat.immersiverailroading:augment.set=%s の時のみ作動します +chat.immersiverailroading:augment.reset=全ての車両に対して作動します chat.immersiverailroading:misc.wood_planks=木材 -chat.immersiverailroading:build.invalid_block=無効なブロックです x=%s y=%s z=%s +chat.immersiverailroading:build.invalid_block=(x=%s y=%s z=%s)に無効なブロックがあります +chat.immersiverailroading:radio.link=無線コントローラが車両と接続しました +chat.immersiverailroading:radio.relink=無線コントローラが新たな車両に接続しました +chat.immersiverailroading:radio.unlink=無線コントローラが車両から切り離されました +chat.immersiverailroading:radio.nolink=無線コントローラは車両と接続していません +chat.immersiverailroading:radio.cant_link=車両 %s は無線制御装置を備えていません +chat.immersiverailroading:brush.no.variants=この車両に他の塗装はありません +chat.immersiverailroading:brush.next_debug=この車両の塗装は %s を使用し %s へ変更しました +chat.immersiverailroading:brush.mode.set=以下のモードに変更しました: %s +chat.immersiverailroading:brush.mode.gui=選択メニュー +chat.immersiverailroading:brush.mode.random_single=ランダム塗装(選択車両のみ) +chat.immersiverailroading:brush.mode.random_coupled=ランダム塗装(編成) +chat.immersiverailroading:switch_state.unlocked=分岐器をアンロックしました +chat.immersiverailroading:switch_state.locked=分岐器は %s でロックされました +chat.immersiverailroading:switch_state.reset=最後にロックされた分岐器が無線でアンロックされました! +chat.immersiverailroading:switch_state.cant_reset=まだこのキーで分岐器をロックしたことがありません! +chat.immersiverailroading:switch_state.already_reset=最後にロックした分岐器をリセットしました! +chat.immersiverailroading:multiblock.select=マルチブロック:%s を選択しました gui.immersiverailroading:label.brake=ブレーキ -gui.immersiverailroading:label.throttle=スロットル -gui.immersiverailroading:selector.type=種類: %s -gui.immersiverailroading:selector.gauge=線路規格: %s -gui.immersiverailroading:selector.quarters=%s 度の曲線 -gui.immersiverailroading:selector.rail_bed=路床: %s -gui.immersiverailroading:selector.rail_bed_fill=線路下ブロック: %s -gui.immersiverailroading:selector.position=位置: %s -gui.immersiverailroading:selector.direction=方向: %s +gui.immersiverailroading:label.throttle=加減弁 +gui.immersiverailroading:label.reverser=逆転機 +gui.immersiverailroading:slider.zoom=ズーム: +gui.immersiverailroading:selector.page=%s / %s ページ +gui.immersiverailroading:selector.type=種類:%s +gui.immersiverailroading:selector.gauge=軌間:%s +gui.immersiverailroading:selector.track=レールのスタイル:%s +gui.immersiverailroading:selector.quarters=%s 度曲線 +gui.immersiverailroading:selector.curvosity=%s 曲線度 +gui.immersiverailroading:selector.rail_bed=バラスト:%s +gui.immersiverailroading:selector.rail_bed_fill=線路下のブロック充填:%s +gui.immersiverailroading:selector.position=位置:%s +gui.immersiverailroading:selector.smoothing=垂直スムージング:%s +gui.immersiverailroading:selector.direction=方向:%s gui.immersiverailroading:selector.transfer_table_entry_count=トラバーサー線路数:%s gui.immersiverailroading:selector.transfer_table_entry_spacing=隣接する線路との間隔:%s -gui.immersiverailroading:selector.place_blueprint=設計図のみ設置 -gui.immersiverailroading:selector.grade_crossing=平面交差 -gui.immersiverailroading:selector.plate_type=プレートの種類: %s -gui.immersiverailroading:selector.plate_boiler=プレートボイラー: %s -gui.immersiverailroading:selector.cast_single=1回だけ鋳造 +gui.immersiverailroading:selector.place_blueprint=設計図設置 +gui.immersiverailroading:selector.grade_crossing=踏切 +gui.immersiverailroading:selector.plate_type=プレートの種類:%s +gui.immersiverailroading:selector.plate_boiler=ボイラープレート:%s +gui.immersiverailroading:selector.cast_single=1回のみ鋳造 gui.immersiverailroading:selector.cast_repeat=繰り返し鋳造 +gui.immersiverailroading:selector.paintbrush_random=ランダム塗装 +gui.immersiverailroading:selector.paintbrush_apply_to_stock=選択車両をランダム塗装 +gui.immersiverailroading:selector.paintbrush_apply_to_train=列車をランダム塗装 + +gui.immersiverailroading:item.switch_key=右クリックで分岐器は以下のポジションで循環します:[直進ロック、分岐ロック、ロック解除]。 ロック中の分岐器はレッドストーン信号を無視します! +gui.immersiverailroading:item.switch_key.data=最後にロックした分岐器: %s は %s ポジションです + +gui.immersiverailroading:item.radio_card.linked_to=%s とリンク +gui.immersiverailroading:item.radio_card.not_linked=車両とリンクしていません + +gui.immersiverailroading:item.track_exchanger=空中で右クリックをすると選択GUIを開きます。 レールを右クリックするとレールの種類がGUI上のものに変更されます +gui.immersiverailroading:item.paint_brush.mode=現在のモード: %s +gui.immersiverailroading:item.paint_brush.description=スニークと右クリックでモードを循環させます gui.immersiverailroading:none=なし -gui.immersiverailroading:track.type=種類: %s -gui.immersiverailroading:track.length=長さ: %s -gui.immersiverailroading:track.gauge=線路規格: %s -gui.immersiverailroading:track.quarters=%s 度の曲線 -gui.immersiverailroading:track.position=位置: %s -gui.immersiverailroading:track.direction=方向: %s -gui.immersiverailroading:track.rail_bed=路床: %s -gui.immersiverailroading:track.rail_bed_fill=線路下ブロック: %s -gui.immersiverailroading:track.place_blueprint_true=設置: 設計図 -gui.immersiverailroading:track.place_blueprint_false=設置: 線路 - -gui.immersiverailroading:loco.works=鉄道会社名: %s -gui.immersiverailroading:loco.horse_power=馬力: %s -gui.immersiverailroading:loco.tractive_effort=牽引力 %s ニュートン -gui.immersiverailroading:loco.max_speed=最高速度: %s -gui.immersiverailroading:stock.gauge=線路規格: %s -gui.immersiverailroading:stock.texture=Variant: %s -gui.immersiverailroading:cast.raw=使用前にスチームハンマーによる工程が必要です! -gui.immersiverailroading:stock.tank_capacity=最大積載量: %s バケツ -gui.immersiverailroading:stock.freight_capacity=最大積載量: %s スタック -gui.immersiverailroading:stock.weight=重量: %s Kg - -immersiverailroading:gauge.brunel=ブルネル -immersiverailroading:gauge.standard=標準 -immersiverailroading:gauge.narrow=狭幅 -immersiverailroading:gauge.minecraft=マインカート +gui.immersiverailroading:track.type=種類: %s +gui.immersiverailroading:track.length=長さ: %s +gui.immersiverailroading:track.gauge=軌間: %s +gui.immersiverailroading:track.quarters=%s 度曲線 +gui.immersiverailroading:track.curvosity=%s 曲線度 +gui.immersiverailroading:track.position=位置: %s +gui.immersiverailroading:track.smoothing=垂直スムージング: %s +gui.immersiverailroading:track.direction=方向: %s +gui.immersiverailroading:track.rail_bed=バラスト: %s +gui.immersiverailroading:track.rail_bed_fill=線路下ブロック充填: %s +gui.immersiverailroading:track.place_blueprint_true=設置: 設計図 +gui.immersiverailroading:track.place_blueprint_false=設置: 線路 + +gui.immersiverailroading:loco.works=製造: %s +gui.immersiverailroading:loco.power=出力: %s +gui.immersiverailroading:loco.tractive_effort=牽引力: %s +gui.immersiverailroading:loco.max_speed=最高時速: %s +gui.immersiverailroading:stock.gauge=軌間: %s +gui.immersiverailroading:stock.texture=塗装: %s +gui.immersiverailroading:cast.raw=使用前に蒸気ハンマーによる加工が必要です! +gui.immersiverailroading:stock.tank_capacity=積載量: %s バケツ +gui.immersiverailroading:stock.freight_capacity=積載量: %s スタック +gui.immersiverailroading:stock.weight=重量: %s kg +gui.immersiverailroading:stock.modeler=モデラー: %s +gui.immersiverailroading:stock.pack=パック: %s + +gui.immersiverailroading:overlay.on=オン +gui.immersiverailroading:overlay.off=オフ + +immersiverailroading:gauge.brunel=ブルネル広軌 +immersiverailroading:gauge.standard=標準軌 +immersiverailroading:gauge.narrow=狭軌 +immersiverailroading:gauge.minecraft=マイクラゲージ immersiverailroading:gauge.model=模型 immersiverailroading:plate.small=小さいプレート immersiverailroading:plate.medium=中くらいのプレート -immersiverailroading:plate.large=大きなプレート +immersiverailroading:plate.large=大きいプレート immersiverailroading:plate.boiler=ボイラープレート track.immersiverailroading:class.straight=直線 -track.immersiverailroading:class.crossing=交差 +track.immersiverailroading:class.crossing=平面交差 track.immersiverailroading:class.slope=勾配 track.immersiverailroading:class.turn=曲線 track.immersiverailroading:class.turntable=転車台 track.immersiverailroading:class.transfertable=トラバーサー track.immersiverailroading:class.switch=分岐器 -track.immersiverailroading:class.custom=任意の曲線 -track.immersiverailroading:position.fixed=固定 +track.immersiverailroading:class.custom=カスタム + +track.immersiverailroading:position.fixed=ブロックに単位 track.immersiverailroading:position.pixels=ピクセル単位 -track.immersiverailroading:position.pixels_locked=ピクセル単位(固定) +track.immersiverailroading:position.pixels_locked=ピクセル単位(固定) track.immersiverailroading:position.smooth=無段階 -track.immersiverailroading:position.smooth_locked=無段階(固定) +track.immersiverailroading:position.smooth_locked=無段階(固定) + +track.immersiverailroading:smoothing.both=両者 +track.immersiverailroading:smoothing.near=近い +track.immersiverailroading:smoothing.far=遠い +track.immersiverailroading:smoothing.neither=どちらでもない track.immersiverailroading:direction.none=両方向 -track.immersiverailroading:direction.left=右に固定 -track.immersiverailroading:direction.right=左に固定 - -part.immersiverailroading:component.frame=フレーム -part.immersiverailroading:component.front_frame=フロントフレーム -part.immersiverailroading:component.bogey_wheel=台車用車輪 -part.immersiverailroading:component.bogey=台車 -part.immersiverailroading:component.bogey_front_wheel=台車用前輪 -part.immersiverailroading:component.bogey_front=フロント台車 -part.immersiverailroading:component.bogey_rear_wheel=台車用後輪 -part.immersiverailroading:component.bogey_rear=リア台車 -part.immersiverailroading:component.frame_wheel=フレーム車輪 +track.immersiverailroading:direction.left=左側に固定 +track.immersiverailroading:direction.right=右側に固定 + +part.immersiverailroading:component.frame=台枠 +part.immersiverailroading:component.front_frame=前側台枠 +part.immersiverailroading:component.rear_frame=後側台枠 +part.immersiverailroading:component.bogey_wheel=台車車輪 +part.immersiverailroading:component.bogey=台車枠 +part.immersiverailroading:component.bogey_front_wheel=前側台車車輪 +part.immersiverailroading:component.bogey_front=前側台車枠 +part.immersiverailroading:component.bogey_rear_wheel=後側台車車輪 +part.immersiverailroading:component.bogey_rear=後側台車枠 +part.immersiverailroading:component.frame_wheel=車輪 part.immersiverailroading:component.shell=外装 -part.immersiverailroading:component.cab=運転台 +part.immersiverailroading:component.cab=運転室 part.immersiverailroading:component.bell=ベル -part.immersiverailroading:component.whistle=笛 +part.immersiverailroading:component.whistle=汽笛 part.immersiverailroading:component.horn=警笛 part.immersiverailroading:component.fuel_tank=燃料タンク part.immersiverailroading:component.alternator=発電機 part.immersiverailroading:component.engine_block=エンジンブロック +part.immersiverailroading:component.crankshaft=クランクシャフト part.immersiverailroading:component.piston=ピストン +part.immersiverailroading:component.fan=ファン +part.immersiverailroading:component.drive_shaft=ドライブシャフト +part.immersiverailroading:component.gearbox=ギアボックス +part.immersiverailroading:component.fluid_coupling=流体継手 +part.immersiverailroading:component.final_drive=最終駆動装置 +part.immersiverailroading:component.torque_converter=トルクコンバータ part.immersiverailroading:component.firebox=火室 -part.immersiverailroading:component.steam_chest=蒸気室 -part.immersiverailroading:component.steam_chest_front=蒸気室前 -part.immersiverailroading:component.steam_chest_rear=蒸気室後 +part.immersiverailroading:component.smokebox=煙室 +part.immersiverailroading:component.steam_chest=シリンダーブロック +part.immersiverailroading:component.steam_chest_pos=シリンダーブロック part.immersiverailroading:component.boiler_segment=ボイラー部品 -part.immersiverailroading:component.piping=導管 -part.immersiverailroading:component.wheel_driver=車軸 -part.immersiverailroading:component.wheel_driver_front=Wheel Driver Front -part.immersiverailroading:component.wheel_driver_rear=Wheel Driver Rear +part.immersiverailroading:component.piping=導管類 +part.immersiverailroading:component.wheel_driver=動輪 +part.immersiverailroading:component.wheel_driver_pos=動輪 part.immersiverailroading:component.cylinder=シリンダー -part.immersiverailroading:component.side_rod=サイドロッド -part.immersiverailroading:component.main_rod=メインロッド +part.immersiverailroading:component.side_rod=連結棒 +part.immersiverailroading:component.main_rod=主連棒 part.immersiverailroading:component.piston_rod=ピストンロッド -part.immersiverailroading:component.union_link=ユニオンリンク -part.immersiverailroading:component.combination_lever=合併てこ +part.immersiverailroading:component.union_link=結びリンク +part.immersiverailroading:component.combination_lever=合併テコ part.immersiverailroading:component.valve_stem=バルブ軸 -part.immersiverailroading:component.radius_bar=ラディウスバー -part.immersiverailroading:component.expansion_link=拡張リンク -part.immersiverailroading:component.eccentric_rod=偏心棒 -part.immersiverailroading:component.eccentric_crank=偏心クランク -part.immersiverailroading:component.reversing_arm=逆転アーム -part.immersiverailroading:component.lifting_link=釣り上げリンク +part.immersiverailroading:component.radius_bar=心向棒 +part.immersiverailroading:component.expansion_link=加減リンク +part.immersiverailroading:component.eccentric_rod=エキセン棒 +part.immersiverailroading:component.eccentric_crank=返クランク +part.immersiverailroading:component.reversing_arm=逆転軸腕 +part.immersiverailroading:component.lifting_link=リフトリンク part.immersiverailroading:component.reach_rod=逆転棒 -part.immersiverailroading:component.walcherts_linkage=ヴァルスハールツリンケージ -part.immersiverailroading:component.smokebox=煙室 -part.immersiverailroading:component.gearbox=ギアボックス +part.immersiverailroading:component.walcherts_linkage=ワルシャートリンケージ +part.immersiverailroading:component.valve_rod=バルブギア部品 +part.immersiverailroading:controls.cylinder_drain=ドレイン +part.immersiverailroading:controls.bell=ベル +part.immersiverailroading:controls.whistle=汽笛 +part.immersiverailroading:controls.horn=タイフォン +part.immersiverailroading:controls.train_brake=自弁 +part.immersiverailroading:controls.independent_brake=単弁 +part.immersiverailroading:controls.throttle=加減弁 +part.immersiverailroading:controls.reverser=逆転機 +part.immersiverailroading:controls.throttle_brake=エンジンブレーキ +part.immersiverailroading:controls.engine_start=エンジンスイッチ + +multiblock.immersiverailroading:boiler_machine=ボイラーマシーン +multiblock.immersiverailroading:casting=鋳造機 +multiblock.immersiverailroading:plate_machine=プレート鍛造機 +multiblock.immersiverailroading:rail_machine=レール鍛造機 +multiblock.immersiverailroading:steam_hammer=蒸気ハンマー immersiverailroading:crafting_type.casting=鋳造機 -immersiverailroading:crafting_type.casting_hammer=鋳造機,パワーハンマー -immersiverailroading:crafting_type.plate_small=プレートローラー -immersiverailroading:crafting_type.plate_medium=プレートローラー -immersiverailroading:crafting_type.plate_large=プレートローラー -immersiverailroading:crafting_type.plate_boiler=プレートローラー, ボイラーローラー +immersiverailroading:crafting_type.casting_hammer=鋳造、鋳造ハンマー +immersiverailroading:crafting_type.plate_small=プレートローラー 小 +immersiverailroading:crafting_type.plate_medium=プレートローラー 中 +immersiverailroading:crafting_type.plate_large=プレートローラー 大 +immersiverailroading:crafting_type.plate_boiler=プレートローラー、ボイラーローラー itemGroup.immersiverailroading.main=Immersive Railroading itemGroup.immersiverailroading.locomotive=IR 機関車 -itemGroup.immersiverailroading.stock=IR 運搬車 +itemGroup.immersiverailroading.stock=IR 車両 itemGroup.immersiverailroading.passenger=IR 客車 itemGroup.immersiverailroading.components=IR 部品 -death.attack.immersiverailroading:casting=%s は溶けた鉄鋼が水泳プールに適していないことを学んだdeath.attack.immersiverailroading:hitByTrain=%s は「事故は起こるさ」を獲得した +death.attack.immersiverailroading:casting=%s は溶けた金属が泳ぐのに適していないことを学んだ +death.attack.immersiverailroading:hitByTrain=%s は列車から逃げきれなかった +death.attack.immersiverailroading:hitByTrainInDarkness=%s は向かってくる列車の前照灯が見えなかったようだ -immersiverailroading:detector_mode.simple=列車を検出 +immersiverailroading:detector_mode.simple=車両を検出 immersiverailroading:detector_mode.speed=速度を検出 -immersiverailroading:detector_mode.passengers乗客数を検出 -immersiverailroading:detector_mode.cargo=荷物が一杯であることを検出 -immersiverailroading:detector_mode.liquid=液体が一杯であることを検出immersiverailroading:detector_mode.computer=コンピューター -immersiverailroading:loco_control_mode.throttle_forward=スロットルを前にする -immersiverailroading:loco_control_mode.throttle_reverse=スロットルを後にする -immersiverailroading:loco_control_mode.brake=ブレーキをかける -immersiverailroading:loco_control_mode.horn=警笛を鳴らす +immersiverailroading:detector_mode.passengers=乗客数を検出 +immersiverailroading:detector_mode.cargo=貨物の積載率を検出 +immersiverailroading:detector_mode.liquid=液体の積載率を検出 +immersiverailroading:detector_mode.computer=コンピューター +immersiverailroading:loco_control_mode.throttle=加減弁 +immersiverailroading:loco_control_mode.reverser=逆転機 +immersiverailroading:loco_control_mode.brake=ブレーキ +immersiverailroading:loco_control_mode.horn=警笛 immersiverailroading:loco_control_mode.computer=コンピューター -immersiverailroading:coupler_augment_mode.engaged=連結する -immersiverailroading:coupler_augment_mode.disengaged=解結する +immersiverailroading:loco_control_mode.bell=ベル +immersiverailroading:coupler_augment_mode.engaged=連結 +immersiverailroading:coupler_augment_mode.disengaged=解結 +immersiverailroading:redstone_mode.enabled=有効 +immersiverailroading:redstone_mode.required=レッドストーンで有効 +immersiverailroading:redstone_mode.inverted=レッドストーンで無効 +immersiverailroading:redstone_mode.disabled=無効 + +immersiverailroading:switch_state.none=無 +immersiverailroading:switch_state.straight=直進 +immersiverailroading:switch_state.turn=分岐 key.categories.immersiverailroading=Immersive Railroading -ir_keys.increase_throttle=スロットルをあげる -ir_keys.zero_throttle=スロットルをゼロにする -ir_keys.decrease_throttle=スロットルをさげる -ir_keys.increase_brake=ブレーキをあげる -ir_keys.zero_brake=ブレーキをゼロにする -ir_keys.decrease_brake=ブレーキを下げる -ir_keys.horn=警笛を鳴らす -ir_keys.dead_mans_switch=デッドマンスイッチ +ir_keys.increase_throttle=加減弁を上げる +ir_keys.zero_throttle=加減弁をゼロにする +ir_keys.decrease_throttle=加減弁を下げる +ir_keys.increase_reverser=逆転機を前進に入れる +ir_keys.zero_reverser=逆転機をニュートラルにする +ir_keys.decrease_reverser=逆転機を後進に戻す +ir_keys.increase_brake=自弁を締める +ir_keys.zero_brake=自弁をゼロにする +ir_keys.decrease_brake=自弁を緩める +ir_keys.increase_independent_brake=単弁を締める +ir_keys.zero_independent_brake=単弁をゼロにする +ir_keys.decrease_independent_brake=単弁を緩める +ir_keys.horn=警笛 +ir_keys.bell=ベル +ir_keys.dead_mans_switch=デッドマン装置 ir_keys.start_stop_engine=エンジンを始動/停止する -ir_keys.config=Config +ir_keys.config=構成 + +# Default pack's train name. Translation is optional. +immersiverailroading:entity.locomotives.a1_peppercorn=A1 Peppercorn +immersiverailroading:entity.locomotives.a5_switcher=A5 Switcher +immersiverailroading:entity.locomotives.alco_rs1=RS-1 +immersiverailroading:entity.locomotives.big_boy=Big Boy (4000 class) +immersiverailroading:entity.locomotives.br01=br01 +immersiverailroading:entity.locomotives.class_38=Class 38 +immersiverailroading:entity.locomotives.cooke_mogul=DSP&P Mogul +immersiverailroading:entity.locomotives.e6_atlantic=E6 Atlantic +immersiverailroading:entity.locomotives.emd_sd40-2=EMD SD40-2 +immersiverailroading:entity.locomotives.emd_sw1500=SW1500 +immersiverailroading:entity.locomotives.firefly=Firefly +immersiverailroading:entity.locomotives.ge_40_ton_boxcab=Class B-B-70/70-4HM829 Boxcab +immersiverailroading:entity.locomotives.ge_b40_8=GE B40-8 +immersiverailroading:entity.locomotives.ge_b40_8w=GE B40-8w +immersiverailroading:entity.locomotives.ge_c44_9cw=GE C44-9CW +immersiverailroading:entity.locomotives.iron_duke=Iron Duke +immersiverailroading:entity.locomotives.k36=D&RGW K36 +immersiverailroading:entity.locomotives.k4_pacific=K4 Pacific +immersiverailroading:entity.locomotives.rodgers_460=Rodgers Ten Wheeler +immersiverailroading:entity.locomotives.skookum=Skookum 2-4-4-2 +immersiverailroading:entity.tender.a1_peppercorn_tender=A1 Peppercorn Tender +immersiverailroading:entity.tender.a5_tender=A5 Slope Tender +immersiverailroading:entity.tender.big_boy_tender=Big Boy (4000 class) Tender +immersiverailroading:entity.tender.br01_tender=drg class 01 tender +immersiverailroading:entity.tender.class_38_tender=Class 38 Tender +immersiverailroading:entity.tender.cooke_tender=Cooke Tender +immersiverailroading:entity.tender.e6_tender=E6 Atlantic Tender +immersiverailroading:entity.tender.k4_tender=K4 Pacific Tender +immersiverailroading:entity.tender.k36_tender=K36 Tender +immersiverailroading:entity.tender.rodgers_460_tender=Rodgers Ten Wheeler Tender +immersiverailroading:entity.tender.skookum_tender=Skookum Tender + +immersiverailroading:entity.hand_car.hand_car_1=Hand Car + +immersiverailroading:entity.passenger.b70baggage=PRR B70 Baggage +immersiverailroading:entity.passenger.br_coach_mk1=BR Coach MK1 +immersiverailroading:entity.passenger.p70coach1=PRR P70 Coach 1 + +immersiverailroading:entity.freight.70t_hopper_slsf=70T Hopper SLSF +immersiverailroading:entity.freight.attx_flatcar_1=ATTX Flatcar 1 +immersiverailroading:entity.freight.boxcar_x26=Box Car X26 +immersiverailroading:entity.freight.drgw_1000class_gondola=1000 Series Gondola +immersiverailroading:entity.freight.drgw_3000class_boxcar=3000 Series Boxcar +immersiverailroading:entity.freight.drgw_5500class_stockcar=5500 Series Stockcar +immersiverailroading:entity.freight.drgw_rail_and_tie_outfit=Rail & Tie Car +immersiverailroading:entity.freight.dw_gondola=DW Gondola +immersiverailroading:entity.freight.n5c_cabin_car=N5c Caboose +immersiverailroading:entity.freight.prr_flatcar_1=PRR Flatcar 1 +immersiverailroading:entity.freight.russell_snow_plow=Russell Snow Plow +immersiverailroading:entity.freight.usra_boxcar_classrr40=USRA Boxcar Class RR-40 +immersiverailroading:entity.freight.usra_hopper_55t=USRA Hopper 55T +immersiverailroading:entity.freight.waycar=Waycar + +immersiverailroading:entity.tank.kamx_t=Kamx T +immersiverailroading:entity.tank.slag_car_1=Slag Car 1 +immersiverailroading:entity.tank.tank_us2=Tank US 2 diff --git a/src/main/resources/assets/immersiverailroading/lang/ru_ru.lang b/src/main/resources/assets/immersiverailroading/lang/ru_ru.lang index 7c17689f7..d4595052b 100644 --- a/src/main/resources/assets/immersiverailroading/lang/ru_ru.lang +++ b/src/main/resources/assets/immersiverailroading/lang/ru_ru.lang @@ -1,4 +1,4 @@ -item.immersiverailroading:item_large_wrench.name=Железнодорожный ключ +item.immersiverailroading:item_large_wrench.name=Железнодорожный ключ item.immersiverailroading:item_hook.name=Сцепной крюк item.immersiverailroading:item_paint_brush.name=Малярная кисть item.immersiverailroading:item_augment.SPEED_RETARDER.name=Замедлитель скорости @@ -10,6 +10,7 @@ item.immersiverailroading:item_augment.FLUID_LOADER.name=Модуль загру item.immersiverailroading:item_augment.FLUID_UNLOADER.name=Модуль разгрузки жидкостей item.immersiverailroading:item_augment.DETECTOR.name=Датчик item.immersiverailroading:item_augment.COUPLER.name=Модуль автосцепки +item.immersiverailroading:item_augment.ACTUATOR.name=[Need translate] item.immersiverailroading:item_rail_part.name=Рельс item.immersiverailroading:item_cast_rail.name=Заготовка рельса item.immersiverailroading:item_manual.name=Руководство по эксплуатации @@ -31,7 +32,6 @@ chat.immersiverailroading:stock.missing=Недостает следующих ч chat.immersiverailroading:stock.invalid=Ошибка В02: невозможно разместить подвижной состав, данный тип подвижного состава не существует на сервере, так как пакет, в котором он состоит, не установлен на сервере. Проверьте, установили ли Вы этот пакет на сервер chat.immersiverailroading:stock.wrong_gauge=Ошибка А07: данный подвижной состав не предназначен для данной колеи! chat.immersiverailroading:stock.placement=Ошибка А04: подвижной состав должен быть установлен на прямом участке пути! -chat.immersiverailroading:brush.no.variants=Ошибка А11: к сожалению, данный подвижной состав не имеет альтернативных вариантов окраски chat.immersiverailroading:stock.deadmans_switch_enabled=Переключатель питания ТСКБМ: включен chat.immersiverailroading:stock.deadmans_switch_disabled=Переключатель питания ТСКБМ: отключен chat.immersiverailroading:coupler.front=Передняя @@ -51,37 +51,62 @@ chat.immersiverailroading:radio.relink=Радиоконтроллер подкл chat.immersiverailroading:radio.unlink=Радиоконтроллер отключен от локомотива chat.immersiverailroading:radio.nolink=Радиоконтроллер не привязан к какому-либо локомотиву chat.immersiverailroading:radio.cant_link=Локомотив %s не имеет системы удаленного радиоконтроля +chat.immersiverailroading:brush.no.variants=Ошибка А11: к сожалению, данный подвижной состав не имеет альтернативных вариантов окраски +chat.immersiverailroading:brush.next_debug=[Need translate] +chat.immersiverailroading:brush.mode.set=[Need translate] +chat.immersiverailroading:brush.mode.gui=[Need translate] +chat.immersiverailroading:brush.mode.random_single=[Need translate] +chat.immersiverailroading:brush.mode.random_coupled=[Need translate] chat.immersiverailroading:switch_state.unlocked=Стрелочный перевод разблокирован и готов к работе. chat.immersiverailroading:switch_state.locked=Стрелочный перевод заблокирован. Остряк (перо) %s +chat.immersiverailroading:switch_state.reset=[Need translate] +chat.immersiverailroading:switch_state.cant_reset=[Need translate] +chat.immersiverailroading:switch_state.already_reset=[Need translate] +chat.immersiverailroading:multiblock.select=[Need translate] -immersiverailroading:switch_state.none=Нет -immersiverailroading:switch_state.straight=прижат -immersiverailroading:switch_state.turn=отжат - -gui.immersiverailroading:item.switch_key=Используйте на стрелке чтобы переключиться между режимами (заблокировано в прямом положении, в поворотном положении или разблокировано). Если стрелка заблокирована, редстоун-сигнал игнорируется! -gui.immersiverailroading:item.track_exchanger=Щелкните правой кнопкой мыши в воздухе, чтобы открыть графический интерфейс выбора. Щелкните правой кнопкой мыши на пути, чтобы изменить его тип на тот, который определен в графическом интерфейсе -gui.immersiverailroading:none=Нет - +gui.immersiverailroading:label.brake=Тормоз +gui.immersiverailroading:label.throttle=Тяга +gui.immersiverailroading:label.reverser=[Need translate] +gui.immersiverailroading:slider.zoom=[Need translate] +gui.immersiverailroading:selector.page=[Need translate] gui.immersiverailroading:selector.type=Тип: %s gui.immersiverailroading:selector.gauge=Колея: %s gui.immersiverailroading:selector.track=Модель пути: %s gui.immersiverailroading:selector.quarters=Радиус поворота %s° +gui.immersiverailroading:selector.curvosity=[Need translate] gui.immersiverailroading:selector.rail_bed=Балласт: %s gui.immersiverailroading:selector.rail_bed_fill=Насыпь: %s gui.immersiverailroading:selector.position=Позиция установки пути: %s gui.immersiverailroading:selector.smoothing=Искривление %s gui.immersiverailroading:selector.direction=Фиксация направления: %s +gui.immersiverailroading:selector.transfer_table_entry_count=[Need translate] +gui.immersiverailroading:selector.transfer_table_entry_spacing=[Need translate] gui.immersiverailroading:selector.place_blueprint=Включить предварительный режим gui.immersiverailroading:selector.grade_crossing=Включить встраивание (для переездов) gui.immersiverailroading:selector.plate_type=Тип пластины: %s gui.immersiverailroading:selector.plate_boiler=Тип пластины (котловой): %s gui.immersiverailroading:selector.cast_single=Произвести единично gui.immersiverailroading:selector.cast_repeat=Произвести повторно +gui.immersiverailroading:selector.paintbrush_random=[Need translate] +gui.immersiverailroading:selector.paintbrush_apply_to_stock=[Need translate] +gui.immersiverailroading:selector.paintbrush_apply_to_train=[Need translate] + +gui.immersiverailroading:item.switch_key=Используйте на стрелке чтобы переключиться между режимами (заблокировано в прямом положении, в поворотном положении или разблокировано). Если стрелка заблокирована, редстоун-сигнал игнорируется! +gui.immersiverailroading:item.switch_key.data=[Need translate] + +gui.immersiverailroading:item.radio_card.linked_to=[Need translate] +gui.immersiverailroading:item.radio_card.not_linked=[Need translate] + +gui.immersiverailroading:item.track_exchanger=Щелкните правой кнопкой мыши в воздухе, чтобы открыть графический интерфейс выбора. Щелкните правой кнопкой мыши на пути, чтобы изменить его тип на тот, который определен в графическом интерфейсе +gui.immersiverailroading:item.paint_brush.mode=[Need translate] +gui.immersiverailroading:item.paint_brush.description=[Need translate] +gui.immersiverailroading:none=Нет gui.immersiverailroading:track.type=Тип: %s gui.immersiverailroading:track.length=Длина: %s gui.immersiverailroading:track.gauge=Колея: %s gui.immersiverailroading:track.quarters=%s° кривой +gui.immersiverailroading:track.curvosity=[Need translate] gui.immersiverailroading:track.position=Позиция установки пути: %s gui.immersiverailroading:track.smoothing=Искривление %s gui.immersiverailroading:track.direction=Фиксация направления: %s @@ -90,6 +115,33 @@ gui.immersiverailroading:track.rail_bed_fill=Насыпь: %s gui.immersiverailroading:track.place_blueprint_true=Предварительный режим gui.immersiverailroading:track.place_blueprint_false=Обычная установка пути +gui.immersiverailroading:loco.works=Эксплуатируется: %s +gui.immersiverailroading:loco.power=[Need translate] +gui.immersiverailroading:loco.tractive_effort=[Need translate] +gui.immersiverailroading:loco.max_speed=Максимальная скорость: %s +gui.immersiverailroading:stock.gauge=Колея: %s +gui.immersiverailroading:stock.texture=Окрас: %s +gui.immersiverailroading:cast.raw=Необходима обработка в паровом молоте перед использованием! +gui.immersiverailroading:stock.tank_capacity=Вместимость жидкости: %s вёдер +gui.immersiverailroading:stock.freight_capacity=Вместимость груза: %s слотов +gui.immersiverailroading:stock.weight=Вес: %s кг +gui.immersiverailroading:stock.modeler=Создатель: %s +gui.immersiverailroading:stock.pack=Пакет моделей: %s + +gui.immersiverailroading:overlay.on=[Need translate] +gui.immersiverailroading:overlay.off=[Need translate] + +immersiverailroading:gauge.brunel=Сверхширокая (3000/≈2,88) +immersiverailroading:gauge.standard=Стандартная советская (1524/≈1,55) +immersiverailroading:gauge.narrow=Узкая (1196/≈1,25) +immersiverailroading:gauge.minecraft=Метровая (1000/1,00) +immersiverailroading:gauge.model=Модельная (25/0,25) + +immersiverailroading:plate.small=Малая стандартная пластина +immersiverailroading:plate.medium=Средняя стандартная пластина +immersiverailroading:plate.large=Большая стандартная пластина +immersiverailroading:plate.boiler=Универсальная котловая пластина + track.immersiverailroading:class.straight=Прямая track.immersiverailroading:class.crossing=Пересечение track.immersiverailroading:class.slope=Подъём @@ -114,32 +166,9 @@ track.immersiverailroading:direction.none=Нет track.immersiverailroading:direction.left=Только влево track.immersiverailroading:direction.right=Только вправо -gui.immersiverailroading:loco.works=Эксплуатируется: %s -gui.immersiverailroading:loco.horse_power=Мощность %s лошадиных сил -gui.immersiverailroading:loco.tractive_effort=Тяговое усилие: %s ньютонов -gui.immersiverailroading:loco.max_speed=Максимальная скорость: %s -gui.immersiverailroading:stock.gauge=Колея: %s -gui.immersiverailroading:stock.texture=Окрас: %s -gui.immersiverailroading:cast.raw=Необходима обработка в паровом молоте перед использованием! -gui.immersiverailroading:stock.tank_capacity=Вместимость жидкости: %s вёдер -gui.immersiverailroading:stock.freight_capacity=Вместимость груза: %s слотов -gui.immersiverailroading:stock.weight=Вес: %s кг -gui.immersiverailroading:stock.modeler=Создатель: %s -gui.immersiverailroading:stock.pack=Пакет моделей: %s - -immersiverailroading:gauge.brunel=Сверхширокая (3000/≈2,88) -immersiverailroading:gauge.standard=Стандартная советская (1524/≈1,55) -immersiverailroading:gauge.narrow=Узкая (1196/≈1,25) -immersiverailroading:gauge.minecraft=Метровая (1000/1,00) -immersiverailroading:gauge.model=Модельная (25/0,25) - -immersiverailroading:plate.small=Малая стандартная пластина -immersiverailroading:plate.medium=Средняя стандартная пластина -immersiverailroading:plate.large=Большая стандартная пластина -immersiverailroading:plate.boiler=Универсальная котловая пластина - part.immersiverailroading:component.frame=Рама part.immersiverailroading:component.front_frame=Передняя рама +part.immersiverailroading:component.rear_frame=[Need translate] part.immersiverailroading:component.bogey_wheel=Колёсная пара для тележки part.immersiverailroading:component.bogey=Тележка part.immersiverailroading:component.bogey_front_wheel=Передняя колёсная пара @@ -155,16 +184,22 @@ part.immersiverailroading:component.horn=Гудок part.immersiverailroading:component.fuel_tank=Топливный бак part.immersiverailroading:component.alternator=Генератор переменного тока part.immersiverailroading:component.engine_block=Двигательный блок +part.immersiverailroading:component.crankshaft=[Need translate] part.immersiverailroading:component.piston=Поршень +part.immersiverailroading:component.fan=[Need translate] +part.immersiverailroading:component.drive_shaft=[Need translate] +part.immersiverailroading:component.gearbox=Трансмиссия +part.immersiverailroading:component.fluid_coupling=[Need translate] +part.immersiverailroading:component.final_drive=[Need translate] +part.immersiverailroading:component.torque_converter=[Need translate] part.immersiverailroading:component.firebox=Топка +part.immersiverailroading:component.smokebox=Дымовая коробка part.immersiverailroading:component.steam_chest=Паровая коробка -part.immersiverailroading:component.steam_chest_front=Передняя часть паровой коробки -part.immersiverailroading:component.steam_chest_rear=Задняя часть паровой коробки +part.immersiverailroading:component.steam_chest_pos=[Need translate] part.immersiverailroading:component.boiler_segment=Сегмент бойлера part.immersiverailroading:component.piping=Трубопровод part.immersiverailroading:component.wheel_driver=Ведущая колёсная пара -part.immersiverailroading:component.wheel_driver_front=Передняя ведущая колёсная пара -part.immersiverailroading:component.wheel_driver_rear=Задняя ведущая колёсная пара +part.immersiverailroading:component.wheel_driver_pos=[Need translate] part.immersiverailroading:component.cylinder=Цилиндр part.immersiverailroading:component.side_rod=Спарник part.immersiverailroading:component.main_rod=Дышло @@ -180,10 +215,24 @@ part.immersiverailroading:component.reversing_arm=Реверсивный рыч part.immersiverailroading:component.lifting_link=Подъемная связь part.immersiverailroading:component.reach_rod=Шток дистанционного привода клапана part.immersiverailroading:component.walcherts_linkage=Парораспределительный механизм Вальсхарта -part.immersiverailroading:component.smokebox=Дымовая коробка -part.immersiverailroading:component.gearbox=Трансмиссия -gui.immersiverailroading:label.brake=Тормоз -gui.immersiverailroading:label.throttle=Тяга +part.immersiverailroading:component.valve_rod=[Need translate] + +part.immersiverailroading:controls.cylinder_drain=[Need translate] +part.immersiverailroading:controls.bell=[Need translate] +part.immersiverailroading:controls.whistle=[Need translate] +part.immersiverailroading:controls.horn=[Need translate] +part.immersiverailroading:controls.train_brake=[Need translate] +part.immersiverailroading:controls.independent_brake=[Need translate] +part.immersiverailroading:controls.throttle=[Need translate] +part.immersiverailroading:controls.reverser=[Need translate] +part.immersiverailroading:controls.throttle_brake=[Need translate] +part.immersiverailroading:controls.engine_start=[Need translate] + +multiblock.immersiverailroading:boiler_machine=[Need translate] +multiblock.immersiverailroading:casting=[Need translate] +multiblock.immersiverailroading:plate_machine=[Need translate] +multiblock.immersiverailroading:rail_machine=[Need translate] +multiblock.immersiverailroading:steam_hammer=[Need translate] immersiverailroading:crafting_type.casting=Литьё immersiverailroading:crafting_type.casting_hammer=Литьё, мех. молот @@ -200,6 +249,7 @@ itemGroup.immersiverailroading.components=Компоненты ПС death.attack.immersiverailroading:casting=%s открыл для себя, что, увы, резервуар с расскаленным металлом нельзя использовать в качестве бассейна. death.attack.immersiverailroading:hitByTrain=%s попал под поезд +death.attack.immersiverailroading:hitByTrainInDarkness=[Need translate] immersiverailroading:detector_mode.simple=Обнаружение подвижного состава immersiverailroading:detector_mode.speed=Измерение скорости @@ -207,11 +257,12 @@ immersiverailroading:detector_mode.passengers=Счет пассажиров immersiverailroading:detector_mode.cargo=Измерение загруженности грузовых вагонов (в %) immersiverailroading:detector_mode.liquid=Измерение загруженности жидкостных грузовых вагонов (в%) immersiverailroading:detector_mode.computer=Компьютер -immersiverailroading:loco_control_mode.throttle_forward=Тяга вперед -immersiverailroading:loco_control_mode.throttle_reverse=Реверсивная тяга +immersiverailroading:loco_control_mode.throttle=[Need translate] +immersiverailroading:loco_control_mode.reverser=[Need translate] immersiverailroading:loco_control_mode.brake=Пневматический тормоз immersiverailroading:loco_control_mode.horn=Гудок immersiverailroading:loco_control_mode.computer=Компьютер +immersiverailroading:loco_control_mode.bell=[Need translate] immersiverailroading:coupler_augment_mode.engaged=Сцепка immersiverailroading:coupler_augment_mode.disengaged=Расцепка immersiverailroading:redstone_mode.enabled=Включён @@ -219,15 +270,83 @@ immersiverailroading:redstone_mode.required=Включён с Редстоуно immersiverailroading:redstone_mode.inverted=Отключен с Редстоуном immersiverailroading:redstone_mode.disabled=Отключён +immersiverailroading:switch_state.none=Нет +immersiverailroading:switch_state.straight=прижат +immersiverailroading:switch_state.turn=отжат + key.categories.immersiverailroading=Immersive Railroading ir_keys.increase_throttle=Увеличить тягу ir_keys.zero_throttle=Обнулить тягу ir_keys.decrease_throttle=Уменьшить тягу +ir_keys.increase_reverser=[Need translate] +ir_keys.zero_reverser=[Need translate] +ir_keys.decrease_reverser=[Need translate] ir_keys.increase_brake=Торможение (пневматический тормоз) ir_keys.zero_brake=Отпустить пневматический тормоз ir_keys.decrease_brake=Ослабить пневматический тормоз +ir_keys.increase_independent_brake=[Need translate] +ir_keys.zero_independent_brake=[Need translate] +ir_keys.decrease_independent_brake=[Need translate] ir_keys.horn=Гудок ir_keys.bell=Колокол ir_keys.dead_mans_switch=Переключатель питания ТСКБМ ir_keys.start_stop_engine=Запуск/остановка двигателя (для диз- или эл-поездов) ir_keys.config=Конфигурация + +# Default pack's train name. Translation is optional. +immersiverailroading:entity.locomotives.a1_peppercorn=A1 Peppercorn +immersiverailroading:entity.locomotives.a5_switcher=A5 Switcher +immersiverailroading:entity.locomotives.alco_rs1=RS-1 +immersiverailroading:entity.locomotives.big_boy=Big Boy (4000 class) +immersiverailroading:entity.locomotives.br01=br01 +immersiverailroading:entity.locomotives.class_38=Class 38 +immersiverailroading:entity.locomotives.cooke_mogul=DSP&P Mogul +immersiverailroading:entity.locomotives.e6_atlantic=E6 Atlantic +immersiverailroading:entity.locomotives.emd_sd40-2=EMD SD40-2 +immersiverailroading:entity.locomotives.emd_sw1500=SW1500 +immersiverailroading:entity.locomotives.firefly=Firefly +immersiverailroading:entity.locomotives.ge_40_ton_boxcab=Class B-B-70/70-4HM829 Boxcab +immersiverailroading:entity.locomotives.ge_b40_8=GE B40-8 +immersiverailroading:entity.locomotives.ge_b40_8w=GE B40-8w +immersiverailroading:entity.locomotives.ge_c44_9cw=GE C44-9CW +immersiverailroading:entity.locomotives.iron_duke=Iron Duke +immersiverailroading:entity.locomotives.k36=D&RGW K36 +immersiverailroading:entity.locomotives.k4_pacific=K4 Pacific +immersiverailroading:entity.locomotives.rodgers_460=Rodgers Ten Wheeler +immersiverailroading:entity.locomotives.skookum=Skookum 2-4-4-2 +immersiverailroading:entity.tender.a1_peppercorn_tender=A1 Peppercorn Tender +immersiverailroading:entity.tender.a5_tender=A5 Slope Tender +immersiverailroading:entity.tender.big_boy_tender=Big Boy (4000 class) Tender +immersiverailroading:entity.tender.br01_tender=drg class 01 tender +immersiverailroading:entity.tender.class_38_tender=Class 38 Tender +immersiverailroading:entity.tender.cooke_tender=Cooke Tender +immersiverailroading:entity.tender.e6_tender=E6 Atlantic Tender +immersiverailroading:entity.tender.k4_tender=K4 Pacific Tender +immersiverailroading:entity.tender.k36_tender=K36 Tender +immersiverailroading:entity.tender.rodgers_460_tender=Rodgers Ten Wheeler Tender +immersiverailroading:entity.tender.skookum_tender=Skookum Tender + +immersiverailroading:entity.hand_car.hand_car_1=Hand Car + +immersiverailroading:entity.passenger.b70baggage=PRR B70 Baggage +immersiverailroading:entity.passenger.br_coach_mk1=BR Coach MK1 +immersiverailroading:entity.passenger.p70coach1=PRR P70 Coach 1 + +immersiverailroading:entity.freight.70t_hopper_slsf=70T Hopper SLSF +immersiverailroading:entity.freight.attx_flatcar_1=ATTX Flatcar 1 +immersiverailroading:entity.freight.boxcar_x26=Box Car X26 +immersiverailroading:entity.freight.drgw_1000class_gondola=1000 Series Gondola +immersiverailroading:entity.freight.drgw_3000class_boxcar=3000 Series Boxcar +immersiverailroading:entity.freight.drgw_5500class_stockcar=5500 Series Stockcar +immersiverailroading:entity.freight.drgw_rail_and_tie_outfit=Rail & Tie Car +immersiverailroading:entity.freight.dw_gondola=DW Gondola +immersiverailroading:entity.freight.n5c_cabin_car=N5c Caboose +immersiverailroading:entity.freight.prr_flatcar_1=PRR Flatcar 1 +immersiverailroading:entity.freight.russell_snow_plow=Russell Snow Plow +immersiverailroading:entity.freight.usra_boxcar_classrr40=USRA Boxcar Class RR-40 +immersiverailroading:entity.freight.usra_hopper_55t=USRA Hopper 55T +immersiverailroading:entity.freight.waycar=Waycar + +immersiverailroading:entity.tank.kamx_t=Kamx T +immersiverailroading:entity.tank.slag_car_1=Slag Car 1 +immersiverailroading:entity.tank.tank_us2=Tank US 2 diff --git a/src/main/resources/assets/immersiverailroading/lang/zh_cn.lang b/src/main/resources/assets/immersiverailroading/lang/zh_cn.lang index abce7170a..f8f246abb 100644 --- a/src/main/resources/assets/immersiverailroading/lang/zh_cn.lang +++ b/src/main/resources/assets/immersiverailroading/lang/zh_cn.lang @@ -1,103 +1,141 @@ item.immersiverailroading:item_large_wrench.name=大型扳手 item.immersiverailroading:item_hook.name=车钩 item.immersiverailroading:item_paint_brush.name=油漆刷 -item.immersiverailroading:item_augment.SPEED_RETARDER.name=高速减速器 -item.immersiverailroading:item_augment.WATER_TROUGH.name=水槽 +item.immersiverailroading:item_augment.SPEED_RETARDER.name=车辆减速器 +item.immersiverailroading:item_augment.WATER_TROUGH.name=水槽(暂无实际作用) item.immersiverailroading:item_augment.LOCO_CONTROL.name=机车控制器 item.immersiverailroading:item_augment.ITEM_LOADER.name=物品装载器 item.immersiverailroading:item_augment.ITEM_UNLOADER.name=物品卸载器 item.immersiverailroading:item_augment.FLUID_LOADER.name=流体装载器 item.immersiverailroading:item_augment.FLUID_UNLOADER.name=流体卸载器 -item.immersiverailroading:item_augment.DETECTOR.name=探测器 -item.immersiverailroading:item_augment.COUPLER.name=联结器 -item.immersiverailroading:item_rail_part.name=铁轨段 -item.immersiverailroading:item_cast_rail.name=铁轨铸件 +item.immersiverailroading:item_augment.DETECTOR.name=车辆状态检测器 +item.immersiverailroading:item_augment.COUPLER.name=车钩连接器 +item.immersiverailroading:item_augment.ACTUATOR.name=车门步进器 +item.immersiverailroading:item_rail_part.name=钢轨段 +item.immersiverailroading:item_cast_rail.name=钢轨铸件 item.immersiverailroading:item_manual.name=沉浸铁路指南 item.immersiverailroading:item_rail.name=轨道蓝图 item.immersiverailroading:item_conductor_whistle.name=乘务员口哨 item.immersiverailroading:item_golden_spike.name=金道钉 item.immersiverailroading:item_radio_control_card.name=列车无线遥控卡 +item.immersiverailroading:item_switch_key.name=道岔钥匙 +item.immersiverailroading:item_track_exchanger.name=轨道样式更换器 -tile.immersiverailroading:block_rail.name=铁轨 -tile.immersiverailroading:block_rail_gag.name=铁轨(终止) -tile.immersiverailroading:block_rail_preview.name=铁轨预览 +tile.immersiverailroading:block_rail.name=轨道 +tile.immersiverailroading:block_rail_gag.name=轨道(占位) +tile.immersiverailroading:block_rail_preview.name=轨道(预览) tile.immersiverailroading:block_steam_hammer.name=蒸汽锤 -chat.immersiverailroading:stock.built=%s 完成组装! -chat.immersiverailroading:stock.dissasembled=%s 被拆卸了! -chat.immersiverailroading:stock.missing=缺失:%s -chat.immersiverailroading:stock.invalid=错误:服务器上不存在此机车。无法放置 -chat.immersiverailroading:stock.wrong_gauge=轨距错误! -chat.immersiverailroading:stock.placement=机车必须放在直行铁轨上 +chat.immersiverailroading:stock.built=%s 已组装完成! +chat.immersiverailroading:stock.dissasembled=%s 已拆解完成! +chat.immersiverailroading:stock.missing=缺失组件:%s +chat.immersiverailroading:stock.invalid=错误:服务器上不存在此机车,无法放置。请确保你于此服务器拥有一致的资源包并启用! +chat.immersiverailroading:stock.wrong_gauge=车厢与轨道的轨距不符! +chat.immersiverailroading:stock.placement=机车必须放置在直行轨道上! chat.immersiverailroading:stock.deadmans_switch_enabled=失能开关开启 chat.immersiverailroading:stock.deadmans_switch_disabled=失能开关关闭 -chat.immersiverailroading:coupler.front=前部 -chat.immersiverailroading:coupler.back=后部 +chat.immersiverailroading:coupler.front=前端 +chat.immersiverailroading:coupler.back=后端 chat.immersiverailroading:coupler.engaged=车钩 %s 设置为正常模式 chat.immersiverailroading:coupler.disengaged=车钩 %s 设置为调车模式 -chat.immersiverailroading:coupler.status.coupled=%s 车钩连接到 %s(%s,%s,%s) -chat.immersiverailroading:coupler.status.decoupled.engaged=%s 车钩在正常模式下被解开 -chat.immersiverailroading:coupler.status.decoupled.disengaged=%s 车钩在分流模式下解开 +chat.immersiverailroading:coupler.status.coupled=%s 车钩已与 %s(%s,%s,%s)连挂 +chat.immersiverailroading:coupler.status.decoupled.engaged=%s 车钩在正常模式下解挂 +chat.immersiverailroading:coupler.status.decoupled.disengaged=%s 车钩在调车模式下解挂 chat.immersiverailroading:build.missing=缺失 %s -chat.immersiverailroading:augment.set=设置参数在 %s 时发挥作用 -chat.immersiverailroading:augment.reset=设置参数作用于任意铁轨 +chat.immersiverailroading:augment.set=Augment过滤器设置为仅与 %s 交互 +chat.immersiverailroading:augment.reset=清空Augment过滤器 chat.immersiverailroading:misc.wood_planks=木板 -chat.immersiverailroading:build.invalid_block=(x=%s y=%s z=%s)处有非法方块 -chat.immersiverailroading:radio.link=遥控卡已经连接到机车 -chat.immersiverailroading:radio.relink=遥控卡已经连接到新的机车 -chat.immersiverailroading:radio.unlink=遥控卡与机车分离 -chat.immersiverailroading:radio.nolink=遥控卡没有连接的机车 -chat.immersiverailroading:radio.cant_link=%s 机车没有无线控制装置 +chat.immersiverailroading:build.invalid_block=(x=%s y=%s z=%s)处有不可替换的方块,请先清除后再放置多方块结构! +chat.immersiverailroading:radio.link=遥控卡已连接到机车 +chat.immersiverailroading:radio.relink=遥控卡已重连到新的机车 +chat.immersiverailroading:radio.unlink=遥控卡已与机车断开连接 +chat.immersiverailroading:radio.nolink=遥控卡未连接到任何机车 +chat.immersiverailroading:radio.cant_link=%s 机车没有无线控制系统,无法连接 chat.immersiverailroading:brush.no.variants=这辆车没有涂装变体 +chat.immersiverailroading:brush.next_debug=这辆车的涂装已设置为:%s(%s模式) +chat.immersiverailroading:brush.mode.set=油漆刷模式已切换为:%s +chat.immersiverailroading:brush.mode.gui=涂装选择菜单 +chat.immersiverailroading:brush.mode.random_single=随机(仅此车厢) +chat.immersiverailroading:brush.mode.random_coupled=随机 (整列车) +chat.immersiverailroading:switch_state.unlocked=道岔方向已解锁 +chat.immersiverailroading:switch_state.locked=道岔方向已锁定为 %s +chat.immersiverailroading:switch_state.reset=最后使用此钥匙锁定的道岔已成功解锁! +chat.immersiverailroading:switch_state.cant_reset=此钥匙尚未与任何道岔绑定! +chat.immersiverailroading:switch_state.already_reset=最后使用此钥匙锁定的道岔已被解锁! +chat.immersiverailroading:multiblock.select=已选择多方块结构:%s gui.immersiverailroading:label.brake=制动 gui.immersiverailroading:label.throttle=节流阀 +gui.immersiverailroading:label.reverser=换向器 +gui.immersiverailroading:slider.zoom=缩放比例: +gui.immersiverailroading:selector.page=第 %s 页,共 %s 页 gui.immersiverailroading:selector.type=类型:%s gui.immersiverailroading:selector.gauge=轨距:%s +gui.immersiverailroading:selector.track=轨道样式:%s gui.immersiverailroading:selector.quarters=%s 度弯道 -gui.immersiverailroading:selector.rail_bed=铁轨基座:%s -gui.immersiverailroading:selector.rail_bed_fill=铁轨基座填方:%s -gui.immersiverailroading:selector.position=位置:%s +gui.immersiverailroading:selector.curvosity=%s 曲率 +gui.immersiverailroading:selector.rail_bed=道床类型:%s +gui.immersiverailroading:selector.rail_bed_fill=道床填方类型:%s +gui.immersiverailroading:selector.position=位置锁定方式:%s +gui.immersiverailroading:selector.smoothing=垂直平滑:%s gui.immersiverailroading:selector.direction=方向:%s +gui.immersiverailroading:selector.transfer_table_entry_count=移车台轨道数:%s +gui.immersiverailroading:selector.transfer_table_entry_spacing=移车台轨道间距:%s gui.immersiverailroading:selector.place_blueprint=放置蓝图 -gui.immersiverailroading:selector.grade_crossing=铁路道口 +gui.immersiverailroading:selector.grade_crossing=设置为平交道口 gui.immersiverailroading:selector.plate_type=板材类型:%s gui.immersiverailroading:selector.plate_boiler=锅炉板材:%s gui.immersiverailroading:selector.cast_single=单次铸造 gui.immersiverailroading:selector.cast_repeat=循环铸造 +gui.immersiverailroading:selector.paintbrush_random=应用随机涂装 +gui.immersiverailroading:selector.paintbrush_apply_to_stock=应用至此车厢 +gui.immersiverailroading:selector.paintbrush_apply_to_train=应用至整列车 + +gui.immersiverailroading:item.switch_key=右击循环切换模式:锁定直向、锁定侧向、不锁定。锁定后道岔将忽略红石信号! +gui.immersiverailroading:item.switch_key.data=最后锁定的道岔:%s,模式:%s + +gui.immersiverailroading:item.radio_card.linked_to=已连接至 %s +gui.immersiverailroading:item.radio_card.not_linked=未连接至任何机车 + +gui.immersiverailroading:item.track_exchanger=对空气右击打开GUI,对轨道右击应用所选类型 +gui.immersiverailroading:item.paint_brush.mode=当前模式:%s +gui.immersiverailroading:item.paint_brush.description=潜行右击以循环切换模式 gui.immersiverailroading:none=无 gui.immersiverailroading:track.type=类型:%s gui.immersiverailroading:track.length=长度:%s gui.immersiverailroading:track.gauge=轨距:%s gui.immersiverailroading:track.quarters=%s 度转弯 -gui.immersiverailroading:track.position=位置:%s +gui.immersiverailroading:track.curvosity=%s 曲率 +gui.immersiverailroading:track.position=位置锁定方式:%s +gui.immersiverailroading:track.smoothing=垂直平滑:%s gui.immersiverailroading:track.direction=方向:%s -gui.immersiverailroading:selector.transfer_table_entry_count=移车台入口数: %s -gui.immersiverailroading:selector.transfer_table_entry_spacing=移车台轨道间距: %s -gui.immersiverailroading:track.rail_bed=基座:%s -gui.immersiverailroading:track.rail_bed_fill=基座填方:%s -gui.immersiverailroading:track.place_blueprint_true=放置:蓝图 -gui.immersiverailroading:track.place_blueprint_false=放置:轨道 +gui.immersiverailroading:track.rail_bed=道床:%s +gui.immersiverailroading:track.rail_bed_fill=道床填方:%s +gui.immersiverailroading:track.place_blueprint_true=放置轨道蓝图 +gui.immersiverailroading:track.place_blueprint_false=直接放置轨道 gui.immersiverailroading:loco.works=服务公司:%s -gui.immersiverailroading:loco.horse_power=马力:%s -gui.immersiverailroading:loco.tractive_effort=牵引力 %s 牛顿 -gui.immersiverailroading:loco.max_speed=最大速度:%s +gui.immersiverailroading:loco.power=功率:%s +gui.immersiverailroading:loco.tractive_effort=牵引力:%s +gui.immersiverailroading:loco.max_speed=最高速度:%s gui.immersiverailroading:stock.gauge=轨距:%s -gui.immersiverailroading:stock.texture=变体:%s -gui.immersiverailroading:cast.raw=使用前需要在蒸汽锤中加工! -gui.immersiverailroading:stock.tank_capacity=容量:%s 桶 -gui.immersiverailroading:stock.freight_capacity=容量:%s 组 +gui.immersiverailroading:stock.texture=涂装:%s +gui.immersiverailroading:cast.raw=使用前需经蒸汽锤加工! +gui.immersiverailroading:stock.tank_capacity=液体容积:%s 桶 +gui.immersiverailroading:stock.freight_capacity=物品容量:%s 组 gui.immersiverailroading:stock.weight=重量:%s Kg gui.immersiverailroading:stock.modeler=模型作者:%s -gui.immersiverailroading:stock.pack=包:%s +gui.immersiverailroading:stock.pack=所属资源包:%s + +gui.immersiverailroading:overlay.on=开 +gui.immersiverailroading:overlay.off=关 immersiverailroading:gauge.brunel=布鲁内尔轨 immersiverailroading:gauge.standard=标准轨 immersiverailroading:gauge.narrow=窄轨 -immersiverailroading:gauge.minecraft=Minecraft -immersiverailroading:gauge.model=模型 +immersiverailroading:gauge.minecraft=Minecraft轨 +immersiverailroading:gauge.model=模型轨 immersiverailroading:plate.small=小型板材 immersiverailroading:plate.medium=中型板材 @@ -106,8 +144,8 @@ immersiverailroading:plate.boiler=锅炉板材 track.immersiverailroading:class.straight=直行 track.immersiverailroading:class.crossing=道口 -track.immersiverailroading:class.slope=斜坡 -track.immersiverailroading:class.turn=弯道 +track.immersiverailroading:class.slope=坡道 +track.immersiverailroading:class.turn=圆弧 track.immersiverailroading:class.turntable=转车台 track.immersiverailroading:class.transfertable=移车台 track.immersiverailroading:class.switch=道岔 @@ -115,66 +153,93 @@ track.immersiverailroading:class.custom=自定义曲线 track.immersiverailroading:position.fixed=对齐方块 track.immersiverailroading:position.pixels=对齐像素 -track.immersiverailroading:position.pixels_locked=锁定像素 +track.immersiverailroading:position.pixels_locked=像素锁定 track.immersiverailroading:position.smooth=无限制 track.immersiverailroading:position.smooth_locked=平滑锁定 -track.immersiverailroading:direction.none=无锁定 -track.immersiverailroading:direction.left=右侧锁定 -track.immersiverailroading:direction.right=左侧锁定 +track.immersiverailroading:smoothing.both=双向平滑 +track.immersiverailroading:smoothing.near=仅近端平滑 +track.immersiverailroading:smoothing.far=仅远端平滑 +track.immersiverailroading:smoothing.neither=无平滑 + +track.immersiverailroading:direction.none=不锁定 +track.immersiverailroading:direction.left=锁定至右向 +track.immersiverailroading:direction.right=锁定至左向 part.immersiverailroading:component.frame=车架 part.immersiverailroading:component.front_frame=前车架 -part.immersiverailroading:component.bogey_wheel=底盘轮 +part.immersiverailroading:component.rear_frame=后车架 +part.immersiverailroading:component.bogey_wheel=转向架轮 part.immersiverailroading:component.bogey=转向架 -part.immersiverailroading:component.bogey_front_wheel=转向架前轮 -part.immersiverailroading:component.bogey_front=转向架前端 -part.immersiverailroading:component.bogey_rear_wheel=转向架后轮 -part.immersiverailroading:component.bogey_rear=转向架后端 +part.immersiverailroading:component.bogey_front_wheel=前转向架轮 +part.immersiverailroading:component.bogey_front=前转向架 +part.immersiverailroading:component.bogey_rear_wheel=后转向架轮 +part.immersiverailroading:component.bogey_rear=后转向架 part.immersiverailroading:component.frame_wheel=车架轮 part.immersiverailroading:component.shell=外壳 part.immersiverailroading:component.cab=司机室 part.immersiverailroading:component.bell=警铃 -part.immersiverailroading:component.whistle=车哨 -part.immersiverailroading:component.horn=喇叭 +part.immersiverailroading:component.whistle=汽笛 +part.immersiverailroading:component.horn=风笛 part.immersiverailroading:component.fuel_tank=燃料箱 part.immersiverailroading:component.alternator=发电机 -part.immersiverailroading:component.engine_block=发动机座 +part.immersiverailroading:component.engine_block=发动机缸体 +part.immersiverailroading:component.crankshaft=发动机曲轴 part.immersiverailroading:component.piston=活塞 +part.immersiverailroading:component.fan=风机 +part.immersiverailroading:component.drive_shaft=传动轴 +part.immersiverailroading:component.gearbox=传动齿轮箱 +part.immersiverailroading:component.fluid_coupling=液力耦合器 +part.immersiverailroading:component.final_drive=最终传动 +part.immersiverailroading:component.torque_converter=液力变矩器 part.immersiverailroading:component.firebox=燃烧室 -part.immersiverailroading:component.steam_chest=蒸汽箱 -part.immersiverailroading:component.steam_chest_front=前蒸汽箱 -part.immersiverailroading:component.steam_chest_rear=后蒸汽箱 -part.immersiverailroading:component.boiler_segment=锅炉部分 -part.immersiverailroading:component.piping=管道 -part.immersiverailroading:component.wheel_driver=车轮驱动器 -part.immersiverailroading:component.wheel_driver_front=车轮驱动器前端 -part.immersiverailroading:component.wheel_driver_rear=车轮驱动器后端 +part.immersiverailroading:component.smokebox=烟箱 +part.immersiverailroading:component.steam_chest=汽室 +part.immersiverailroading:component.steam_chest_pos=车架汽室 +part.immersiverailroading:component.boiler_segment=锅炉段 +part.immersiverailroading:component.piping=管系 +part.immersiverailroading:component.wheel_driver=动轮 +part.immersiverailroading:component.wheel_driver_pos=车架动轮 part.immersiverailroading:component.cylinder=汽缸 -part.immersiverailroading:component.side_rod=侧杆 -part.immersiverailroading:component.main_rod=主杆 -part.immersiverailroading:component.piston_rod=活塞杆 -part.immersiverailroading:component.union_link=结合连接器 -part.immersiverailroading:component.combination_lever=组合杠杆 +part.immersiverailroading:component.side_rod=摇杆 +part.immersiverailroading:component.main_rod=主连杆 +part.immersiverailroading:component.piston_rod=十字头 +part.immersiverailroading:component.union_link=结合杆 +part.immersiverailroading:component.combination_lever=合并杆 part.immersiverailroading:component.valve_stem=阀杆 -part.immersiverailroading:component.radius_bar=曲拐臂 -part.immersiverailroading:component.expansion_link=扩展连接器 +part.immersiverailroading:component.radius_bar=半径杆 +part.immersiverailroading:component.expansion_link=月牙板 part.immersiverailroading:component.eccentric_rod=偏心杆 part.immersiverailroading:component.eccentric_crank=偏心曲柄 -part.immersiverailroading:component.reversing_arm=倒车臂 -part.immersiverailroading:component.lifting_link=起重连接器 -part.immersiverailroading:component.reach_rod=触杆 -part.immersiverailroading:component.walcherts_linkage=瓦尔希茨连接器 -part.immersiverailroading:component.smokebox=烟箱 -part.immersiverailroading:component.gearbox=齿轮箱 +part.immersiverailroading:component.reversing_arm=回动臂 +part.immersiverailroading:component.lifting_link=吊杆 +part.immersiverailroading:component.reach_rod=连接杆 +part.immersiverailroading:component.walcherts_linkage=华氏阀动装置 +part.immersiverailroading:component.valve_rod=阀动装置组件 +part.immersiverailroading:controls.cylinder_drain=汽缸排水阀 +part.immersiverailroading:controls.bell=警铃 +part.immersiverailroading:controls.whistle=汽笛 +part.immersiverailroading:controls.horn=风笛 +part.immersiverailroading:controls.train_brake=列车制动阀 +part.immersiverailroading:controls.independent_brake=单独制动阀 +part.immersiverailroading:controls.throttle=节流阀 +part.immersiverailroading:controls.reverser=换向器 +part.immersiverailroading:controls.throttle_brake=制动机 +part.immersiverailroading:controls.engine_start=启动/停止发动机 -immersiverailroading:crafting_type.casting=铸造 -immersiverailroading:crafting_type.casting_hammer=铸造,能量锤 -immersiverailroading:crafting_type.plate_small=辊压板 -immersiverailroading:crafting_type.plate_medium=辊压板 -immersiverailroading:crafting_type.plate_large=辊压板 -immersiverailroading:crafting_type.plate_boiler=辊压板,蒸汽辊压 +multiblock.immersiverailroading:boiler_machine=锅炉卷板机 +multiblock.immersiverailroading:casting=铸造盆 +multiblock.immersiverailroading:plate_machine=板材辊压机 +multiblock.immersiverailroading:rail_machine=钢轨辊压机 +multiblock.immersiverailroading:steam_hammer=蒸汽锤 + +immersiverailroading:crafting_type.casting=需要在铸造盆中铸造 +immersiverailroading:crafting_type.casting_hammer=需要在铸造盆中铸造,并在蒸汽锤中冲压 +immersiverailroading:crafting_type.plate_small=需要小型板材 +immersiverailroading:crafting_type.plate_medium=需要中型板材 +immersiverailroading:crafting_type.plate_large=需要大型板材 +immersiverailroading:crafting_type.plate_boiler=需要锅炉板材 itemGroup.immersiverailroading.main=沉浸铁路 itemGroup.immersiverailroading.locomotive=沉浸铁路丨机车 @@ -182,86 +247,106 @@ itemGroup.immersiverailroading.stock=沉浸铁路丨货车 itemGroup.immersiverailroading.passenger=沉浸铁路丨客车 itemGroup.immersiverailroading.components=沉浸铁路丨组件 -death.attack.immersiverailroading:casting=%s 发现熔化的金属并不是一个适合游泳的地方 -death.attack.immersiverailroading:hitByTrain=%s 没能逃离火车的碾压 +death.attack.immersiverailroading:casting=%s 发现熔化的金属并不适合游泳 +death.attack.immersiverailroading:hitByTrain=%s 被火车创飞了 +death.attack.immersiverailroading:hitByTrainInDarkness=%s 没能察觉飞驰过来的火车头灯 + +immersiverailroading:detector_mode.simple=当前Augment模式:检测货物 +immersiverailroading:detector_mode.speed=当前Augment模式:检测速度 +immersiverailroading:detector_mode.passengers=当前Augment模式:检测乘客数 +immersiverailroading:detector_mode.cargo=当前Augment模式:检测货物的存储百分比 +immersiverailroading:detector_mode.liquid=当前Augment模式:检测流体的存储百分比 +immersiverailroading:detector_mode.computer=当前Augment模式:使用OC/CC的电脑 +immersiverailroading:loco_control_mode.throttle=当前Augment模式:控制节流阀 +immersiverailroading:loco_control_mode.reverser=当前Augment模式:控制换向器 +immersiverailroading:loco_control_mode.brake=当前Augment模式:控制制动 +immersiverailroading:loco_control_mode.horn=当前Augment模式:控制风笛 +immersiverailroading:loco_control_mode.computer=当前Augment模式:使用OC/CC的电脑 +immersiverailroading:loco_control_mode.bell=当前Augment模式:控制警铃 +immersiverailroading:coupler_augment_mode.engaged=当前Augment模式:连挂车厢 +immersiverailroading:coupler_augment_mode.disengaged=当前Augment模式:解挂车厢 +immersiverailroading:redstone_mode.enabled=当前Augment模式设置为常开 +immersiverailroading:redstone_mode.required=当前Augment模式设置为需要红石信号输入以工作 +immersiverailroading:redstone_mode.inverted=当前Augment模式设置为无红石信号输入以工作 +immersiverailroading:redstone_mode.disabled=当前Augment模式设置为停用 -immersiverailroading:detector_mode.simple=检测货物 -immersiverailroading:detector_mode.speed=检测速度 -immersiverailroading:detector_mode.passengers=检测乘客数 -immersiverailroading:detector_mode.cargo=检测货物的存储百分比 -immersiverailroading:detector_mode.liquid=检测流体的存储百分比 -immersiverailroading:detector_mode.computer=电脑 -immersiverailroading:loco_control_mode.throttle_forward=节流阀前推 -immersiverailroading:loco_control_mode.throttle_reverse=节流阀反转 -immersiverailroading:loco_control_mode.brake=制动 -immersiverailroading:loco_control_mode.horn=鸣笛 -immersiverailroading:loco_control_mode.computer=电脑 -immersiverailroading:coupler_augment_mode.engaged=连接 -immersiverailroading:coupler_augment_mode.disengaged=断连 +immersiverailroading:switch_state.none=无 +immersiverailroading:switch_state.straight=直向 +immersiverailroading:switch_state.turn=侧向 key.categories.immersiverailroading=沉浸铁路 ir_keys.increase_throttle=增大节流阀 -ir_keys.zero_throttle=关闭节流阀 -ir_keys.decrease_throttle=减少节流阀 -ir_keys.increase_brake=增加空气制动 -ir_keys.zero_brake=关闭空气制动 -ir_keys.decrease_brake=减少空气制动 -ir_keys.horn=鸣笛 +ir_keys.zero_throttle=节流阀归零 +ir_keys.decrease_throttle=减小节流阀 +ir_keys.increase_reverser=增大换向器 +ir_keys.zero_reverser=换向器归零 +ir_keys.decrease_reverser=减小换向器 +ir_keys.increase_brake=增大列车制动阀 +ir_keys.zero_brake=列车制动阀归零 +ir_keys.decrease_brake=减小列车制动阀 +ir_keys.increase_independent_brake=增大单独制动阀 +ir_keys.zero_independent_brake=单独制动阀归零 +ir_keys.decrease_independent_brake=减小单独制动阀 +ir_keys.horn=鸣笛(汽笛/风笛) +ir_keys.bell=鸣警铃 ir_keys.dead_mans_switch=失能开关 -ir_keys.start_stop_engine=启动/停止引擎 -ir_keys.config=Config +ir_keys.start_stop_engine=启动/停止发动机 +ir_keys.config=配置菜单 + +# Default pack's train name. Translation is optional. +immersiverailroading:entity.locomotives.a1_peppercorn=A1 Peppercorn +immersiverailroading:entity.locomotives.a5_switcher=A5 Switcher +immersiverailroading:entity.locomotives.alco_rs1=RS-1 +immersiverailroading:entity.locomotives.big_boy=Big Boy (4000 class) +immersiverailroading:entity.locomotives.br01=br01 +immersiverailroading:entity.locomotives.class_38=Class 38 +immersiverailroading:entity.locomotives.cooke_mogul=DSP&P Mogul +immersiverailroading:entity.locomotives.e6_atlantic=E6 Atlantic +immersiverailroading:entity.locomotives.emd_sd40-2=EMD SD40-2 +immersiverailroading:entity.locomotives.emd_sw1500=SW1500 +immersiverailroading:entity.locomotives.firefly=Firefly +immersiverailroading:entity.locomotives.ge_40_ton_boxcab=Class B-B-70/70-4HM829 Boxcab +immersiverailroading:entity.locomotives.ge_b40_8=GE B40-8 +immersiverailroading:entity.locomotives.ge_b40_8w=GE B40-8w +immersiverailroading:entity.locomotives.ge_c44_9cw=GE C44-9CW +immersiverailroading:entity.locomotives.iron_duke=Iron Duke +immersiverailroading:entity.locomotives.k36=D&RGW K36 +immersiverailroading:entity.locomotives.k4_pacific=K4 Pacific +immersiverailroading:entity.locomotives.rodgers_460=Rodgers Ten Wheeler +immersiverailroading:entity.locomotives.skookum=Skookum 2-4-4-2 +immersiverailroading:entity.tender.a1_peppercorn_tender=A1 Peppercorn Tender +immersiverailroading:entity.tender.a5_tender=A5 Slope Tender +immersiverailroading:entity.tender.big_boy_tender=Big Boy (4000 class) Tender +immersiverailroading:entity.tender.br01_tender=drg class 01 tender +immersiverailroading:entity.tender.class_38_tender=Class 38 Tender +immersiverailroading:entity.tender.cooke_tender=Cooke Tender +immersiverailroading:entity.tender.e6_tender=E6 Atlantic Tender +immersiverailroading:entity.tender.k4_tender=K4 Pacific Tender +immersiverailroading:entity.tender.k36_tender=K36 Tender +immersiverailroading:entity.tender.rodgers_460_tender=Rodgers Ten Wheeler Tender +immersiverailroading:entity.tender.skookum_tender=Skookum Tender + +immersiverailroading:entity.hand_car.hand_car_1=Hand Car + +immersiverailroading:entity.passenger.b70baggage=PRR B70 Baggage +immersiverailroading:entity.passenger.br_coach_mk1=BR Coach MK1 +immersiverailroading:entity.passenger.p70coach1=PRR P70 Coach 1 + +immersiverailroading:entity.freight.70t_hopper_slsf=70T Hopper SLSF +immersiverailroading:entity.freight.attx_flatcar_1=ATTX Flatcar 1 +immersiverailroading:entity.freight.boxcar_x26=Box Car X26 +immersiverailroading:entity.freight.drgw_1000class_gondola=1000 Series Gondola +immersiverailroading:entity.freight.drgw_3000class_boxcar=3000 Series Boxcar +immersiverailroading:entity.freight.drgw_5500class_stockcar=5500 Series Stockcar +immersiverailroading:entity.freight.drgw_rail_and_tie_outfit=Rail & Tie Car +immersiverailroading:entity.freight.dw_gondola=DW Gondola +immersiverailroading:entity.freight.n5c_cabin_car=N5c Caboose +immersiverailroading:entity.freight.prr_flatcar_1=PRR Flatcar 1 +immersiverailroading:entity.freight.russell_snow_plow=Russell Snow Plow +immersiverailroading:entity.freight.usra_boxcar_classrr40=USRA Boxcar Class RR-40 +immersiverailroading:entity.freight.usra_hopper_55t=USRA Hopper 55T +immersiverailroading:entity.freight.waycar=守车 -# 机车命名 -# 这一块属于额外添加的内容,原英文文件中不存在 -# immersiverailroading:entity.locomotives.a1_peppercorn= -# immersiverailroading:entity.locomotives.big_boy= -# immersiverailroading:entity.locomotives.k4_pacific= -# immersiverailroading:entity.locomotives.e6_atlantic= -# immersiverailroading:entity.locomotives.a5_switcher= -# immersiverailroading:entity.locomotives.class_38= -# immersiverailroading:entity.locomotives.rodgers_460= -# immersiverailroading:entity.locomotives.skookum= -# immersiverailroading:entity.locomotives.br01= -# immersiverailroading:entity.locomotives.cooke_mogul= -# immersiverailroading:entity.locomotives.k36= -# immersiverailroading:entity.locomotives.firefly= -# immersiverailroading:entity.locomotives.iron_duke= -# immersiverailroading:entity.locomotives.ge_b40_8= -# immersiverailroading:entity.locomotives.ge_b40_8w= -# immersiverailroading:entity.locomotives.ge_c44_9cw= -# immersiverailroading:entity.locomotives.ge_40_ton_boxcab= -# immersiverailroading:entity.locomotives.alco_rs1= -# immersiverailroading:entity.locomotives.emd_sw1500= -# immersiverailroading:entity.locomotives.emd_sd40-2= -# immersiverailroading:entity.tender.a1_peppercorn_tender= -# immersiverailroading:entity.tender.big_boy_tender= -# immersiverailroading:entity.tender.k4_tender= -# immersiverailroading:entity.tender.e6_tender= -# immersiverailroading:entity.tender.a5_tender= -# immersiverailroading:entity.tender.class_38_tender= -# immersiverailroading:entity.tender.rodgers_460_tender= -# immersiverailroading:entity.tender.skookum_tender= -# immersiverailroading:entity.tender.br01_tender= -# immersiverailroading:entity.tender.cooke_tender= -# immersiverailroading:entity.tender.k36_tender= -# immersiverailroading:entity.hand_car.hand_car_1= -# immersiverailroading:entity.passenger.br_coach_mk1= -# immersiverailroading:entity.passenger.b70baggage= -# immersiverailroading:entity.passenger.p70coach1= -# immersiverailroading:entity.freight.boxcar_x26= -# immersiverailroading:entity.freight.usra_boxcar_classrr40= -# immersiverailroading:entity.freight.70t_hopper_slsf= -# immersiverailroading:entity.freight.attx_flatcar_1= -# immersiverailroading:entity.freight.dw_gondola= -# immersiverailroading:entity.freight.prr_flatcar_1= -# immersiverailroading:entity.freight.usra_hopper_55t= -# immersiverailroading:entity.freight.n5c_cabin_car= -# immersiverailroading:entity.freight.russell_snow_plow= -# immersiverailroading:entity.freight.drgw_3000class_boxcar= -# immersiverailroading:entity.freight.drgw_1000class_gondola= -# immersiverailroading:entity.freight.drgw_5500class_stockcar= -# immersiverailroading:entity.freight.drgw_rail_and_tie_outfit= -# immersiverailroading:entity.freight.waycar= -# immersiverailroading:entity.tank.tank_us2= -# immersiverailroading:entity.tank.kamx_t= -# immersiverailroading:entity.tank.slag_car_1= +immersiverailroading:entity.tank.kamx_t=Kamx T +immersiverailroading:entity.tank.slag_car_1=Slag Car 1 +immersiverailroading:entity.tank.tank_us2=Tank US 2 diff --git a/src/main/resources/assets/immersiverailroading/models/rolling_stock/locomotives/firefly/firefly.obj b/src/main/resources/assets/immersiverailroading/models/rolling_stock/locomotives/firefly/firefly.obj index f4c3dbdf5..0c9f76a00 100644 --- a/src/main/resources/assets/immersiverailroading/models/rolling_stock/locomotives/firefly/firefly.obj +++ b/src/main/resources/assets/immersiverailroading/models/rolling_stock/locomotives/firefly/firefly.obj @@ -90064,7 +90064,7 @@ vn 0.0000 -1.0000 0.0000 vn 0.0000 1.0000 0.0000 vn -1.0000 0.0000 0.0000 vn 1.0000 0.0000 0.0000 -usemtl (null) +usemtl None s off f 24841//20290 24842//20290 24843//20290 f 24842//20290 24841//20290 24844//20290 @@ -90478,7 +90478,7 @@ vn 0.1379 -0.9904 0.0000 vn -0.1379 0.9904 0.0000 vn 0.0319 -0.9995 0.0000 vn -0.0319 0.9995 0.0000 -usemtl (null) +usemtl None s off f 24985//20296 24986//20296 24987//20296 f 24986//20296 24985//20296 24988//20296 @@ -90872,7 +90872,7 @@ vn 1.0000 0.0000 0.0000 vn 0.0000 1.0000 0.0000 vn 0.0000 -1.0000 0.0000 vn -1.0000 0.0000 0.0000 -usemtl (null) +usemtl None s off f 25257//20347 25258//20347 25259//20347 f 25258//20347 25257//20347 25260//20347 @@ -91089,7 +91089,7 @@ vn 1.0000 0.0000 0.0000 vn 0.0000 0.0000 -1.0000 vn 0.0000 -1.0000 0.0000 vn 0.0000 1.0000 0.0000 -usemtl (null) +usemtl None s off f 25401//20353 25402//20353 25403//20353 f 25402//20353 25401//20353 25404//20353 @@ -91262,7 +91262,7 @@ vn -0.9993 0.0370 0.0000 vn 0.9993 -0.0370 0.0000 vn -0.9429 0.3330 0.0000 vn 0.9429 -0.3330 0.0000 -usemtl (null) +usemtl None s off f 25533//20359 25534//20359 25535//20359 f 25534//20359 25533//20359 25536//20359 @@ -91448,7 +91448,7 @@ vn -1.0000 0.0000 0.0000 vn 0.0000 1.0000 0.0000 vn 1.0000 0.0000 0.0000 vn 0.0000 0.0000 -1.0000 -usemtl (null) +usemtl None s off f 25585//20393 25586//20393 25587//20393 f 25586//20393 25585//20393 25588//20393 @@ -91601,7 +91601,7 @@ vn 1.0000 0.0000 0.0000 vn 0.0000 1.0000 0.0000 vn -1.0000 0.0000 0.0000 vn 0.0000 0.0000 -1.0000 -usemtl (null) +usemtl None s off f 25705//20399 25706//20399 25707//20399 f 25706//20399 25705//20399 25708//20399 @@ -91762,7 +91762,7 @@ vn 0.8775 0.4795 0.0000 vn 0.9689 0.2474 0.0000 vn -0.9689 0.2474 0.0000 vn -0.8775 0.4795 0.0000 -usemtl (null) +usemtl None s off f 25777//20405 25778//20405 25779//20405 f 25778//20405 25777//20405 25780//20405 @@ -166600,7 +166600,7 @@ vn 0.0000 -1.0000 0.0000 vn 0.0000 1.0000 0.0000 vn 1.0000 0.0000 0.0000 vn -1.0000 0.0000 0.0000 -usemtl (null) +usemtl None s off f 45569//38524 45570//38524 45571//38524 f 45570//38524 45569//38524 45572//38524 @@ -167016,7 +167016,7 @@ vn -0.1379 -0.9904 0.0000 vn 0.1379 0.9904 0.0000 vn -0.0320 -0.9995 0.0000 vn 0.0320 0.9995 0.0000 -usemtl (null) +usemtl None s off f 45713//38530 45714//38530 45715//38530 f 45714//38530 45713//38530 45716//38530 @@ -167410,7 +167410,7 @@ vn 0.0000 0.0000 -1.0000 vn 0.0000 1.0000 0.0000 vn 0.0000 -1.0000 0.0000 vn 1.0000 0.0000 0.0000 -usemtl (null) +usemtl None s off f 45985//38583 45986//38583 45987//38583 f 45986//38583 45985//38583 45988//38583 @@ -167631,7 +167631,7 @@ vn 1.0000 0.0000 0.0000 vn -1.0000 0.0000 0.0000 vn 0.9982 0.0000 -0.0604 vn -0.9862 0.0000 0.1657 -usemtl (null) +usemtl None s off f 46129//38589 46130//38589 46131//38589 f 46130//38589 46129//38589 46132//38589 @@ -167802,7 +167802,7 @@ vn 0.9993 0.0370 0.0000 vn -0.9993 -0.0370 0.0000 vn 0.9429 0.3330 0.0000 vn -0.9429 -0.3330 0.0000 -usemtl (null) +usemtl None s off f 46261//38599 46262//38599 46263//38599 f 46262//38599 46261//38599 46264//38599 @@ -167988,7 +167988,7 @@ vn -1.0000 0.0000 0.0000 vn 0.0000 -1.0000 0.0000 vn 1.0000 0.0000 0.0000 vn 0.0000 1.0000 0.0000 -usemtl (null) +usemtl None s off f 46313//38631 46314//38631 46315//38631 f 46314//38631 46313//38631 46316//38631 @@ -168141,7 +168141,7 @@ vn -1.0000 0.0000 0.0000 vn 0.0000 1.0000 0.0000 vn 1.0000 0.0000 0.0000 vn 0.0000 0.0000 1.0000 -usemtl (null) +usemtl None s off f 46433//38637 46434//38637 46435//38637 f 46434//38637 46433//38637 46436//38637 @@ -168302,7 +168302,7 @@ vn -0.8775 0.4795 0.0000 vn -0.9689 0.2474 0.0000 vn 0.9689 0.2475 0.0000 vn 0.8775 0.4795 0.0000 -usemtl (null) +usemtl None s off f 46505//38643 46506//38643 46507//38643 f 46506//38643 46505//38643 46508//38643 diff --git a/src/main/resources/assets/immersiverailroading/models/rolling_stock/locomotives/iron_duke/iron_duke.obj b/src/main/resources/assets/immersiverailroading/models/rolling_stock/locomotives/iron_duke/iron_duke.obj index 763423250..f04712d1b 100644 --- a/src/main/resources/assets/immersiverailroading/models/rolling_stock/locomotives/iron_duke/iron_duke.obj +++ b/src/main/resources/assets/immersiverailroading/models/rolling_stock/locomotives/iron_duke/iron_duke.obj @@ -88888,7 +88888,7 @@ vn -0.0872 -0.9962 0.0000 vn -0.9962 0.0872 0.0000 vn -0.9962 0.0871 0.0000 vn 0.0000 0.0000 -1.0000 -usemtl (null) +usemtl None s off f 25039//19600 25045//19600 25040//19600 f 25045//19600 25039//19600 25044//19600 @@ -89122,7 +89122,7 @@ vn -0.4248 -0.5895 0.6870 vn -0.4248 -0.5895 -0.6870 vn -0.3018 -0.6641 0.6840 vn -0.3018 -0.6641 -0.6840 -usemtl (null) +usemtl None s off f 25059//19608 25117//19608 25118//19608 f 25117//19608 25059//19608 25095//19608 @@ -89513,7 +89513,7 @@ vn -0.3010 -0.6629 0.6855 vn -0.3010 -0.6629 -0.6855 vn -0.1748 -0.7036 0.6887 vn -0.1748 -0.7036 -0.6887 -usemtl (null) +usemtl None s off f 25229//19687 25167//19687 25168//19687 f 25167//19688 25229//19688 25169//19688 @@ -89758,7 +89758,7 @@ vn -0.7016 0.7126 0.0000 vn -0.9962 0.0872 0.0000 vn 0.7034 -0.7108 0.0000 vn -0.0000 0.0000 -1.0000 -usemtl (null) +usemtl None s off f 25315//19760 25313//19760 25299//19760 f 25313//19760 25315//19760 25312//19760 @@ -89968,7 +89968,7 @@ vn 0.0396 -0.7130 0.7000 vn 0.0396 -0.7130 -0.7000 vn 0.6254 -0.5248 -0.5773 vn 0.6254 -0.5248 0.5773 -usemtl (null) +usemtl None s off f 25371//19769 25368//19769 25335//19769 f 25368//19769 25371//19769 25336//19769 @@ -90281,7 +90281,7 @@ vn 0.7222 -0.0323 -0.6909 vn 0.7222 -0.0323 0.6909 vn 0.7124 0.0413 -0.7006 vn 0.7124 0.0413 0.7006 -usemtl (null) +usemtl None s off f 25487//19816 25419//19816 25485//19816 f 25419//19817 25487//19817 25420//19817 @@ -90528,7 +90528,7 @@ vn 0.7930 -0.6092 0.0000 vn 0.7931 -0.6092 0.0000 vn 0.0000 0.0000 -1.0000 vn -0.0001 0.0000 -1.0000 -usemtl (null) +usemtl None s off f 25517//19903 25550//19903 25518//19903 f 25550//19903 25517//19903 25522//19903 @@ -90684,7 +90684,7 @@ vn -0.9962 -0.0872 0.0000 vn 0.9962 0.0871 0.0000 vn -0.0000 0.0000 -1.0000 vn -0.8000 0.0000 0.6000 -usemtl (null) +usemtl None s off f 25572//19916 25599//19916 25571//19916 f 25599//19916 25572//19916 25569//19916 @@ -90827,7 +90827,7 @@ vn -0.9785 -0.2061 0.0000 vn -0.7999 0.6001 0.0000 vn -0.9962 0.0873 0.0000 vn -0.9274 0.3741 0.0000 -usemtl (null) +usemtl None s off f 25612//19925 25614//19925 25610//19925 f 25610//19925 25613//19925 25612//19925 @@ -90963,7 +90963,7 @@ vn 0.5712 0.8208 0.0000 vn -0.1547 0.9879 0.0000 vn 0.3266 0.9452 0.0000 vn 0.0879 0.9961 0.0000 -usemtl (null) +usemtl None s 1 f 25642//19943 25640//19943 25639//19944 f 25639//19944 25641//19944 25642//19943 @@ -91088,7 +91088,7 @@ vn -0.9826 -0.1858 0.0000 vn -0.9899 0.1416 0.0000 vn -0.9962 -0.0871 0.0000 vn -0.9999 0.0125 0.0000 -usemtl (null) +usemtl None s off f 25711//19981 25706//19981 25705//19981 f 25705//19981 25707//19981 25711//19981 @@ -166767,7 +166767,7 @@ vn -0.0872 0.9962 0.0000 vn 0.0872 -0.9962 0.0000 vn 0.9962 0.0872 0.0000 vn -0.0000 0.0000 -1.0000 -usemtl (null) +usemtl None s off f 46240//37814 46223//37814 46229//37814 f 46226//37814 46227//37814 46223//37814 @@ -166996,7 +166996,7 @@ vn 0.4248 -0.5895 -0.6870 vn 0.4248 -0.5895 0.6870 vn 0.3017 -0.6641 -0.6840 vn 0.3017 -0.6641 0.6840 -usemtl (null) +usemtl None s off f 46291//37820 46292//37820 46294//37820 f 46268//37821 46247//37821 46289//37821 @@ -167389,7 +167389,7 @@ vn 0.3010 -0.6629 -0.6855 vn 0.3010 -0.6629 0.6855 vn 0.1748 -0.7036 -0.6887 vn 0.1748 -0.7036 0.6887 -usemtl (null) +usemtl None s off f 46404//37894 46355//37894 46396//37894 f 46355//37894 46356//37894 46396//37894 @@ -167635,7 +167635,7 @@ vn 0.9962 0.0872 0.0000 vn -0.7034 -0.7108 0.0000 vn 0.9962 0.0871 0.0000 vn 0.0000 0.0000 -1.0000 -usemtl (null) +usemtl None s off f 46488//37969 46483//37969 46516//37969 f 46512//37969 46484//37969 46483//37969 @@ -167847,7 +167847,7 @@ vn -0.0396 -0.7130 -0.7000 vn -0.0396 -0.7130 0.7000 vn -0.6254 -0.5248 -0.5773 vn -0.6254 -0.5248 0.5773 -usemtl (null) +usemtl None s off f 46567//37979 46523//37979 46569//37979 f 46569//37979 46523//37979 46570//37979 @@ -168161,7 +168161,7 @@ vn -0.7223 -0.0323 0.6908 vn -0.7221 -0.0323 -0.6910 vn -0.7124 0.0413 0.7006 vn -0.7124 0.0413 -0.7006 -usemtl (null) +usemtl None s off f 46607//38028 46608//38028 46656//38028 f 46608//38029 46649//38029 46656//38029 @@ -168409,7 +168409,7 @@ vn -0.7930 -0.6092 0.0000 vn -0.7931 -0.6091 0.0000 vn 0.0000 0.0000 -1.0000 vn 0.0001 0.0000 -1.0000 -usemtl (null) +usemtl None s off f 46730//38116 46728//38116 46731//38116 f 46731//38116 46728//38116 46699//38116 @@ -168567,7 +168567,7 @@ vn 0.9962 -0.0872 0.0000 vn 0.9962 -0.0871 0.0000 vn 0.0000 0.0000 -1.0000 vn 0.0000 0.1551 0.9879 -usemtl (null) +usemtl None s off f 46749//38130 46757//38130 46775//38130 f 46757//38130 46773//38130 46775//38130 @@ -168710,7 +168710,7 @@ vn 0.9785 -0.2061 0.0000 vn 0.7999 0.6001 0.0000 vn 0.9962 0.0873 0.0000 vn 0.9274 0.3741 0.0000 -usemtl (null) +usemtl None s off f 46801//38141 46800//38141 46806//38141 f 46798//38141 46806//38141 46800//38141 @@ -168840,7 +168840,7 @@ vn -0.5712 0.8207 0.0000 vn 0.1547 0.9879 0.0000 vn -0.3266 0.9452 0.0000 vn -0.0879 0.9961 0.0000 -usemtl (null) +usemtl None s 1 f 46827//38159 46829//38159 46828//38160 f 46828//38160 46829//38159 46830//38160 @@ -168966,7 +168966,7 @@ vn 0.9826 -0.1858 0.0000 vn 0.9899 0.1416 0.0000 vn 0.9962 -0.0871 0.0000 vn 0.9999 0.0125 0.0000 -usemtl (null) +usemtl None s off f 46895//38191 46893//38191 46900//38191 f 46894//38191 46900//38191 46893//38191 diff --git a/src/main/resources/assets/immersiverailroading/rolling_stock/default/base.caml b/src/main/resources/assets/immersiverailroading/rolling_stock/default/base.caml index a53631ada..95916ccf6 100644 --- a/src/main/resources/assets/immersiverailroading/rolling_stock/default/base.caml +++ b/src/main/resources/assets/immersiverailroading/rolling_stock/default/base.caml @@ -44,10 +44,11 @@ properties = # Required: valve_gear = null # Optional: Type of generic valve gear or Animatrix definition # valve_gear = WALSCHAERTS # Generic Example # valve_gear = # Animatrix Example -# # More steps are recommended, but this should work -# -1.0 = immersiverailroading:some/path/animation_-1.0.anim # Reverse -# 0.0 = immersiverailroading:some/path/animation_0.0.anim # Neutral -# 1.0 = immersiverailroading:some/path/animation_1.0.anim # Forward +# animatrix = +# # More steps are recommended, but this should work +# -1.0 = immersiverailroading:some/path/animation_-1.0.anim # Reverse +# 0.0 = immersiverailroading:some/path/animation_0.0.anim # Neutral +# 1.0 = immersiverailroading:some/path/animation_1.0.anim # Forward independent_brake = False # Optional: Does this piece of stock have an independent brake? Usually False except for Locomotives pressure_brake = True # Optional: Does this piece of stock have a pressure brake? Usually True except for Hand Cars @@ -60,6 +61,8 @@ properties = # Required: swayMultiplier = 1 # Optional: How much the stock should sway when going over bumpy tracks / joints tiltMultiplier = 0 # Optional: How much the stock should tilt into curves + snow_layers = 1 # Optional: How many snow layers are left after clearing snow + interior_light_level = 0.4 # Optional: How bright the interior should be by default # Exterior Light Properties @@ -68,6 +71,7 @@ properties = # Required: # blinkIntervalSeconds = 0 # Optional: How often this should blink # blinkOffsetSeconds = 0 # Optional: How much to offset the start of blinking from other lights # blinkFullBright = True # Optional: Should this add the emissive modifier when enabled? +# revertDirection = False # Optional: Should this light face the opposite direction? Like a front-facing light at stock's tail # reverseColor = null # Optional: How to tint the light when the stock is in reverse, red example: 0xFF2222 # castsLight = True # Optional: If optifine is installed, should we try to fake real lighting? Too many of these can cause performance issues! # lightTex = "immersiverailroading:textures/light.png" # Optional: light flare texture @@ -162,4 +166,4 @@ particles = # Optional: Configure general particle emitter settings # R = # X = 1 # Y = 1 -# Z = 1 \ No newline at end of file +# Z = 1 diff --git a/src/main/resources/assets/immersiverailroading/rolling_stock/default/diesel.caml b/src/main/resources/assets/immersiverailroading/rolling_stock/default/diesel.caml index 8ac02d050..9051d3848 100644 --- a/src/main/resources/assets/immersiverailroading/rolling_stock/default/diesel.caml +++ b/src/main/resources/assets/immersiverailroading/rolling_stock/default/diesel.caml @@ -9,6 +9,10 @@ properties = throttle_notches = 8 # Optional: Number of throttle notches in the cab dynamic_traction_control = false # If the onboard computer can try to prevent wheel slip horn_sustained = False # Optional: Should the horn repeat + # fuel_override: "water:1000" # Optional: add fluid filter for this locomotive, and if you want you can also override burntime here + # fuel_override: "ethanol:1700" + # fuel_override: "gasoline" # "gasoline" will use 100 defined in config as burntime + # fuel_override: "lava" # "lava" will be skipped in default environment because it neither exist in default config nor have burntime specified here sounds = idle = "immersiverailroading:sounds/diesel/default/idle.ogg" # Optional: See sound_definition.caml for details diff --git a/src/main/resources/assets/immersiverailroading/rolling_stock/default/locomotive.caml b/src/main/resources/assets/immersiverailroading/rolling_stock/default/locomotive.caml index eb23e8af8..58fa84d86 100644 --- a/src/main/resources/assets/immersiverailroading/rolling_stock/default/locomotive.caml +++ b/src/main/resources/assets/immersiverailroading/rolling_stock/default/locomotive.caml @@ -3,19 +3,29 @@ import: "immersiverailroading:rolling_stock/default/base.caml" works = null # Optional: Displayed as part of the item tooltip properties = - hasRadioEquipment = False # Optional: Most locomotives don't support remote control + hasRadioEquipment = False # Optional: Most locomotives don't support remote control + + isLinkedBrakeThrottle = False # Optional: Should the throttle / brake controls be connected? + toggle_bell = True # Optional: Should the bell be toggled on/off or should it require you to hold a button to activate? + cog = False # Optional: provides near infinite traction when on cog-enabled track + + # Overrides + independent_brake = True # Optional: Does this piece of stock have an independent brake? Defaults to False except for Locomotives + linear_brake_control = False # Optional: Make brakes move in a linear fashion, TODO FIX/REMOVE THIS + + cab_car = False # Optional: Cab Cars don't have any motive power, but can be MU'd - cab_car = False # Optional: Cab Cars don't have any motive power, but can be MU'd # The following are ignored if cab_car = True - horsepower = null # Required - tractive_effort_lbf = null # Required - max_speed_kmh = null # Required - multi_unit_capable = False # Optional: Defaults to true for Diesel Electrics + power_kw = null # Required: Any power definition + power_w = null + power_ps = null # Metric horsepower + power_hp = null # Imperial horsepower + horsepower = null # Old format for power - isLinkedBrakeThrottle = False # Optional: Should the throttle / brake controls be connected? - toggle_bell = True # Optional: Should the bell be toggled on/off or should it require you to hold a button to activate? - cog = False # Optional: provides near infinite traction when on cog-enabled track + tractive_effort_kn = null # Required: any tractive effort definition + tractive_effort_n = null + tractive_effort_lbf = null - # Overrides - independent_brake = True # Optional: Does this piece of stock have an independent brake? Usually False except for Locomotives - linear_brake_control = False # Optional: Make brakes move in a linear fashion, TODO FIX/REMOVE THIS + max_speed_kmh = null # Required + + multi_unit_capable = False # Optional: Defaults to true for diesels diff --git a/src/main/resources/assets/immersiverailroading/rolling_stock/default/steam.caml b/src/main/resources/assets/immersiverailroading/rolling_stock/default/steam.caml index 5f211c934..cb521267f 100644 --- a/src/main/resources/assets/immersiverailroading/rolling_stock/default/steam.caml +++ b/src/main/resources/assets/immersiverailroading/rolling_stock/default/steam.caml @@ -3,10 +3,15 @@ import: "immersiverailroading:rolling_stock/default/locomotive.caml" properties = # The following is ignored if cab_car is set to True water_capacity_l = null # Required: Boiler fluid capacity in liters - max_psi = null # Required: Maximum boiler pressure in PSI + + max_pressure_bar = null # Required: Any max pressure definition + max_pressure_kpa = null + max_pressure_psi = null + max_psi = null # Old format for max pressure + firebox = # Firebox Properties - slots = null # Required: Number of slots in this container - width = null # Required: Width of the container, recommended to be a numeric factor of the width ex: 32 and 8 + slots = null # Required: Number of slots in this container + width = null # Required: Width of the container, recommended to be a numeric factor of the width ex: 32 and 8 tender_auto_feed = True # Optional: Should this locomotive auto pull fuel from tenders? cab_forward = False # Optional: Flip the locomotion direction to more accurately simulate a cab forward type locomotive