diff --git a/build.gradle b/build.gradle index bce39f7..01be3bc 100644 --- a/build.gradle +++ b/build.gradle @@ -16,8 +16,8 @@ rootProject.ext.fabric_loader_version = new JsonSlurper().parse(("https://meta.f rootProject.ext.forge_version = minecraft_version + "-" + new JsonSlurper().parse(("https://files.minecraftforge.net/net/minecraftforge/forge/promotions_slim.json").toURL())["promos"][minecraft_version + "-latest"] rootProject.ext.fabric_api_version = getModrinthVersion("fabric", minecraft_version, "fabric-api") rootProject.ext.mod_menu_version = getModrinthVersion("fabric", minecraft_version, "modmenu") -rootProject.ext.cloth_config_fabric_version = getModrinthVersion("fabric", minecraft_version, "cloth-config") -rootProject.ext.cloth_config_forge_version = getModrinthVersion("forge", minecraft_version, "cloth-config") +rootProject.ext.cloth_config_fabric_version = getModrinthVersion("fabric", minecraft_version, "cloth-config").replace("+fabric", "") +rootProject.ext.cloth_config_forge_version = getModrinthVersion("forge", minecraft_version, "cloth-config").replace("+forge", "") rootProject.ext.filters_api_version = getModrinthVersion("fabric", minecraft_version, "filters-api") rootProject.ext.architectury_version = getModrinthVersion("forge", minecraft_version, "architectury-api").split("\\+")[0] rootProject.ext.architectury_id = minecraft_main_version == 16 ? "me.shedaniel" : "dev.architectury" diff --git a/common/src/main/java/ziyue/tjmetro/BlockEntityTypes.java b/common/src/main/java/ziyue/tjmetro/BlockEntityTypes.java index d60a87d..91ac32c 100644 --- a/common/src/main/java/ziyue/tjmetro/BlockEntityTypes.java +++ b/common/src/main/java/ziyue/tjmetro/BlockEntityTypes.java @@ -69,4 +69,5 @@ public interface BlockEntityTypes RegistryObject> STATION_NAME_ENTRANCE_TIANJIN_PINYIN_TILE_ENTITY = new RegistryObject<>(() -> RegistryUtilities.getBlockEntityType((pos, state) -> new BlockStationNameEntranceTianjin.TileEntityStationNameEntranceTianjin(true, false, pos, state), BlockList.STATION_NAME_ENTRANCE_TIANJIN_PINYIN.get())); RegistryObject> STATION_NAME_ENTRANCE_TIANJIN_BMT_TILE_ENTITY = new RegistryObject<>(() -> RegistryUtilities.getBlockEntityType((pos, state) -> new BlockStationNameEntranceTianjin.TileEntityStationNameEntranceTianjin(false, true, pos, state), BlockList.STATION_NAME_ENTRANCE_TIANJIN_BMT.get())); RegistryObject> STATION_NAME_ENTRANCE_TIANJIN_BMT_PINYIN_TILE_ENTITY = new RegistryObject<>(() -> RegistryUtilities.getBlockEntityType((pos, state) -> new BlockStationNameEntranceTianjin.TileEntityStationNameEntranceTianjin(true, true, pos, state), BlockList.STATION_NAME_ENTRANCE_TIANJIN_BMT_PINYIN.get())); + RegistryObject> STATION_NAME_PLATE_TILE_ENTITY = new RegistryObject<>(() -> RegistryUtilities.getBlockEntityType(BlockStationNamePlate.TileEntityStationNamePlate::new, BlockList.STATION_NAME_PLATE.get())); } \ No newline at end of file diff --git a/common/src/main/java/ziyue/tjmetro/BlockList.java b/common/src/main/java/ziyue/tjmetro/BlockList.java index 2402d10..b7b4cc2 100644 --- a/common/src/main/java/ziyue/tjmetro/BlockList.java +++ b/common/src/main/java/ziyue/tjmetro/BlockList.java @@ -104,4 +104,5 @@ public interface BlockList RegistryObject STATION_NAME_ENTRANCE_TIANJIN_PINYIN = new RegistryObject<>(() -> new BlockStationNameEntranceTianjin(true, false)); RegistryObject STATION_NAME_ENTRANCE_TIANJIN_BMT = new RegistryObject<>(() -> new BlockStationNameEntranceTianjin(false, true)); RegistryObject STATION_NAME_ENTRANCE_TIANJIN_BMT_PINYIN = new RegistryObject<>(() -> new BlockStationNameEntranceTianjin(true, true)); + RegistryObject STATION_NAME_PLATE = new RegistryObject<>(BlockStationNamePlate::new); } diff --git a/common/src/main/java/ziyue/tjmetro/TianjinMetro.java b/common/src/main/java/ziyue/tjmetro/TianjinMetro.java index b8feab8..a8e8a48 100644 --- a/common/src/main/java/ziyue/tjmetro/TianjinMetro.java +++ b/common/src/main/java/ziyue/tjmetro/TianjinMetro.java @@ -68,8 +68,8 @@ public static void init( registerBlockItem.accept("station_name_entrance_tianjin_pinyin", BlockList.STATION_NAME_ENTRANCE_TIANJIN_PINYIN, SIGNS); registerBlockItem.accept("station_name_entrance_tianjin_bmt", BlockList.STATION_NAME_ENTRANCE_TIANJIN_BMT, SIGNS); registerBlockItem.accept("station_name_entrance_tianjin_bmt_pinyin", BlockList.STATION_NAME_ENTRANCE_TIANJIN_BMT_PINYIN, SIGNS); + registerBlockItem.accept("station_name_plate", BlockList.STATION_NAME_PLATE, SIGNS); registerEnchantedBlockItem.accept("station_name_sign_1", BlockList.STATION_NAME_SIGN_1, SIGNS); -// registerBlockItem.accept("station_name_pole", BlockList.STATION_NAME_POLE, SIGNS); /* PLATFORM GATES */ registerItem.accept("psd_door_tianjin", ItemList.PSD_DOOR_TIANJIN, GATES); registerItem.accept("psd_glass_tianjin", ItemList.PSD_GLASS_TIANJIN, GATES); @@ -198,7 +198,7 @@ public static void init( registerBlockEntityType.accept("station_name_entrance_tianjin_pinyin", BlockEntityTypes.STATION_NAME_ENTRANCE_TIANJIN_PINYIN_TILE_ENTITY); registerBlockEntityType.accept("station_name_entrance_tianjin_bmt", BlockEntityTypes.STATION_NAME_ENTRANCE_TIANJIN_BMT_TILE_ENTITY); registerBlockEntityType.accept("station_name_entrance_tianjin_bmt_pinyin", BlockEntityTypes.STATION_NAME_ENTRANCE_TIANJIN_BMT_PINYIN_TILE_ENTITY); -// registerBlockEntityType.accept("station_name_pole", BlockEntityTypes.STATION_NAME_POLE_TILE_ENTITY); + registerBlockEntityType.accept("station_name_plate", BlockEntityTypes.STATION_NAME_PLATE_TILE_ENTITY); mtr.Registry.registerNetworkReceiver(PACKET_UPDATE_CUSTOM_CONTENT, PacketGuiServer::receiveCustomContentC2S); mtr.Registry.registerNetworkReceiver(PACKET_UPDATE_CUSTOM_COLOR, PacketGuiServer::receiveCustomColorC2S); diff --git a/common/src/main/java/ziyue/tjmetro/TianjinMetroClient.java b/common/src/main/java/ziyue/tjmetro/TianjinMetroClient.java index 672a42a..3c676f8 100644 --- a/common/src/main/java/ziyue/tjmetro/TianjinMetroClient.java +++ b/common/src/main/java/ziyue/tjmetro/TianjinMetroClient.java @@ -32,6 +32,7 @@ public static void init() { RegistryClient.registerBlockRenderType(RenderType.cutout(), BlockList.PSD_DOOR_TIANJIN.get()); RegistryClient.registerBlockRenderType(RenderType.cutout(), BlockList.PSD_GLASS_TIANJIN.get()); RegistryClient.registerBlockRenderType(RenderType.cutout(), BlockList.PSD_GLASS_END_TIANJIN.get()); + RegistryClient.registerBlockRenderType(RenderType.cutout(), BlockList.METAL_DETECTION_DOOR.get()); RegistryClient.registerBlockRenderType(RenderType.translucent(), BlockList.ROLLING.get()); RegistryClient.registerBlockColors(BlockList.STATION_COLOR_CEILING.get()); @@ -95,6 +96,7 @@ public static void init() { RegistryClient.registerTileEntityRenderer(BlockEntityTypes.STATION_NAME_ENTRANCE_TIANJIN_PINYIN_TILE_ENTITY.get(), RenderStationNameEntranceTianjin::new); RegistryClient.registerTileEntityRenderer(BlockEntityTypes.STATION_NAME_ENTRANCE_TIANJIN_BMT_TILE_ENTITY.get(), RenderStationNameEntranceTianjin::new); RegistryClient.registerTileEntityRenderer(BlockEntityTypes.STATION_NAME_ENTRANCE_TIANJIN_BMT_PINYIN_TILE_ENTITY.get(), RenderStationNameEntranceTianjin::new); + RegistryClient.registerTileEntityRenderer(BlockEntityTypes.STATION_NAME_PLATE_TILE_ENTITY.get(), RenderStationNamePlate::new); RegistryClient.registerNetworkReceiver(IPacket.PACKET_OPEN_CUSTOM_CONTENT_SCREEN, packet -> PacketGuiClient.openCustomContentScreenS2C(Minecraft.getInstance(), packet)); RegistryClient.registerNetworkReceiver(IPacket.PACKET_OPEN_CUSTOM_COLOR_SCREEN, packet -> PacketGuiClient.openCustomColorScreenS2C(Minecraft.getInstance(), packet)); diff --git a/common/src/main/java/ziyue/tjmetro/block/BlockStationNameEntranceTianjin.java b/common/src/main/java/ziyue/tjmetro/block/BlockStationNameEntranceTianjin.java index 208f2f3..e4a97f5 100644 --- a/common/src/main/java/ziyue/tjmetro/block/BlockStationNameEntranceTianjin.java +++ b/common/src/main/java/ziyue/tjmetro/block/BlockStationNameEntranceTianjin.java @@ -155,8 +155,7 @@ public void writeCompoundTag(CompoundTag compoundTag) { public void setData(Long selectedId) { Consumer setStyle = direction -> { BlockPos offsetPos = getBlockPos(); - while (level.getBlockState(offsetPos).getBlock() instanceof BlockStationNameEntranceTianjin) { - TileEntityStationNameEntranceTianjin entity = (TileEntityStationNameEntranceTianjin) level.getBlockEntity(offsetPos); + while (level.getBlockEntity(offsetPos) instanceof TileEntityStationNameEntranceTianjin entity) { entity.selectedId = selectedId; entity.setChanged(); entity.syncData(); diff --git a/common/src/main/java/ziyue/tjmetro/block/BlockStationNamePlate.java b/common/src/main/java/ziyue/tjmetro/block/BlockStationNamePlate.java new file mode 100644 index 0000000..4d6d595 --- /dev/null +++ b/common/src/main/java/ziyue/tjmetro/block/BlockStationNamePlate.java @@ -0,0 +1,143 @@ +package ziyue.tjmetro.block; + +import mtr.Blocks; +import mtr.block.IBlock; +import mtr.mappings.BlockEntityClientSerializableMapper; +import mtr.mappings.BlockEntityMapper; +import mtr.mappings.EntityBlockMapper; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.HorizontalDirectionalBlock; +import net.minecraft.world.level.block.SimpleWaterloggedBlock; +import net.minecraft.world.level.block.state.BlockBehaviour; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.properties.IntegerProperty; +import net.minecraft.world.level.material.FluidState; +import net.minecraft.world.level.material.Fluids; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.phys.shapes.VoxelShape; +import org.jetbrains.annotations.Nullable; +import ziyue.tjmetro.BlockEntityTypes; + +import java.util.function.Consumer; + +import static net.minecraft.world.level.block.state.properties.BlockStateProperties.WATERLOGGED; + +public class BlockStationNamePlate extends HorizontalDirectionalBlock implements SimpleWaterloggedBlock, EntityBlockMapper +{ + public static final IntegerProperty POS = IntegerProperty.create("pos", 0, 3); + + public BlockStationNamePlate() { + this(BlockBehaviour.Properties.copy(Blocks.STATION_NAME_TALL_WALL.get())); + } + + public BlockStationNamePlate(Properties properties) { + super(properties); + } + + @Nullable + @Override + public BlockState getStateForPlacement(BlockPlaceContext blockPlaceContext) { + BlockState blockState = defaultBlockState().setValue(FACING, blockPlaceContext.getHorizontalDirection()).setValue(WATERLOGGED, false); + if (IBlock.isReplaceable(blockPlaceContext, blockState.getValue(FACING).getClockWise(), 4)) { + for (int i = 1; i < 4; i++) { + blockPlaceContext.getLevel().setBlock(blockPlaceContext.getClickedPos().relative(blockState.getValue(FACING).getClockWise(), i), blockState.setValue(POS, i), 2); + } + return blockState.setValue(POS, 0); + } + return null; + } + + @Override + public void playerWillDestroy(Level level, BlockPos blockPos, BlockState blockState, Player player) { + for (int i = 1; i < blockState.getValue(POS) + 1; i++) { + IBlockExtends.breakBlock(level, blockPos.relative(blockState.getValue(FACING).getCounterClockWise(), i), this); + } + for (int i = 1; i < 4 - blockState.getValue(POS); i++) { + IBlockExtends.breakBlock(level, blockPos.relative(blockState.getValue(FACING).getClockWise(), i), this); + } + super.playerWillDestroy(level, blockPos, blockState, player); + } + + @Override + public VoxelShape getShape(BlockState blockState, BlockGetter blockGetter, BlockPos blockPos, CollisionContext collisionContext) { + final Direction facing = IBlock.getStatePropertySafe(blockState, FACING); + final int pos = IBlock.getStatePropertySafe(blockState, POS); + if ((pos % 3) != 0) { + return IBlock.getVoxelShapeByDirection(0, 0, 7, 16, 12, 9, facing); + } else { + final VoxelShape main = IBlock.getVoxelShapeByDirection(3.25, 0, 7, 16, 12, 9, (pos == 3) ? facing.getOpposite() : facing); + final VoxelShape pole = IBlock.getVoxelShapeByDirection(2, 0, 7, 3.25, 16, 9, (pos == 3) ? facing.getOpposite() : facing); + return Shapes.or(main, pole); + } + } + + @Override + public BlockEntityMapper createBlockEntity(BlockPos pos, BlockState state) { + return new TileEntityStationNamePlate(pos, state); + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder builder) { + builder.add(FACING, WATERLOGGED, POS); + } + + @Override + public FluidState getFluidState(BlockState blockState) { + return blockState.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(blockState); + } + + public static class TileEntityStationNamePlate extends BlockEntityClientSerializableMapper + { + public final float yOffset; + public final float zOffset; + protected Long selectedId; + protected static final String KEY_SELECTED_ID = "selected_id"; + + public TileEntityStationNamePlate(BlockPos pos, BlockState state) { + super(BlockEntityTypes.STATION_NAME_PLATE_TILE_ENTITY.get(), pos, state); + this.yOffset = 0.0F; + this.zOffset = 0.00625F; + this.selectedId = -1L; + } + + @Override + public void readCompoundTag(CompoundTag compoundTag) { + selectedId = compoundTag.getLong(KEY_SELECTED_ID); + } + + @Override + public void writeCompoundTag(CompoundTag compoundTag) { + compoundTag.putLong(KEY_SELECTED_ID, selectedId); + } + + public void setData(Long selectedId) { + Consumer setStyle = direction -> { + BlockPos offsetPos = getBlockPos(); + while (level.getBlockEntity(offsetPos) instanceof TileEntityStationNamePlate entity) { + entity.selectedId = selectedId; + entity.setChanged(); + entity.syncData(); + offsetPos = offsetPos.relative(direction); + } + }; + setStyle.accept(IBlock.getStatePropertySafe(getBlockState(), FACING).getClockWise()); + setStyle.accept(IBlock.getStatePropertySafe(getBlockState(), FACING).getCounterClockWise()); + this.selectedId = selectedId; + setChanged(); + syncData(); + } + + public Long getSelectedId() { + return selectedId; + } + } +} diff --git a/common/src/main/java/ziyue/tjmetro/render/RenderRailwaySignWall.java b/common/src/main/java/ziyue/tjmetro/render/RenderRailwaySignWall.java index 09105a1..f774587 100644 --- a/common/src/main/java/ziyue/tjmetro/render/RenderRailwaySignWall.java +++ b/common/src/main/java/ziyue/tjmetro/render/RenderRailwaySignWall.java @@ -84,7 +84,7 @@ public void render(T entity, float tickDelta, PoseStack matrices, MultiBufferSou UtilitiesClient.rotateZDegrees(matricesNew, 180); matricesNew.translate(block.getXStart() / 16F - 0.5, -0.25, 0.493); if (entity instanceof BlockRailwaySignWallBig.TileEntityRailwaySignWallBig) { - matricesNew.translate(0, -0.218, 0); + matricesNew.translate(0, -0.218, -0.003); matricesNew.scale(2, 2, 2); } }); diff --git a/common/src/main/java/ziyue/tjmetro/render/RenderStationNamePlate.java b/common/src/main/java/ziyue/tjmetro/render/RenderStationNamePlate.java new file mode 100644 index 0000000..e96e94f --- /dev/null +++ b/common/src/main/java/ziyue/tjmetro/render/RenderStationNamePlate.java @@ -0,0 +1,75 @@ +package ziyue.tjmetro.render; + +import com.mojang.blaze3d.vertex.PoseStack; +import mtr.block.BlockStationNameBase; +import mtr.block.IBlock; +import mtr.client.ClientData; +import mtr.client.IDrawing; +import mtr.data.IGui; +import mtr.data.RailwayData; +import mtr.data.Station; +import mtr.mappings.BlockEntityRendererMapper; +import mtr.mappings.Text; +import mtr.mappings.UtilitiesClient; +import mtr.render.RenderTrains; +import mtr.render.StoredMatrixTransformations; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import ziyue.tjmetro.block.BlockStationNameEntranceTianjin; +import ziyue.tjmetro.block.BlockStationNamePlate; +import ziyue.tjmetro.client.ClientCache; + +import static ziyue.tjmetro.block.BlockStationNamePlate.POS; + +/** + * @author ZiYueCommentary + * @see mtr.render.RenderStationNameTiled + * @see BlockStationNameEntranceTianjin + * @since beta-1 + */ + +public class RenderStationNamePlate extends BlockEntityRendererMapper implements IGui, IDrawing +{ + public RenderStationNamePlate(BlockEntityRenderDispatcher dispatcher) { + super(dispatcher); + } + + @Override + public void render(T entity, float tickDelta, PoseStack matrices, MultiBufferSource vertexConsumers, int light, int overlay) { + final BlockGetter world = entity.getLevel(); + if (world == null) return; + + + final BlockPos pos = entity.getBlockPos(); + final BlockState state = world.getBlockState(pos); + final Direction facing = IBlock.getStatePropertySafe(state, BlockStationNameBase.FACING); + + final StoredMatrixTransformations storedMatrixTransformations = new StoredMatrixTransformations(); + storedMatrixTransformations.add(matricesNew -> { + matricesNew.translate(0.5 + entity.getBlockPos().getX(), 0.5 + entity.yOffset + entity.getBlockPos().getY(), 0.5 + entity.getBlockPos().getZ()); + UtilitiesClient.rotateYDegrees(matricesNew, -facing.toYRot()); + UtilitiesClient.rotateZDegrees(matricesNew, 180); + }); + + final Station station = RailwayData.getStation(ClientData.STATIONS, ClientData.DATA_CACHE, pos); + final StoredMatrixTransformations storedMatrixTransformations2 = storedMatrixTransformations.copy(); + storedMatrixTransformations2.add(matricesNew -> matricesNew.translate(0, 0, 0.5 - entity.zOffset - SMALL_OFFSET)); + + final int lengthLeft = entity.getBlockState().getValue(POS); + final int propagateProperty = IBlock.getStatePropertySafe(world, pos, BlockStationNameEntranceTianjin.STYLE); + final float logoSize = 0.5F; + + final ClientCache.DynamicResource resource = ClientCache.DATA_CACHE.getStationNameEntrance(station.id, entity.getSelectedId(), propagateProperty, IGui.insertTranslation("gui.mtr.station_cjk", "gui.mtr.station", 1, station.name), false, 4); + + RenderTrains.scheduleRender(resource.resourceLocation, false, RenderTrains.QueuedRenderLayer.INTERIOR, (poseStack, vertexConsumer) -> { + storedMatrixTransformations2.transform(poseStack); + IDrawing.drawTexture(poseStack, vertexConsumer, -0.5F, -logoSize / 2, 1, logoSize, (float) (lengthLeft - 1) / 4, 0, (float) lengthLeft / 4, 1, facing, ARGB_WHITE, light); + poseStack.popPose(); + }); + } +} diff --git a/common/src/main/resources/assets/tjmetro/blockstates/station_name_plate.json b/common/src/main/resources/assets/tjmetro/blockstates/station_name_plate.json new file mode 100644 index 0000000..68d038c --- /dev/null +++ b/common/src/main/resources/assets/tjmetro/blockstates/station_name_plate.json @@ -0,0 +1,20 @@ +{ + "variants": { + "facing=north,pos=0": { "model": "mtr:block/railway_sign_end_one_and_a_half" }, + "facing=east,pos=0": { "model": "mtr:block/railway_sign_end_one_and_a_half", "y": 90 }, + "facing=south,pos=0": { "model": "mtr:block/railway_sign_end_one_and_a_half", "y": 180 }, + "facing=west,pos=0": { "model": "mtr:block/railway_sign_end_one_and_a_half", "y": 270 }, + "facing=north,pos=1": { "model": "mtr:block/railway_sign_middle" }, + "facing=east,pos=1": { "model": "mtr:block/railway_sign_middle", "y": 90 }, + "facing=south,pos=1": { "model": "mtr:block/railway_sign_middle", "y": 180 }, + "facing=west,pos=1": { "model": "mtr:block/railway_sign_middle", "y": 270 }, + "facing=north,pos=2": { "model": "mtr:block/railway_sign_middle" }, + "facing=east,pos=2": { "model": "mtr:block/railway_sign_middle", "y": 90 }, + "facing=south,pos=2": { "model": "mtr:block/railway_sign_middle", "y": 180 }, + "facing=west,pos=2": { "model": "mtr:block/railway_sign_middle", "y": 270 }, + "facing=north,pos=3": { "model": "mtr:block/railway_sign_end_one_and_a_half", "y": 180 }, + "facing=east,pos=3": { "model": "mtr:block/railway_sign_end_one_and_a_half", "y": 270 }, + "facing=south,pos=3": { "model": "mtr:block/railway_sign_end_one_and_a_half" }, + "facing=west,pos=3": { "model": "mtr:block/railway_sign_end_one_and_a_half", "y": 90 } + } +} \ No newline at end of file diff --git a/common/src/main/resources/assets/tjmetro/textures/block/logo_stroke.png b/common/src/main/resources/assets/tjmetro/textures/block/logo_stroke.png new file mode 100644 index 0000000..3e60853 Binary files /dev/null and b/common/src/main/resources/assets/tjmetro/textures/block/logo_stroke.png differ diff --git a/icons/nursery.svg b/icons/nursery.svg new file mode 100644 index 0000000..0ea933e --- /dev/null +++ b/icons/nursery.svg @@ -0,0 +1,29 @@ + + + + + + + + diff --git a/icons/tianjin_metro_logo_stroke.svg b/icons/tianjin_metro_logo_stroke.svg new file mode 100644 index 0000000..b62031d --- /dev/null +++ b/icons/tianjin_metro_logo_stroke.svg @@ -0,0 +1,15 @@ + + + + + + + + + + +