diff --git a/assets/mods/basegame/books/btex.xml b/assets/mods/basegame/books/btex.xml index 18989fcdf..bc18f1809 100644 --- a/assets/mods/basegame/books/btex.xml +++ b/assets/mods/basegame/books/btex.xml @@ -169,12 +169,12 @@ <img src="http(s) or file URL" height="8"/>
<img fromgame="basegame:gui/small.png" height="4"/>
<img gameitem="basegame:33" height="1"/> + --><img fromgame="basegame:gui/small.png" height="4"/>

The height attribute specifies the height of the image in the number of lines, - rather than pixels, the width is calculated automatically. Image width wider than the text width will cause an error.

+ rather than pixels, the width is calculated automatically; image width wider than the text width + will cause an error. The tag optionally takes caption attribute which prints a text below the image.

Supported image formats: JPEG, PNG, BMP or TGA

@@ -304,7 +304,9 @@ system is there because the book is being printed in the background on separate threads (yes, they are multi-threaded!) to not interfere with the normal gameplay, or else the players will encounter the freezing every time the book is being printed, and this would be a huge minus towards - the gameplay experience. If the process exits without any error, the mailing system will be + the gameplay experience.

+ +

If the process exits without any error, the mailing system will be notified and will send the mail containing finished books to the player; if the process exits with errors, the mail containing details of the errors will be sent instead.

diff --git a/assets/mods/basegame/books/btex_ko.xml b/assets/mods/basegame/books/btex_ko.xml index 967be8ba4..a1dff909e 100644 --- a/assets/mods/basegame/books/btex_ko.xml +++ b/assets/mods/basegame/books/btex_ko.xml @@ -142,7 +142,7 @@
  • left — 문단을 좌측정렬함
  • right — 문단을 우측정렬함
  • center — 문단을 중앙정렬함
  • -
  • justify — 문단을 양끝정렬함. 기본값
  • +
  • justify — 문단을 양쪽정렬함. 기본값
  • p, span, callout 태그는 추가로 class="code" 속성을 지원한다. 이 속성이 적용된 문구는 코드꼴(code font)을 사용하여 인자된다.

    @@ -162,11 +162,10 @@ <img src="http(s)나 file URL" height="8"/>
    <img fromgame="basegame:gui/small.png" height="4"/>
    <img gameitem="basegame:33" height="1"/> + --><img fromgame="basegame:gui/small.png" height="4"/>
    -

    height 속성은 이미지의 높이를 픽셀 단위가 아닌 줄의 개수로 지정하어야 한다. 이미지의 너비는 자동으로 계산된다. 텍스트의 너비보다 넓다면 오류가 발생한다.

    +

    height 속성은 이미지의 높이를 픽셀 단위가 아닌 줄의 개수로 지정하어야 한다. 이미지의 너비는 자동으로 계산되며, 텍스트의 너비보다 넓다면 오류가 발생한다. 이미지 하단에 문구를 출력하려면 caption 속성을 사용할 수 있다.

    지원하는 이미지 포맷: JPEG·PNG·BMP·TGA

    @@ -268,8 +267,15 @@ -->[koKR] 원고가 담긴 홀로테이프를 출판사로 우편을 통해 보내야 책이 인쇄됩니다. + 일반인 출입금지 + 왜 책이 인쇄될 때까지 기다려야 하나요? 인쇄기를 직접 사용할 수는 없나요? +

    엔진은 빠른 물건이 아니다. 책을 하나 조판하려면 최소 몇 초가 필요하다. “대기 시스템”은 별도의 스레드 풀에서 (멀티스레딩으로 작동함) 책이 인쇄되도록 하여 게임플레이를 방해하지 않도록 도입되었다. 이것이 없다면 책이 한번 인쇄될 때마다 게임이 ‘응답 없음’ 상태가 될 것이고, 이는 인게임 경험에 매우 부정적으로 작용한다.

    + +

    인쇄 프로세스가 오류 없이 종료되었다면, 우편 시스템을 통해 플레이어에게 완성된 책을 배송한다. 오류가 있다면 오류 정보를 담은 우편이 대신 배송된다.

    + +

    상기와 같은 이유로 “인쇄기”는 플레이어에게 직접적으로 제공되지 않고, “출판사”와 우편을 통해 간접적으로 이용하는 형태로 제공된다.

    diff --git a/btexdoc.dtd b/btexdoc.dtd index 5ff3ee26b..21f946d33 100644 --- a/btexdoc.dtd +++ b/btexdoc.dtd @@ -48,6 +48,7 @@ "src CDATA #IMPLIED fromgame CDATA #IMPLIED gameitem CDATA #IMPLIED + caption %Text; #IMPLIED height %Number; #REQUIRED"> FileOutputStream(tempFile.file()).use { fileOutputStream -> val dataBuffer = ByteArray(1024) @@ -954,39 +960,47 @@ object BTeXParser { } Pixmap(tempFile).also { App.disposables.add(it) } } - - val imgWidth = (imgHeight.toFloat() / inputPixmap.height * inputPixmap.width).roundToInt() - - if (imgWidth > doc.textWidth) - throw RuntimeException("Image width ($imgWidth) is larger than the text width (${doc.textWidth})") - - val drawCallObj = { parentText: BTeXDrawCall -> object : BTeXBatchDrawCall(imgWidth, (heightInLines - 1).coerceAtLeast(0), parentText) { - private lateinit var inputTexture: Texture - override fun draw(doc: BTeXDocument, batch: SpriteBatch, x: Float, y: Float, font: TerrarumSansBitmap?) { - if (!::inputTexture.isInitialized) { - inputTexture = Texture(inputPixmap).also { App.disposables.add(it) } - } - val destX = (x + (doc.pageDimensionWidth - imgWidth) / 2) - val destY = y + 1 - batch.draw(inputTexture, destX, destY, imgWidth.toFloat(), imgHeight.toFloat()) - } - override fun drawToPixmap(doc: BTeXDocument, pixmap: Pixmap, x: Int, y: Int, font: TerrarumSansBitmap?) { - val destX = x - val destY = y + 1 - pixmap.drawPixmap(inputPixmap, 0, 0, inputPixmap.width, inputPixmap.height, destX, destY, imgWidth, imgHeight) - } - } } - - objDict[btexObjName] = { text: BTeXDrawCall -> drawCallObj(text) } - objWidthDict[btexObjName] = imgWidth - - typesetParagraphs(objectMarkerWithWidth(btexObjName, imgWidth), handler, align = "center") } - catch (e: IOException) { } - catch (e: GdxRuntimeException) { } - finally { - tempFile.delete() + else if (fromgame != null) { + val moduleName = fromgame.substringBefore(':') + val modulePath = fromgame.substringAfter(':') + Pixmap(ModMgr.getGdxFile(moduleName, modulePath)) } + else throw InternalError() + + val imgWidth = (imgHeight.toFloat() / inputPixmap.height * inputPixmap.width).roundToInt() + + if (imgWidth > doc.textWidth) + throw RuntimeException("Image width ($imgWidth) is larger than the text width (${doc.textWidth})") + + val drawCallObj = { parentText: BTeXDrawCall -> object : BTeXBatchDrawCall(imgWidth, (heightInLines - 1).coerceAtLeast(0), parentText) { + private lateinit var inputTexture: Texture + override fun draw(doc: BTeXDocument, batch: SpriteBatch, x: Float, y: Float, font: TerrarumSansBitmap?) { + if (!::inputTexture.isInitialized) { + inputTexture = Texture(inputPixmap).also { App.disposables.add(it) } + } + val destX = (x + (doc.pageDimensionWidth - imgWidth) / 2) + val destY = y + 1 + batch.draw(inputTexture, destX, destY, imgWidth.toFloat(), imgHeight.toFloat()) + } + override fun drawToPixmap(doc: BTeXDocument, pixmap: Pixmap, x: Int, y: Int, font: TerrarumSansBitmap?) { + val destX = x + val destY = y + 1 + pixmap.drawPixmap(inputPixmap, 0, 0, inputPixmap.width, inputPixmap.height, destX, destY, imgWidth, imgHeight) + } + } } + + objDict[btexObjName] = { text: BTeXDrawCall -> drawCallObj(text) } + objWidthDict[btexObjName] = imgWidth + + typesetParagraphs(objectMarkerWithWidth(btexObjName, imgWidth), handler, align = "center") + if (caption != null) + typesetParagraphs("$ccDefault$caption", handler, align = "center") + } + catch (e: IOException) { } + catch (e: GdxRuntimeException) { } + finally { + tempFile.delete() } } @@ -1697,7 +1711,7 @@ object BTeXParser { val dotGap = 10 val dotPosEnd = typeWidth - pageNumWidth - dotGap*1.5f - typesetParagraphs("$ccDefault$heading$name", handler, typeWidth, startingPage = pageToWrite ?: doc.currentPage, align = "justify").let { + typesetParagraphs("$ccDefault$heading$name", handler, typeWidth - pageNumWidth - dotGap, startingPage = pageToWrite ?: doc.currentPage, align = "justify").let { it.forEach { it.posX += indentation diff --git a/src/net/torvald/terrarum/tests/BTeXTest.kt b/src/net/torvald/terrarum/tests/BTeXTest.kt index 4bdfdb6a3..5534b533f 100644 --- a/src/net/torvald/terrarum/tests/BTeXTest.kt +++ b/src/net/torvald/terrarum/tests/BTeXTest.kt @@ -27,11 +27,11 @@ import kotlin.system.measureTimeMillis class BTeXTest : ApplicationAdapter() { // val filePath = "btex.xml" -// val filePath = "btex_ko.xml" - val filePath = "test.xml" + val filePath = "btex_ko.xml" +// val filePath = "test.xml" // val filePath = "literature/en/daniel_defoe_robinson_crusoe.xml" // val filePath = "literature/ruRU/anton_chekhov_palata_no_6.xml" -// val filePath = "literature/koKR/yisang_nalgae.btxbook" +// val filePath = "literature/koKR/yisang_nalgae.xml" private lateinit var document: BTeXDocument